"""Rudimentary support for loading MutatorMath .designspace files.""" from __future__ import print_function, division, absolute_import import collections from fontTools.misc.py23 import * try: import xml.etree.cElementTree as ET except ImportError: import xml.etree.ElementTree as ET __all__ = ['load', 'loads'] namespaces = {'xml': '{http://www.w3.org/XML/1998/namespace}'} def _xmlParseLocation(et): loc = {} for dim in et.find('location'): assert dim.tag == 'dimension' name = dim.attrib['name'] value = float(dim.attrib['xvalue']) assert name not in loc loc[name] = value return loc def _loadItem(et): item = dict(et.attrib) for elt in et: if elt.tag == 'location': value = _xmlParseLocation(et) else: value = {} if 'copy' in elt.attrib: value['copy'] = bool(int(elt.attrib['copy'])) # TODO load more?! item[elt.tag] = value return item def _xmlParseAxisOrMap(elt): dic = {} for name in elt.attrib: if name in ['name', 'tag']: dic[name] = elt.attrib[name] else: dic[name] = float(elt.attrib[name]) return dic def _loadAxis(et): item = dict(_xmlParseAxisOrMap(et)) maps = [] labelnames = {} for elt in et: assert elt.tag in ['labelname', 'map'] if elt.tag == 'labelname': lang = elt.attrib["{0}lang".format(namespaces['xml'])] labelnames[lang] = elt.text elif elt.tag == 'map': maps.append(_xmlParseAxisOrMap(elt)) if labelnames: item['labelname'] = labelnames if maps: item['map'] = maps return item def _load(et): designspace = {} ds = et.getroot() axes_element = ds.find('axes') if axes_element is not None: axes = [] for et in axes_element: axes.append(_loadAxis(et)) designspace['axes'] = axes sources_element = ds.find('sources') if sources_element is not None: sources = [] for et in sources_element: sources.append(_loadItem(et)) # XXX: why don't we call it 'sources'? designspace['masters'] = sources instances_element = ds.find('instances') if instances_element is not None: instances = [] for et in instances_element: instances.append(_loadItem(et)) designspace['instances'] = instances return designspace def load(filename): """Load designspace from a file name or object. Returns a dictionary containing three items: - list of axes - list of masters (aka sources) - list of instances""" return _load(ET.parse(filename)) def loads(string): """Load designspace from a string.""" return _load(ET.fromstring(string))