def test_normalise1(): # normalisation of anisotropic locations, clipping doc = DesignSpaceDocument() # write some axes a1 = AxisDescriptor() a1.minimum = -1000 a1.maximum = 1000 a1.default = 0 a1.name = "axisName_a" a1.tag = "TAGA" doc.addAxis(a1) assert doc.normalizeLocation(dict(axisName_a=0)) == {'axisName_a': 0.0} assert doc.normalizeLocation(dict(axisName_a=1000)) == {'axisName_a': 1.0} # clipping beyond max values: assert doc.normalizeLocation(dict(axisName_a=1001)) == {'axisName_a': 1.0} assert doc.normalizeLocation(dict(axisName_a=500)) == {'axisName_a': 0.5} assert doc.normalizeLocation(dict(axisName_a=-1000)) == {'axisName_a': -1.0} assert doc.normalizeLocation(dict(axisName_a=-1001)) == {'axisName_a': -1.0} # anisotropic coordinates normalise to isotropic assert doc.normalizeLocation(dict(axisName_a=(1000, -1000))) == {'axisName_a': 1.0} doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.minimum, axis.default, axis.maximum)) r.sort() assert r == [('axisName_a', -1.0, 0.0, 1.0)]
def test_normalise2(): # normalisation with minimum > 0 doc = DesignSpaceDocument() # write some axes a2 = AxisDescriptor() a2.minimum = 100 a2.maximum = 1000 a2.default = 100 a2.name = "axisName_b" doc.addAxis(a2) assert doc.normalizeLocation(dict(axisName_b=0)) == {'axisName_b': 0.0} assert doc.normalizeLocation(dict(axisName_b=1000)) == {'axisName_b': 1.0} # clipping beyond max values: assert doc.normalizeLocation(dict(axisName_b=1001)) == {'axisName_b': 1.0} assert doc.normalizeLocation(dict(axisName_b=500)) == {'axisName_b': 0.4444444444444444} assert doc.normalizeLocation(dict(axisName_b=-1000)) == {'axisName_b': 0.0} assert doc.normalizeLocation(dict(axisName_b=-1001)) == {'axisName_b': 0.0} # anisotropic coordinates normalise to isotropic assert doc.normalizeLocation(dict(axisName_b=(1000,-1000))) == {'axisName_b': 1.0} assert doc.normalizeLocation(dict(axisName_b=1001)) == {'axisName_b': 1.0} doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.minimum, axis.default, axis.maximum)) r.sort() assert r == [('axisName_b', 0.0, 0.0, 1.0)]
def main(args): from fontTools import configLogger args = args[1:] # TODO: allow user to configure logging via command-line options configLogger(level="INFO") if len(args) < 1: print("usage: fonttools varLib.models source.designspace", file=sys.stderr) print(" or") print("usage: fonttools varLib.models location1 location2 ...", file=sys.stderr) sys.exit(1) from pprint import pprint if len(args) == 1 and args[0].endswith('.designspace'): from fontTools.designspaceLib import DesignSpaceDocument doc = DesignSpaceDocument() doc.read(args[0]) locs = [s.location for s in doc.sources] print("Original locations:") pprint(locs) doc.normalize() print("Normalized locations:") pprint(locs) else: axes = [chr(c) for c in range(ord('A'), ord('Z')+1)] locs = [dict(zip(axes, (float(v) for v in s.split(',')))) for s in args] model = VariationModel(locs) print("Sorted locations:") pprint(model.locations) print("Supports:") pprint(model.supports)
def test_rulesDocument(tmpdir): # tests of rules in a document, roundtripping. tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "testRules.designspace") testDocPath2 = os.path.join(tmpdir, "testRules_roundtrip.designspace") doc = DesignSpaceDocument() a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 a1.name = "axisName_a" a1.tag = "TAGA" b1 = AxisDescriptor() b1.minimum = 2000 b1.maximum = 3000 b1.default = 2000 b1.name = "axisName_b" b1.tag = "TAGB" doc.addAxis(a1) doc.addAxis(b1) r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=0, maximum=1000), dict(name='axisName_b', minimum=0, maximum=3000) ]) r1.subs.append(("a", "a.alt")) # rule with minium and maximum doc.addRule(r1) assert len(doc.rules) == 1 assert len(doc.rules[0].conditionSets) == 1 assert len(doc.rules[0].conditionSets[0]) == 2 assert _axesAsDict(doc.axes) == {'axisName_a': {'map': [], 'name': 'axisName_a', 'default': 0, 'minimum': 0, 'maximum': 1000, 'tag': 'TAGA'}, 'axisName_b': {'map': [], 'name': 'axisName_b', 'default': 2000, 'minimum': 2000, 'maximum': 3000, 'tag': 'TAGB'}} assert doc.rules[0].conditionSets == [[ {'minimum': 0, 'maximum': 1000, 'name': 'axisName_a'}, {'minimum': 0, 'maximum': 3000, 'name': 'axisName_b'}]] assert doc.rules[0].subs == [('a', 'a.alt')] doc.normalize() assert doc.rules[0].name == 'named.rule.1' assert doc.rules[0].conditionSets == [[ {'minimum': 0.0, 'maximum': 1.0, 'name': 'axisName_a'}, {'minimum': 0.0, 'maximum': 1.0, 'name': 'axisName_b'}]] # still one conditionset assert len(doc.rules[0].conditionSets) == 1 doc.write(testDocPath) # add a stray conditionset _addUnwrappedCondition(testDocPath) doc2 = DesignSpaceDocument() doc2.read(testDocPath) assert len(doc2.axes) == 2 assert len(doc2.rules) == 1 assert len(doc2.rules[0].conditionSets) == 2 doc2.write(testDocPath2) # verify these results # make sure the stray condition is now neatly wrapped in a conditionset. doc3 = DesignSpaceDocument() doc3.read(testDocPath2) assert len(doc3.rules) == 1 assert len(doc3.rules[0].conditionSets) == 2
def main(args=None): """Normalize locations on a given designspace""" from fontTools import configLogger import argparse parser = argparse.ArgumentParser( "fonttools varLib.models", description=main.__doc__, ) parser.add_argument( "--loglevel", metavar="LEVEL", default="INFO", help="Logging level (defaults to INFO)", ) group = parser.add_mutually_exclusive_group(required=True) group.add_argument("-d", "--designspace", metavar="DESIGNSPACE", type=str) group.add_argument( "-l", "--locations", metavar="LOCATION", nargs="+", help= "Master locations as comma-separate coordinates. One must be all zeros.", ) args = parser.parse_args(args) configLogger(level=args.loglevel) from pprint import pprint if args.designspace: from fontTools.designspaceLib import DesignSpaceDocument doc = DesignSpaceDocument() doc.read(args.designspace) locs = [s.location for s in doc.sources] print("Original locations:") pprint(locs) doc.normalize() print("Normalized locations:") locs = [s.location for s in doc.sources] pprint(locs) else: axes = [chr(c) for c in range(ord("A"), ord("Z") + 1)] locs = [ dict(zip(axes, (float(v) for v in s.split(",")))) for s in args.locations ] model = VariationModel(locs) print("Sorted locations:") pprint(model.locations) print("Supports:") pprint(model.supports)
def test_normalise4(): # normalisation with a map doc = DesignSpaceDocument() # write some axes a4 = AxisDescriptor() a4.minimum = 0 a4.maximum = 1000 a4.default = 0 a4.name = "ddd" a4.map = [(0,100), (300, 500), (600, 500), (1000,900)] doc.addAxis(a4) doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.map)) r.sort() assert r == [('ddd', [(0, 0.0), (300, 0.5), (600, 0.5), (1000, 1.0)])]
def test_normalise4(): # normalisation with a map doc = DesignSpaceDocument() # write some axes a4 = AxisDescriptor() a4.minimum = 0 a4.maximum = 1000 a4.default = 0 a4.name = "ddd" a4.map = [(0,100), (300, 500), (600, 500), (1000,900)] doc.addAxis(a4) doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.map)) r.sort() assert r == [('ddd', [(0, 0.1), (300, 0.5), (600, 0.5), (1000, 0.9)])]
def test_axisMapping(): # note: because designspance lib does not do any actual # processing of the mapping data, we can only check if there data is there. doc = DesignSpaceDocument() # write some axes a4 = AxisDescriptor() a4.minimum = 0 a4.maximum = 1000 a4.default = 0 a4.name = "ddd" a4.map = [(0,100), (300, 500), (600, 500), (1000,900)] doc.addAxis(a4) doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.map)) r.sort() assert r == [('ddd', [(0, 0.0), (300, 0.5), (600, 0.5), (1000, 1.0)])]
def test_axisMapping(): # note: because designspance lib does not do any actual # processing of the mapping data, we can only check if there data is there. doc = DesignSpaceDocument() # write some axes a4 = AxisDescriptor() a4.minimum = 0 a4.maximum = 1000 a4.default = 0 a4.name = "ddd" a4.map = [(0,100), (300, 500), (600, 500), (1000,900)] doc.addAxis(a4) doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.map)) r.sort() assert r == [('ddd', [(0, 0.1), (300, 0.5), (600, 0.5), (1000, 0.9)])]
def test_normalise3(): # normalisation of negative values, with default == maximum doc = DesignSpaceDocument() # write some axes a3 = AxisDescriptor() a3.minimum = -1000 a3.maximum = 0 a3.default = 0 a3.name = "ccc" doc.addAxis(a3) assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0} assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0} assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': -1.0} assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': -1.0} doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.minimum, axis.default, axis.maximum)) r.sort() assert r == [('ccc', -1.0, 0.0, 0.0)]
def test_rules(tmpdir): tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "testRules.designspace") testDocPath2 = os.path.join(tmpdir, "testRules_roundtrip.designspace") doc = DesignSpaceDocument() # write some axes a1 = AxisDescriptor() a1.tag = "taga" a1.name = "aaaa" a1.minimum = 0 a1.maximum = 1000 a1.default = 0 doc.addAxis(a1) a2 = AxisDescriptor() a2.tag = "tagb" a2.name = "bbbb" a2.minimum = 0 a2.maximum = 3000 a2.default = 0 doc.addAxis(a2) r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditions.append(dict(name='aaaa', minimum=0, maximum=1000)) r1.conditions.append(dict(name='bbbb', minimum=0, maximum=3000)) r1.subs.append(("a", "a.alt")) # rule with minium and maximum doc.addRule(r1) assert len(doc.rules) == 1 assert len(doc.rules[0].conditions) == 2 assert evaluateRule(r1, dict(aaaa=500, bbbb=0)) == True assert evaluateRule(r1, dict(aaaa=0, bbbb=0)) == True assert evaluateRule(r1, dict(aaaa=1000, bbbb=0)) == True assert evaluateRule(r1, dict(aaaa=1000, bbbb=-100)) == False assert evaluateRule(r1, dict(aaaa=1000.0001, bbbb=0)) == False assert evaluateRule(r1, dict(aaaa=-0.0001, bbbb=0)) == False assert evaluateRule(r1, dict(aaaa=-100, bbbb=0)) == False assert processRules([r1], dict(aaaa=500), ["a", "b", "c"]) == ['a.alt', 'b', 'c'] assert processRules([r1], dict(aaaa=500), ["a.alt", "b", "c"]) == ['a.alt', 'b', 'c'] assert processRules([r1], dict(aaaa=2000), ["a", "b", "c"]) == ['a', 'b', 'c'] # rule with only a maximum r2 = RuleDescriptor() r2.name = "named.rule.2" r2.conditions.append(dict(name='aaaa', maximum=500)) r2.subs.append(("b", "b.alt")) assert evaluateRule(r2, dict(aaaa=0)) == True assert evaluateRule(r2, dict(aaaa=-500)) == True assert evaluateRule(r2, dict(aaaa=1000)) == False # rule with only a minimum r3 = RuleDescriptor() r3.name = "named.rule.3" r3.conditions.append(dict(name='aaaa', minimum=500)) r3.subs.append(("c", "c.alt")) assert evaluateRule(r3, dict(aaaa=0)) == False assert evaluateRule(r3, dict(aaaa=1000)) == True assert evaluateRule(r3, dict(bbbb=1000)) == True # rule with only a minimum, maximum in separate conditions r4 = RuleDescriptor() r4.name = "named.rule.4" r4.conditions.append(dict(name='aaaa', minimum=500)) r4.conditions.append(dict(name='bbbb', maximum=500)) r4.subs.append(("c", "c.alt")) assert evaluateRule(r4, dict()) == True # is this what we expect though? assert evaluateRule(r4, dict(aaaa=1000, bbbb=0)) == True assert evaluateRule(r4, dict(aaaa=0, bbbb=0)) == False assert evaluateRule(r4, dict(aaaa=1000, bbbb=1000)) == False a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 a1.name = "aaaa" a1.tag = "aaaa" b1 = AxisDescriptor() b1.minimum = 2000 b1.maximum = 3000 b1.default = 2000 b1.name = "bbbb" b1.tag = "bbbb" doc.addAxis(a1) doc.addAxis(b1) assert doc._prepAxesForBender() == { 'aaaa': { 'map': [], 'name': 'aaaa', 'default': 0, 'minimum': 0, 'maximum': 1000, 'tag': 'aaaa' }, 'bbbb': { 'map': [], 'name': 'bbbb', 'default': 2000, 'minimum': 2000, 'maximum': 3000, 'tag': 'bbbb' } } assert doc.rules[0].conditions == [{ 'minimum': 0, 'maximum': 1000, 'name': 'aaaa' }, { 'minimum': 0, 'maximum': 3000, 'name': 'bbbb' }] assert doc.rules[0].subs == [('a', 'a.alt')] doc.normalize() assert doc.rules[0].name == 'named.rule.1' assert doc.rules[0].conditions == [{ 'minimum': 0.0, 'maximum': 1.0, 'name': 'aaaa' }, { 'minimum': 0.0, 'maximum': 1.0, 'name': 'bbbb' }] doc.write(testDocPath) new = DesignSpaceDocument() new.read(testDocPath) assert len(new.axes) == 4 assert len(new.rules) == 1 new.write(testDocPath2)
def test_normalise(): doc = DesignSpaceDocument() # write some axes a1 = AxisDescriptor() a1.minimum = -1000 a1.maximum = 1000 a1.default = 0 a1.name = "aaa" a1.tag = "aaaa" doc.addAxis(a1) assert doc.normalizeLocation(dict(aaa=0)) == {'aaa': 0.0} assert doc.normalizeLocation(dict(aaa=1000)) == {'aaa': 1.0} # clipping beyond max values: assert doc.normalizeLocation(dict(aaa=1001)) == {'aaa': 1.0} assert doc.normalizeLocation(dict(aaa=500)) == {'aaa': 0.5} assert doc.normalizeLocation(dict(aaa=-1000)) == {'aaa': -1.0} assert doc.normalizeLocation(dict(aaa=-1001)) == {'aaa': -1.0} # anisotropic coordinates normalise to isotropic assert doc.normalizeLocation(dict(aaa=(1000, -1000))) == {'aaa': 1.0} doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.minimum, axis.default, axis.maximum)) r.sort() assert r == [('aaa', -1.0, 0.0, 1.0)] doc = DesignSpaceDocument() # write some axes a2 = AxisDescriptor() a2.minimum = 100 a2.maximum = 1000 a2.default = 100 a2.name = "bbb" doc.addAxis(a2) assert doc.normalizeLocation(dict(bbb=0)) == {'bbb': 0.0} assert doc.normalizeLocation(dict(bbb=1000)) == {'bbb': 1.0} # clipping beyond max values: assert doc.normalizeLocation(dict(bbb=1001)) == {'bbb': 1.0} assert doc.normalizeLocation(dict(bbb=500)) == {'bbb': 0.4444444444444444} assert doc.normalizeLocation(dict(bbb=-1000)) == {'bbb': 0.0} assert doc.normalizeLocation(dict(bbb=-1001)) == {'bbb': 0.0} # anisotropic coordinates normalise to isotropic assert doc.normalizeLocation(dict(bbb=(1000, -1000))) == {'bbb': 1.0} assert doc.normalizeLocation(dict(bbb=1001)) == {'bbb': 1.0} doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.minimum, axis.default, axis.maximum)) r.sort() assert r == [('bbb', 0.0, 0.0, 1.0)] doc = DesignSpaceDocument() # write some axes a3 = AxisDescriptor() a3.minimum = -1000 a3.maximum = 0 a3.default = 0 a3.name = "ccc" doc.addAxis(a3) assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0} assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0} assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': -1.0} assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': -1.0} doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.minimum, axis.default, axis.maximum)) r.sort() assert r == [('ccc', -1.0, 0.0, 0.0)] doc = DesignSpaceDocument() # write some axes a3 = AxisDescriptor() a3.minimum = 2000 a3.maximum = 3000 a3.default = 2000 a3.name = "ccc" doc.addAxis(a3) assert doc.normalizeLocation(dict(ccc=0)) == {'ccc': 0.0} assert doc.normalizeLocation(dict(ccc=1)) == {'ccc': 0.0} assert doc.normalizeLocation(dict(ccc=-1000)) == {'ccc': 0.0} assert doc.normalizeLocation(dict(ccc=-1001)) == {'ccc': 0.0} doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.minimum, axis.default, axis.maximum)) r.sort() assert r == [('ccc', 0.0, 0.0, 1.0)] doc = DesignSpaceDocument() # write some axes a4 = AxisDescriptor() a4.minimum = 0 a4.maximum = 1000 a4.default = 0 a4.name = "ddd" a4.map = [(0, 100), (300, 500), (600, 500), (1000, 900)] doc.addAxis(a4) doc.normalize() r = [] for axis in doc.axes: r.append((axis.name, axis.map)) r.sort() assert r == [('ddd', [(0, 0.1), (300, 0.5), (600, 0.5), (1000, 0.9)])]