def main(args=None): from fontTools import configLogger if args is None: args = sys.argv[1:] # configure the library logger (for >= WARNING) configLogger() # comment this out to enable debug messages from logger # log.setLevel(logging.DEBUG) if len(args) < 1: print("usage: fonttools varLib.plot source.designspace", file=sys.stderr) print(" or") print("usage: fonttools varLib.plot location1 location2 ...", file=sys.stderr) sys.exit(1) fig = pyplot.figure() if len(args) == 1 and args[0].endswith('.designspace'): doc = DesignSpaceDocument() doc.read(args[0]) plotDocument(doc, fig) 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] plotLocationsSurfaces(locs, fig) pyplot.show()
def assertUFORoundtrip(self, font): self._normalize(font) expected = write_to_lines(font) # Don't propagate anchors when intending to round-trip designspace = to_designspace( font, propagate_anchors=False, minimize_glyphs_diffs=True) # Check that round-tripping in memory is the same as writing on disk roundtrip_in_mem = to_glyphs(designspace) self._normalize(roundtrip_in_mem) actual_in_mem = write_to_lines(roundtrip_in_mem) directory = tempfile.mkdtemp() path = os.path.join(directory, font.familyName + '.designspace') write_designspace_and_UFOs(designspace, path) designspace_roundtrip = DesignSpaceDocument() designspace_roundtrip.read(path) roundtrip = to_glyphs(designspace_roundtrip) self._normalize(roundtrip) actual = write_to_lines(roundtrip) with open('expected.txt', 'w') as f: f.write('\n'.join(expected)) with open('actual_in_mem.txt', 'w') as f: f.write('\n'.join(actual_in_mem)) with open('actual.txt', 'w') as f: f.write('\n'.join(actual)) self.assertLinesEqual( actual_in_mem, actual, "The round-trip in memory or written to disk should be equivalent") self.assertLinesEqual( expected, actual, "The font should not be modified by the roundtrip")
def test_read_with_path_object(): import pathlib source = (pathlib.Path(__file__) / "../data/test_v4_original.designspace").resolve() assert source.exists() doc = DesignSpaceDocument() doc.read(source)
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 getDesignspace(masterfont, *fontsToAdd): dsList = [] slaveAxes = [] localLocation = list() neutralLocation = dict() testLocation = list() masterAxes = list() trad = {"Weight": "wght", "Width" : "wdth"} path, folder = getFile(".designspace", masterfont) masterDesignSpace = DesignSpaceDocument() masterDesignSpace.read(path) # read masterdesignspace of each fonts to merge into master family, # and put it in a list for f in fontsToAdd: path = getFile(".designspace", f)[0] designSpace = DesignSpaceDocument() designSpace.read(path) dsList.append(designSpace) # FIND COMMON NAME AXIS IN MASTER AND SLAVE FAMILIES for ds in dsList: for a in ds.axes: slaveAxes.append(a.tag) neutralLocation[a.tag] = a.default for a in masterDesignSpace.axes: if a.tag in slaveAxes: masterAxes.append(a.tag) return masterDesignSpace, dsList, slaveAxes, masterAxes, neutralLocation
def test_designspace_source_locations(tmpdir): """Check that opening UFOs from their source descriptor works with both the filename and the path attributes. """ designspace_path = os.path.join(str(tmpdir), 'test.designspace') light_ufo_path = os.path.join(str(tmpdir), 'light.ufo') bold_ufo_path = os.path.join(str(tmpdir), 'bold.ufo') designspace = DesignSpaceDocument() light_source = designspace.newSourceDescriptor() light_source.filename = 'light.ufo' designspace.addSource(light_source) bold_source = designspace.newSourceDescriptor() bold_source.path = bold_ufo_path designspace.addSource(bold_source) designspace.write(designspace_path) light = defcon.Font() light.info.ascender = 30 light.save(light_ufo_path) bold = defcon.Font() bold.info.ascender = 40 bold.save(bold_ufo_path) designspace = DesignSpaceDocument() designspace.read(designspace_path) font = to_glyphs(designspace) assert len(font.masters) == 2 assert font.masters[0].ascender == 30 assert font.masters[1].ascender == 40
def main(args=None): from fontTools import configLogger if args is None: args = sys.argv[1:] # configure the library logger (for >= WARNING) configLogger() # comment this out to enable debug messages from logger # log.setLevel(logging.DEBUG) if len(args) < 1: print("usage: fonttools varLib.plot source.designspace", file=sys.stderr) print(" or") print("usage: fonttools varLib.plot location1 location2 ...", file=sys.stderr) sys.exit(1) fig = pyplot.figure() fig.set_tight_layout(True) if len(args) == 1 and args[0].endswith('.designspace'): doc = DesignSpaceDocument() doc.read(args[0]) plotDocument(doc, fig) 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 ] plotLocations(locs, fig) pyplot.show()
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 test_unicodes(tmpdir): tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "testUnicodes.designspace") testDocPath2 = os.path.join(tmpdir, "testUnicodes_roundtrip.designspace") masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") doc = DesignSpaceDocument() # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) s1.name = "master.ufo1" s1.copyInfo = True s1.location = dict(weight=0) doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s2.name = "master.ufo2" s2.location = dict(weight=1000) doc.addSource(s2) # add instance 1 i1 = InstanceDescriptor() i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath)) i1.name = "instance.ufo1" i1.location = dict(weight=500) glyphData = dict(name="arrow", mute=True, unicodes=[100, 200, 300]) i1.glyphs['arrow'] = glyphData doc.addInstance(i1) # now we have sources and instances, but no axes yet. doc.axes = [] # clear the axes # write some axes a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 a1.name = "weight" a1.tag = "wght" doc.addAxis(a1) # write the document doc.write(testDocPath) assert os.path.exists(testDocPath) # import it again new = DesignSpaceDocument() new.read(testDocPath) new.write(testDocPath2) # compare the file contents f1 = open(testDocPath, 'r', encoding='utf-8') t1 = f1.read() f1.close() f2 = open(testDocPath2, 'r', encoding='utf-8') t2 = f2.read() f2.close() assert t1 == t2 # check the unicode values read from the document assert new.instances[0].glyphs['arrow']['unicodes'] == [100, 200, 300]
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 apply_instance_data(designspace_path, include_filenames=None, Font=defcon.Font): """Open UFO instances referenced by designspace, apply Glyphs instance data if present, re-save UFOs and return updated UFO Font objects. Args: designspace_path: path to a designspace file. include_filenames: optional set of instance filenames (relative to the designspace path) to be included. By default all instaces are processed. Font: the class used to load the UFO (default: defcon.Font). Returns: List of opened and updated instance UFOs. """ from fontTools.designspaceLib import DesignSpaceDocument from os.path import normcase, normpath # in fontmake <= 1.4.0 using the old glyphsLib.build_masters API, the # apply_instance_data function is passed an InstanceData object, instead # of a path to a designspace file. We try to stay compatible so one can # update glyphsLib without needing to also update fontmake. # TODO: Drop this sometime in the next releases. if isinstance(designspace_path, InstanceData): designspace = designspace_path.designspace designspace_path = designspace.path else: designspace = DesignSpaceDocument() designspace.read(designspace_path) basedir = os.path.dirname(designspace_path) instance_ufos = [] if include_filenames is not None: include_filenames = {normcase(normpath(p)) for p in include_filenames} for designspace_instance in designspace.instances: fname = designspace_instance.filename assert fname is not None, ( "instance %r missing required filename" % getattr(designspace_instance, "name", designspace_instance)) if include_filenames is not None: fname = normcase(normpath(fname)) if fname not in include_filenames: continue logger.debug("Appling instance data to %s", fname) # fontmake <= 1.4.0 compares the ufo paths returned from this function # to the keys of a dict of designspace locations that have been passed # through normpath (but not normcase). We do the same. ufo = Font(normpath(os.path.join(basedir, fname))) set_weight_class(ufo, designspace, designspace_instance) set_width_class(ufo, designspace, designspace_instance) glyphs_instance = InstanceDescriptorAsGSInstance(designspace_instance) to_ufo_custom_params(None, ufo, glyphs_instance) ufo.save() instance_ufos.append(ufo) return instance_ufos
def test_unicodes(tmpdir): tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "testUnicodes.designspace") testDocPath2 = os.path.join(tmpdir, "testUnicodes_roundtrip.designspace") masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") doc = DesignSpaceDocument() # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) s1.name = "master.ufo1" s1.copyInfo = True s1.location = dict(weight=0) doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s2.name = "master.ufo2" s2.location = dict(weight=1000) doc.addSource(s2) # add instance 1 i1 = InstanceDescriptor() i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath)) i1.name = "instance.ufo1" i1.location = dict(weight=500) glyphData = dict(name="arrow", mute=True, unicodes=[100, 200, 300]) i1.glyphs['arrow'] = glyphData doc.addInstance(i1) # now we have sources and instances, but no axes yet. doc.axes = [] # clear the axes # write some axes a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 a1.name = "weight" a1.tag = "wght" doc.addAxis(a1) # write the document doc.write(testDocPath) assert os.path.exists(testDocPath) # import it again new = DesignSpaceDocument() new.read(testDocPath) new.write(testDocPath2) # compare the file contents with open(testDocPath, 'r', encoding='utf-8') as f1: t1 = f1.read() with open(testDocPath2, 'r', encoding='utf-8') as f2: t2 = f2.read() assert t1 == t2 # check the unicode values read from the document assert new.instances[0].glyphs['arrow']['unicodes'] == [100,200,300]
def doit(args): if args.glyphsfile is None: (path, base, ext) = splitfn(args.designspace) args.glyphsfile = os.path.join(path, base + ".glyphs") logger = args.logger logger.log("Opening designSpace file", "I") ds = DesignSpaceDocument() ds.read(args.designspace) glyphsfont = to_glyphs(ds) logger.log("Writing glyphs file", "I") glyphsfont.save(args.glyphsfile)
def doit(args): if args.glyphsfile is None: (path, base, ext) = splitfn(args.designspace) args.glyphsfile = os.path.join(path, base + ".glyphs") logger = args.logger logger.log("Opening designSpace file", "I") ds = DesignSpaceDocument() ds.read(args.designspace) logger.log("Now creating glyphs object", "I") glyphsfont = to_glyphs( ds, minimize_ufo_diffs=not (args.no_preserve_glyphsapp_metadata)) logger.log("Writing glyphs file", "I") glyphsfont.save(args.glyphsfile)
def main(): root = os.path.join(os.getcwd(), "build") if os.path.exists(root): shutil.rmtree(root) # Copy files from src/masters, as we need to edit them ignore = shutil.ignore_patterns( ".git", ".git*", "*designspaces*", "recursive-mono*.designspace", "recursive-sans*.designspace", "*varfontprep*", ) shutil.copytree("../src/masters", os.path.join(root, "src"), ignore=ignore) src = os.path.join(root, "src", "recursive-MONO_XPRN_wght_slnt_ital.designspace") static_root = os.path.join(root, "static") var_root = os.path.join(root, "var") doc = DesignSpaceDocument() doc.read(src) # Fix default value for weight axis in design space file #for axis in doc.axes: # if axis.name == "Weight": # axis.default = 300 # Still in memory, but need to save for other operations doc.write(src) # Make STAT table #makeSTAT(src, doc) # Sort glyph order # Variable font build #print("Building Variable fonts") # Fix default va # fontmake -m $DS -o variable --output-path $outputDir/$fontName--$date.ttf # Static font build print("Building Static fonts") buildFolders(doc, static_root) buildFontMenuDB(doc, static_root) buildInstances(src, static_root)
def doit(args): glyphsfile = args.glyphsfile if glyphsfile is None: (path,base,ext) = splitfn(args.designspace) glyphsfile = os.path.join(path, base + ".glyphs" ) logger = args.logger logger.log("Opening designSpace file", "I") ds = DesignSpaceDocument() ds.read(args.designspace) logger.log("Now creating glyphs object", "I") glyphsfont = to_glyphs(ds, minimize_ufo_diffs=not(args.no_preserve_glyphsapp_metadata)) if os.path.exists(glyphsfile): # Delete file first so any xattr are not preserved - eg com.schriftgestalt.UIStore logger.log("Deleting existing glyphs file: " + glyphsfile, "I") os.remove(glyphsfile) logger.log("Writing glyphs file: " + glyphsfile, "I") glyphsfont.save(glyphsfile)
def test_designspace_lib_equivalent_to_font_user_data(tmpdir): designspace = DesignSpaceDocument() designspace.lib['designspaceLibKey1'] = 'designspaceLibValue1' # Save to disk and reload the designspace to test the write/read of lib path = os.path.join(str(tmpdir), 'test.designspace') designspace.write(path) designspace = DesignSpaceDocument() designspace.read(path) font = to_glyphs(designspace) assert font.userData['designspaceLibKey1'] == 'designspaceLibValue1' designspace = to_designspace(font) assert designspace.lib['designspaceLibKey1'] == 'designspaceLibValue1'
def test_apply_instance_data(tmpdir, instance_names, ufo_module): font = glyphsLib.GSFont(os.path.join(DATA, "GlyphsUnitTestSans.glyphs")) instance_dir = "instances" designspace = glyphsLib.to_designspace(font, instance_dir=instance_dir) path = str(tmpdir / (font.familyName + ".designspace")) write_designspace_and_UFOs(designspace, path) test_designspace = DesignSpaceDocument() test_designspace.read(designspace.path) if instance_names is None: # Collect all instances. test_instances = [instance.filename for instance in test_designspace.instances] else: # Collect only selected instances. test_instances = [ instance.filename for instance in test_designspace.instances if instance.styleName in instance_names ] # Generate dummy UFOs for collected instances so we don't actually need to # interpolate. tmpdir.mkdir(instance_dir) for instance in test_instances: ufo = ufo_module.Font() ufo.save(str(tmpdir / instance)) ufos = apply_instance_data(designspace.path, include_filenames=test_instances) for filename in test_instances: assert os.path.isdir(str(tmpdir / filename)) assert len(ufos) == len(test_instances) for ufo in ufos: assert ufo.info.openTypeOS2WeightClass in { 100, 200, 300, 400, 500, 700, 900, 357, } assert ufo.info.openTypeOS2WidthClass is None # GlyphsUnitTestSans is wght only
def test_incompleteRule(tmpdir): tmpdir = str(tmpdir) testDocPath1 = os.path.join(tmpdir, "testIncompleteRule.designspace") doc = DesignSpaceDocument() r1 = RuleDescriptor() r1.name = "incomplete.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=100), dict(name='axisName_b', maximum=200) ]) r1.subs.append(("c", "c.alt")) doc.addRule(r1) doc.write(testDocPath1) __removeConditionMinimumMaximumDesignSpace(testDocPath1) new = DesignSpaceDocument() with pytest.raises(DesignSpaceDocumentError) as excinfo: new.read(testDocPath1) assert "No minimum or maximum defined in rule" in str(excinfo.value)
def selectDesignspaceCallback(self, sender): selection = sender.getSelection() designSpaces = self.designspaces.list.get() # delete current list posSize = self.sources.list.getPosSize() del self.sources.list # list of sources is empty if not selection or not len(designSpaces): items = [] self.sources.list = List(posSize, []) return # get sources from selected designspace designSpaceLabel = [D for i, D in enumerate(designSpaces) if i in selection][0] designSpacePath = self._designspaces[designSpaceLabel] designSpace = DesignSpaceDocument() designSpace.read(designSpacePath) # get column descriptions titles = ['name'] titles += [axis.name for axis in designSpace.axes] descriptions = [{"title": D} for D in titles] # make list items self._sources = {} items = [] for source in designSpace.sources: sourceName = os.path.splitext(os.path.split(source.path)[-1])[0] self._sources[sourceName] = source.path item = { 'name' : sourceName } for axis in designSpace.axes: item[axis.name] = source.location[axis.name] items.append(item) # create list UI with items self.sources.list = List( posSize, items, columnDescriptions=descriptions, allowsMultipleSelection=True, enableDelete=False)
def test_adjustAxisDefaultToNeutral(tmpdir): tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "testAdjustAxisDefaultToNeutral.designspace") masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") doc = DesignSpaceDocument() # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) s1.name = "master.ufo1" s1.copyInfo = True s1.copyFeatures = True s1.location = dict(weight=55, width=1000) doc.addSource(s1) # write some axes a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 # the wrong value a1.name = "weight" a1.tag = "wght" doc.addAxis(a1) a2 = AxisDescriptor() a2.minimum = -10 a2.maximum = 10 a2.default = 0 # the wrong value a2.name = "width" a2.tag = "wdth" doc.addAxis(a2) # write the document doc.write(testDocPath) assert os.path.exists(testDocPath) # import it again new = DesignSpaceDocument() new.read(testDocPath) new.check() loc = new.default.location for axisObj in new.axes: n = axisObj.name assert axisObj.default == loc.get(n)
def test_designspace_source_locations(tmpdir, ufo_module): """Check that opening UFOs from their source descriptor works with both the filename and the path attributes. """ designspace_path = os.path.join(str(tmpdir), "test.designspace") light_ufo_path = os.path.join(str(tmpdir), "light.ufo") bold_ufo_path = os.path.join(str(tmpdir), "bold.ufo") designspace = DesignSpaceDocument() wght = AxisDescriptor() wght.minimum = 100 wght.maximum = 700 wght.default = 100 wght.name = "Weight" wght.tag = "wght" designspace.addAxis(wght) light_source = designspace.newSourceDescriptor() light_source.filename = "light.ufo" light_source.location = {"Weight": 100} designspace.addSource(light_source) bold_source = designspace.newSourceDescriptor() bold_source.path = bold_ufo_path bold_source.location = {"Weight": 700} designspace.addSource(bold_source) designspace.write(designspace_path) light = ufo_module.Font() light.info.ascender = 30 light.save(light_ufo_path) bold = ufo_module.Font() bold.info.ascender = 40 bold.save(bold_ufo_path) designspace = DesignSpaceDocument() designspace.read(designspace_path) font = to_glyphs(designspace, ufo_module=ufo_module) assert len(font.masters) == 2 assert font.masters[0].ascender == 30 assert font.masters[1].ascender == 40
def test_documentLib(tmpdir): # roundtrip test of the document lib with some nested data tmpdir = str(tmpdir) testDocPath1 = os.path.join(tmpdir, "testDocumentLibTest.designspace") doc = DesignSpaceDocument() a1 = AxisDescriptor() a1.tag = "TAGA" a1.name = "axisName_a" a1.minimum = 0 a1.maximum = 1000 a1.default = 0 doc.addAxis(a1) dummyData = dict(a=123, b=u"äbc", c=[1,2,3], d={'a':123}) dummyKey = "org.fontTools.designspaceLib" doc.lib = {dummyKey: dummyData} doc.write(testDocPath1) new = DesignSpaceDocument() new.read(testDocPath1) assert dummyKey in new.lib assert new.lib[dummyKey] == dummyData
def carpenter(designSpaceFile): headerString = "" columnSetup = "| :------- |" tableString = "" doc = DesignSpaceDocument() doc.read(designSpaceFile) doc.axes doc.sources doc.instances for axisNames in doc.axes: headerString += " " + axisNames.name + " |" tableHeading = instanceNameString + headerString for additionalColumns in range(len(doc.axes)): columnSetup += " -------: |" for instances in doc.instances: valueString = "| " for axisLocationValue in instances.location.values(): valueString += str(axisLocationValue) + " |" finalString = instances.styleName + "" + valueString + "\n" tableString += finalString finalTable = tableHeading + "\n" + columnSetup + "\n" + tableString return finalTable
def main(): parser = argparse.ArgumentParser(description="Build Reem Kufi fonts.") parser.add_argument("file", metavar="FILE", help="input font to process") parser.add_argument("--out-file", metavar="FILE", help="output font to write", required=True) args = parser.parse_args() with TemporaryDirectory() as tempdir: ufos, designspace = build_masters(args.file, tempdir, tempdir) doc = DesignSpaceDocument() doc.read(designspace) doc.instances = [i for i in doc.instances if i.styleName == "Regular"] assert len(doc.instances) == 1 instance = doc.instances[0] instance.location = dict(Weight=108) instance.path = args.out_file doc.write(designspace) build(designspace, outputUFOFormatVersion=3)
def test_fill_document(tmpdir): tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "test.designspace") masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") doc = DesignSpaceDocument() # write some axes a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 a1.name = "weight" a1.tag = "wght" # note: just to test the element language, not an actual label name recommendations. a1.labelNames[u'fa-IR'] = u"قطر" a1.labelNames[u'en'] = u"Wéíght" doc.addAxis(a1) a2 = AxisDescriptor() a2.minimum = 0 a2.maximum = 1000 a2.default = 15 a2.name = "width" a2.tag = "wdth" a2.map = [(0.0, 10.0), (15.0, 20.0), (401.0, 66.0), (1000.0, 990.0)] a2.hidden = True a2.labelNames[u'fr'] = u"Chasse" doc.addAxis(a2) # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) assert s1.font is None s1.name = "master.ufo1" s1.copyLib = True s1.copyInfo = True s1.copyFeatures = True s1.location = dict(weight=0) s1.familyName = "MasterFamilyName" s1.styleName = "MasterStyleNameOne" s1.mutedGlyphNames.append("A") s1.mutedGlyphNames.append("Z") doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s2.name = "master.ufo2" s2.copyLib = False s2.copyInfo = False s2.copyFeatures = False s2.muteKerning = True s2.location = dict(weight=1000) s2.familyName = "MasterFamilyName" s2.styleName = "MasterStyleNameTwo" doc.addSource(s2) # add master 3 from a different layer s3 = SourceDescriptor() s3.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s3.name = "master.ufo2" s3.copyLib = False s3.copyInfo = False s3.copyFeatures = False s3.muteKerning = False s3.layerName = "supports" s3.location = dict(weight=1000) s3.familyName = "MasterFamilyName" s3.styleName = "Supports" doc.addSource(s3) # add instance 1 i1 = InstanceDescriptor() i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath)) i1.familyName = "InstanceFamilyName" i1.styleName = "InstanceStyleName" i1.name = "instance.ufo1" i1.location = dict(weight=500, spooky=666) # this adds a dimension that is not defined. i1.postScriptFontName = "InstancePostscriptName" i1.styleMapFamilyName = "InstanceStyleMapFamilyName" i1.styleMapStyleName = "InstanceStyleMapStyleName" glyphData = dict(name="arrow", mute=True, unicodes=[0x123, 0x124, 0x125]) i1.glyphs['arrow'] = glyphData i1.lib['com.coolDesignspaceApp.binaryData'] = plistlib.Data(b'<binary gunk>') i1.lib['com.coolDesignspaceApp.specimenText'] = "Hamburgerwhatever" doc.addInstance(i1) # add instance 2 i2 = InstanceDescriptor() i2.filename = os.path.relpath(instancePath2, os.path.dirname(testDocPath)) i2.familyName = "InstanceFamilyName" i2.styleName = "InstanceStyleName" i2.name = "instance.ufo2" # anisotropic location i2.location = dict(weight=500, width=(400,300)) i2.postScriptFontName = "InstancePostscriptName" i2.styleMapFamilyName = "InstanceStyleMapFamilyName" i2.styleMapStyleName = "InstanceStyleMapStyleName" glyphMasters = [dict(font="master.ufo1", glyphName="BB", location=dict(width=20,weight=20)), dict(font="master.ufo2", glyphName="CC", location=dict(width=900,weight=900))] glyphData = dict(name="arrow", unicodes=[101, 201, 301]) glyphData['masters'] = glyphMasters glyphData['note'] = "A note about this glyph" glyphData['instanceLocation'] = dict(width=100, weight=120) i2.glyphs['arrow'] = glyphData i2.glyphs['arrow2'] = dict(mute=False) doc.addInstance(i2) doc.filename = "suggestedFileName.designspace" doc.lib['com.coolDesignspaceApp.previewSize'] = 30 # write some rules r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=0, maximum=1), dict(name='axisName_b', minimum=2, maximum=3) ]) r1.subs.append(("a", "a.alt")) doc.addRule(r1) # write the document doc.write(testDocPath) assert os.path.exists(testDocPath) assert_equals_test_file(testDocPath, 'data/test.designspace') # import it again new = DesignSpaceDocument() new.read(testDocPath) assert new.default.location == {'width': 20.0, 'weight': 0.0} assert new.filename == 'test.designspace' assert new.lib == doc.lib assert new.instances[0].lib == doc.instances[0].lib # test roundtrip for the axis attributes and data axes = {} for axis in doc.axes: if axis.tag not in axes: axes[axis.tag] = [] axes[axis.tag].append(axis.serialize()) for axis in new.axes: if axis.tag[0] == "_": continue if axis.tag not in axes: axes[axis.tag] = [] axes[axis.tag].append(axis.serialize()) for v in axes.values(): a, b = v assert a == b
def test_pathNameResolve(tmpdir): tmpdir = str(tmpdir) # test how descriptor.path and descriptor.filename are resolved testDocPath1 = os.path.join(tmpdir, "testPathName_case1.designspace") testDocPath2 = os.path.join(tmpdir, "testPathName_case2.designspace") testDocPath3 = os.path.join(tmpdir, "testPathName_case3.designspace") testDocPath4 = os.path.join(tmpdir, "testPathName_case4.designspace") testDocPath5 = os.path.join(tmpdir, "testPathName_case5.designspace") testDocPath6 = os.path.join(tmpdir, "testPathName_case6.designspace") masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") a1 = AxisDescriptor() a1.tag = "TAGA" a1.name = "axisName_a" a1.minimum = 0 a1.maximum = 1000 a1.default = 0 # Case 1: filename and path are both empty. Nothing to calculate, nothing to put in the file. doc = DesignSpaceDocument() doc.addAxis(a1) s = SourceDescriptor() s.filename = None s.path = None s.copyInfo = True s.location = dict(weight=0) s.familyName = "MasterFamilyName" s.styleName = "MasterStyleNameOne" doc.addSource(s) doc.write(testDocPath1) verify = DesignSpaceDocument() verify.read(testDocPath1) assert verify.sources[0].filename == None assert verify.sources[0].path == None # Case 2: filename is empty, path points somewhere: calculate a new filename. doc = DesignSpaceDocument() doc.addAxis(a1) s = SourceDescriptor() s.filename = None s.path = masterPath1 s.copyInfo = True s.location = dict(weight=0) s.familyName = "MasterFamilyName" s.styleName = "MasterStyleNameOne" doc.addSource(s) doc.write(testDocPath2) verify = DesignSpaceDocument() verify.read(testDocPath2) assert verify.sources[0].filename == "masters/masterTest1.ufo" assert verify.sources[0].path == posix(masterPath1) # Case 3: the filename is set, the path is None. doc = DesignSpaceDocument() doc.addAxis(a1) s = SourceDescriptor() s.filename = "../somewhere/over/the/rainbow.ufo" s.path = None s.copyInfo = True s.location = dict(weight=0) s.familyName = "MasterFamilyName" s.styleName = "MasterStyleNameOne" doc.addSource(s) doc.write(testDocPath3) verify = DesignSpaceDocument() verify.read(testDocPath3) assert verify.sources[0].filename == "../somewhere/over/the/rainbow.ufo" # make the absolute path for filename so we can see if it matches the path p = os.path.abspath(os.path.join(os.path.dirname(testDocPath3), verify.sources[0].filename)) assert verify.sources[0].path == posix(p) # Case 4: the filename points to one file, the path points to another. The path takes precedence. doc = DesignSpaceDocument() doc.addAxis(a1) s = SourceDescriptor() s.filename = "../somewhere/over/the/rainbow.ufo" s.path = masterPath1 s.copyInfo = True s.location = dict(weight=0) s.familyName = "MasterFamilyName" s.styleName = "MasterStyleNameOne" doc.addSource(s) doc.write(testDocPath4) verify = DesignSpaceDocument() verify.read(testDocPath4) assert verify.sources[0].filename == "masters/masterTest1.ufo" # Case 5: the filename is None, path has a value, update the filename doc = DesignSpaceDocument() doc.addAxis(a1) s = SourceDescriptor() s.filename = None s.path = masterPath1 s.copyInfo = True s.location = dict(weight=0) s.familyName = "MasterFamilyName" s.styleName = "MasterStyleNameOne" doc.addSource(s) doc.write(testDocPath5) # so that the document has a path doc.updateFilenameFromPath() assert doc.sources[0].filename == "masters/masterTest1.ufo" # Case 6: the filename has a value, path has a value, update the filenames with force doc = DesignSpaceDocument() doc.addAxis(a1) s = SourceDescriptor() s.filename = "../somewhere/over/the/rainbow.ufo" s.path = masterPath1 s.copyInfo = True s.location = dict(weight=0) s.familyName = "MasterFamilyName" s.styleName = "MasterStyleNameOne" doc.write(testDocPath5) # so that the document has a path doc.addSource(s) assert doc.sources[0].filename == "../somewhere/over/the/rainbow.ufo" doc.updateFilenameFromPath(force=True) assert doc.sources[0].filename == "masters/masterTest1.ufo"
def test_handleNoAxes(tmpdir): tmpdir = str(tmpdir) # test what happens if the designspacedocument has no axes element. testDocPath = os.path.join(tmpdir, "testNoAxes_source.designspace") testDocPath2 = os.path.join(tmpdir, "testNoAxes_recontructed.designspace") masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") # Case 1: No axes element in the document, but there are sources and instances doc = DesignSpaceDocument() for name, value in [('One', 1),('Two', 2),('Three', 3)]: a = AxisDescriptor() a.minimum = 0 a.maximum = 1000 a.default = 0 a.name = "axisName%s" % (name) a.tag = "ax_%d" % (value) doc.addAxis(a) # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) s1.name = "master.ufo1" s1.copyLib = True s1.copyInfo = True s1.copyFeatures = True s1.location = dict(axisNameOne=-1000, axisNameTwo=0, axisNameThree=1000) s1.familyName = "MasterFamilyName" s1.styleName = "MasterStyleNameOne" doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s2.name = "master.ufo1" s2.copyLib = False s2.copyInfo = False s2.copyFeatures = False s2.location = dict(axisNameOne=1000, axisNameTwo=1000, axisNameThree=0) s2.familyName = "MasterFamilyName" s2.styleName = "MasterStyleNameTwo" doc.addSource(s2) # add instance 1 i1 = InstanceDescriptor() i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath)) i1.familyName = "InstanceFamilyName" i1.styleName = "InstanceStyleName" i1.name = "instance.ufo1" i1.location = dict(axisNameOne=(-1000,500), axisNameTwo=100) i1.postScriptFontName = "InstancePostscriptName" i1.styleMapFamilyName = "InstanceStyleMapFamilyName" i1.styleMapStyleName = "InstanceStyleMapStyleName" doc.addInstance(i1) doc.write(testDocPath) verify = DesignSpaceDocument() verify.read(testDocPath) verify.write(testDocPath2)
def test_localisedNames(tmpdir): tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "testLocalisedNames.designspace") testDocPath2 = os.path.join(tmpdir, "testLocalisedNames_roundtrip.designspace") masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") doc = DesignSpaceDocument() # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) s1.name = "master.ufo1" s1.copyInfo = True s1.location = dict(weight=0) doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s2.name = "master.ufo2" s2.location = dict(weight=1000) doc.addSource(s2) # add instance 1 i1 = InstanceDescriptor() i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath)) i1.familyName = "Montserrat" i1.styleName = "SemiBold" i1.styleMapFamilyName = "Montserrat SemiBold" i1.styleMapStyleName = "Regular" i1.setFamilyName("Montserrat", "fr") i1.setFamilyName(u"モンセラート", "ja") i1.setStyleName("Demigras", "fr") i1.setStyleName(u"半ば", "ja") i1.setStyleMapStyleName(u"Standard", "de") i1.setStyleMapFamilyName("Montserrat Halbfett", "de") i1.setStyleMapFamilyName(u"モンセラート SemiBold", "ja") i1.name = "instance.ufo1" i1.location = dict(weight=500, spooky=666) # this adds a dimension that is not defined. i1.postScriptFontName = "InstancePostscriptName" glyphData = dict(name="arrow", mute=True, unicodes=[0x123]) i1.glyphs['arrow'] = glyphData doc.addInstance(i1) # now we have sources and instances, but no axes yet. doc.axes = [] # clear the axes # write some axes a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 a1.name = "weight" a1.tag = "wght" # note: just to test the element language, not an actual label name recommendations. a1.labelNames[u'fa-IR'] = u"قطر" a1.labelNames[u'en'] = u"Wéíght" doc.addAxis(a1) a2 = AxisDescriptor() a2.minimum = 0 a2.maximum = 1000 a2.default = 0 a2.name = "width" a2.tag = "wdth" a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)] a2.labelNames[u'fr'] = u"Poids" doc.addAxis(a2) # add an axis that is not part of any location to see if that works a3 = AxisDescriptor() a3.minimum = 333 a3.maximum = 666 a3.default = 444 a3.name = "spooky" a3.tag = "spok" a3.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)] #doc.addAxis(a3) # uncomment this line to test the effects of default axes values # write some rules r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='weight', minimum=200, maximum=500), dict(name='width', minimum=0, maximum=150) ]) r1.subs.append(("a", "a.alt")) doc.addRule(r1) # write the document doc.write(testDocPath) assert os.path.exists(testDocPath) # import it again new = DesignSpaceDocument() new.read(testDocPath) new.write(testDocPath2) with open(testDocPath, 'r', encoding='utf-8') as f1: t1 = f1.read() with open(testDocPath2, 'r', encoding='utf-8') as f2: t2 = f2.read() assert t1 == t2
def test_fill_document(tmpdir): tmpdir = str(tmpdir) testDocPath = os.path.join(tmpdir, "test.designspace") masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") doc = DesignSpaceDocument() # write some axes a1 = AxisDescriptor() a1.minimum = 0 a1.maximum = 1000 a1.default = 0 a1.name = "weight" a1.tag = "wght" # note: just to test the element language, not an actual label name recommendations. a1.labelNames[u'fa-IR'] = u"قطر" a1.labelNames[u'en'] = u"Wéíght" doc.addAxis(a1) a2 = AxisDescriptor() a2.minimum = 0 a2.maximum = 1000 a2.default = 20 a2.name = "width" a2.tag = "wdth" a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)] a2.hidden = True a2.labelNames[u'fr'] = u"Chasse" doc.addAxis(a2) # add master 1 s1 = SourceDescriptor() s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath)) assert s1.font is None s1.name = "master.ufo1" s1.copyLib = True s1.copyInfo = True s1.copyFeatures = True s1.location = dict(weight=0) s1.familyName = "MasterFamilyName" s1.styleName = "MasterStyleNameOne" s1.mutedGlyphNames.append("A") s1.mutedGlyphNames.append("Z") doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s2.name = "master.ufo2" s2.copyLib = False s2.copyInfo = False s2.copyFeatures = False s2.muteKerning = True s2.location = dict(weight=1000) s2.familyName = "MasterFamilyName" s2.styleName = "MasterStyleNameTwo" doc.addSource(s2) # add master 3 from a different layer s3 = SourceDescriptor() s3.filename = os.path.relpath(masterPath2, os.path.dirname(testDocPath)) s3.name = "master.ufo2" s3.copyLib = False s3.copyInfo = False s3.copyFeatures = False s3.muteKerning = False s3.layerName = "supports" s3.location = dict(weight=1000) s3.familyName = "MasterFamilyName" s3.styleName = "Supports" doc.addSource(s3) # add instance 1 i1 = InstanceDescriptor() i1.filename = os.path.relpath(instancePath1, os.path.dirname(testDocPath)) i1.familyName = "InstanceFamilyName" i1.styleName = "InstanceStyleName" i1.name = "instance.ufo1" i1.location = dict(weight=500, spooky=666) # this adds a dimension that is not defined. i1.postScriptFontName = "InstancePostscriptName" i1.styleMapFamilyName = "InstanceStyleMapFamilyName" i1.styleMapStyleName = "InstanceStyleMapStyleName" glyphData = dict(name="arrow", mute=True, unicodes=[0x123, 0x124, 0x125]) i1.glyphs['arrow'] = glyphData i1.lib['com.coolDesignspaceApp.binaryData'] = plistlib.Data(b'<binary gunk>') i1.lib['com.coolDesignspaceApp.specimenText'] = "Hamburgerwhatever" doc.addInstance(i1) # add instance 2 i2 = InstanceDescriptor() i2.filename = os.path.relpath(instancePath2, os.path.dirname(testDocPath)) i2.familyName = "InstanceFamilyName" i2.styleName = "InstanceStyleName" i2.name = "instance.ufo2" # anisotropic location i2.location = dict(weight=500, width=(400,300)) i2.postScriptFontName = "InstancePostscriptName" i2.styleMapFamilyName = "InstanceStyleMapFamilyName" i2.styleMapStyleName = "InstanceStyleMapStyleName" glyphMasters = [dict(font="master.ufo1", glyphName="BB", location=dict(width=20,weight=20)), dict(font="master.ufo2", glyphName="CC", location=dict(width=900,weight=900))] glyphData = dict(name="arrow", unicodes=[101, 201, 301]) glyphData['masters'] = glyphMasters glyphData['note'] = "A note about this glyph" glyphData['instanceLocation'] = dict(width=100, weight=120) i2.glyphs['arrow'] = glyphData i2.glyphs['arrow2'] = dict(mute=False) doc.addInstance(i2) doc.filename = "suggestedFileName.designspace" doc.lib['com.coolDesignspaceApp.previewSize'] = 30 # write some rules r1 = RuleDescriptor() r1.name = "named.rule.1" r1.conditionSets.append([ dict(name='axisName_a', minimum=0, maximum=1), dict(name='axisName_b', minimum=2, maximum=3) ]) r1.subs.append(("a", "a.alt")) doc.addRule(r1) # write the document doc.write(testDocPath) assert os.path.exists(testDocPath) assert_equals_test_file(testDocPath, 'data/test.designspace') # import it again new = DesignSpaceDocument() new.read(testDocPath) assert new.default.location == {'width': 20.0, 'weight': 0.0} assert new.filename == 'test.designspace' assert new.lib == doc.lib assert new.instances[0].lib == doc.instances[0].lib # test roundtrip for the axis attributes and data axes = {} for axis in doc.axes: if axis.tag not in axes: axes[axis.tag] = [] axes[axis.tag].append(axis.serialize()) for axis in new.axes: if axis.tag[0] == "_": continue if axis.tag not in axes: axes[axis.tag] = [] axes[axis.tag].append(axis.serialize()) for v in axes.values(): a, b = v assert a == b
def test_read_with_path_object(): import pathlib source = (pathlib.Path(__file__) / "../data/test.designspace").resolve() assert source.exists() doc = DesignSpaceDocument() doc.read(source)
from fontTools.designspaceLib import DesignSpaceDocument from vanilla import * import inspect import defcon f = CurrentFont() thisGlyph = CurrentGlyph() doc = DesignSpaceDocument() doc.read("Crispy[SRIF,wdth,wght].designspace") referenceFileName = doc.sources[ 0].familyName #this assumed a well-made designspace file with correctly named font masters. coordinateslist = [] fontsList = doc.loadSourceFonts(defcon.Font) for i in range(len(fontsList)): nameTag = str(fontsList[i].info.styleName) for glyph in fontsList[i]: compatibilityCounter = 0 if glyph.name == thisGlyph.name: pointCount = 0 for contour in glyph: for segment in contour.segments: for points in segment: pointCount += 1 for refFonts in fontslist: compatible = glyph.isCompatible(refFont[glyph.name]) if compatible: compatibilityCounter += 1 print(compatibilityCounter)
def test_check(invalid_designspace, tmpdir): tmpdir = str(tmpdir) # check if the checks are checking testDocPath = os.path.join(tmpdir, invalid_designspace) masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo") masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo") instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo") instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo") # no default selected doc = DesignSpaceDocument() # add master 1 s1 = SourceDescriptor() s1.path = masterPath1 s1.name = "master.ufo1" s1.location = dict(snap=0, pop=10) s1.familyName = "MasterFamilyName" s1.styleName = "MasterStyleNameOne" doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.path = masterPath2 s2.name = "master.ufo2" s2.location = dict(snap=1000, pop=20) s2.familyName = "MasterFamilyName" s2.styleName = "MasterStyleNameTwo" doc.addSource(s2) doc.checkAxes() doc.getAxisOrder() == ['snap', 'pop'] assert doc.default == None doc.checkDefault() assert doc.default.name == 'master.ufo1' # default selected doc = DesignSpaceDocument() # add master 1 s1 = SourceDescriptor() s1.path = masterPath1 s1.name = "master.ufo1" s1.location = dict(snap=0, pop=10) s1.familyName = "MasterFamilyName" s1.styleName = "MasterStyleNameOne" doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.path = masterPath2 s2.name = "master.ufo2" s2.copyInfo = True s2.location = dict(snap=1000, pop=20) s2.familyName = "MasterFamilyName" s2.styleName = "MasterStyleNameTwo" doc.addSource(s2) doc.checkAxes() assert doc.getAxisOrder() == ['snap', 'pop'] assert doc.default == None doc.checkDefault() assert doc.default.name == 'master.ufo2' # generate a doc without axes, save and read again doc = DesignSpaceDocument() # add master 1 s1 = SourceDescriptor() s1.path = masterPath1 s1.name = "master.ufo1" s1.location = dict(snap=0, pop=10) s1.familyName = "MasterFamilyName" s1.styleName = "MasterStyleNameOne" doc.addSource(s1) # add master 2 s2 = SourceDescriptor() s2.path = masterPath2 s2.name = "master.ufo2" s2.location = dict(snap=1000, pop=20) s2.familyName = "MasterFamilyName" s2.styleName = "MasterStyleNameTwo" doc.addSource(s2) doc.checkAxes() doc.write(testDocPath) __removeAxesFromDesignSpace(testDocPath) new = DesignSpaceDocument() new.read(testDocPath) assert len(new.axes) == 2 new.checkAxes() assert len(new.axes) == 2 assert print([a.name for a in new.axes]) == ['snap', 'pop'] new.write(testDocPath)
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)