def test_compile_withoutPostScriptName(self): inst = NamedInstance() inst.subfamilyNameID = 345 inst.postscriptNameID = 564 inst.coordinates = {"wght": 0.7, "wdth": 0.5} self.assertEqual(FVAR_INSTANCE_DATA_WITHOUT_PSNAME, inst.compile(["wght", "wdth"], False))
def _add_fvar(font, axes, instances): """ Add 'fvar' table to font. axes is an ordered dictionary of DesignspaceAxis objects. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. """ assert axes assert isinstance(axes, OrderedDict) log.info("Generating fvar") fvar = newTable('fvar') nameTable = font['name'] for a in axes.values(): axis = Axis() axis.axisTag = Tag(a.tag) # TODO Skip axes that have no variation. axis.minValue, axis.defaultValue, axis.maxValue = a.minimum, a.default, a.maximum axis.axisNameID = nameTable.addMultilingualName(a.labelNames, font) axis.flags = int(a.hidden) fvar.axes.append(axis) for instance in instances: coordinates = instance.location if "en" not in instance.localisedStyleName: assert instance.styleName localisedStyleName = dict(instance.localisedStyleName) localisedStyleName["en"] = tounicode(instance.styleName) else: localisedStyleName = instance.localisedStyleName psname = instance.postScriptFontName inst = NamedInstance() inst.subfamilyNameID = nameTable.addMultilingualName( localisedStyleName) if psname is not None: psname = tounicode(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = { axes[k].tag: axes[k].map_backward(v) for k, v in coordinates.items() } #inst.coordinates = {axes[k].tag:v for k,v in coordinates.items()} fvar.instances.append(inst) assert "fvar" not in font font['fvar'] = fvar return fvar
def _add_fvar(font, axes, instances): """ Add 'fvar' table to font. axes is an ordered dictionary of DesignspaceAxis objects. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. """ assert axes assert isinstance(axes, OrderedDict) log.info("Generating fvar") fvar = newTable('fvar') nameTable = font['name'] for a in axes.values(): axis = Axis() axis.axisTag = Tag(a.tag) # TODO Skip axes that have no variation. axis.minValue, axis.defaultValue, axis.maxValue = a.minimum, a.default, a.maximum axis.axisNameID = nameTable.addName(tounicode(a.labelname['en'])) # TODO: # Replace previous line with the following when the following issues are resolved: # https://github.com/fonttools/fonttools/issues/930 # https://github.com/fonttools/fonttools/issues/931 # axis.axisNameID = nameTable.addMultilingualName(a.labelname, font) fvar.axes.append(axis) for instance in instances: coordinates = instance['location'] name = tounicode(instance['stylename']) psname = instance.get('postscriptfontname') inst = NamedInstance() inst.subfamilyNameID = nameTable.addName(name) if psname is not None: psname = tounicode(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = { axes[k].tag: axes[k].map_backward(v) for k, v in coordinates.items() } #inst.coordinates = {axes[k].tag:v for k,v in coordinates.items()} fvar.instances.append(inst) assert "fvar" not in font font['fvar'] = fvar return fvar
def _add_fvar(font, axes, instances): """ Add 'fvar' table to font. axes is an ordered dictionary of DesignspaceAxis objects. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. """ assert axes assert isinstance(axes, OrderedDict) log.info("Generating fvar") fvar = newTable('fvar') nameTable = font['name'] for a in axes.values(): axis = Axis() axis.axisTag = Tag(a.tag) # TODO Skip axes that have no variation. axis.minValue, axis.defaultValue, axis.maxValue = a.minimum, a.default, a.maximum axis.axisNameID = nameTable.addMultilingualName(a.labelNames, font) axis.flags = int(a.hidden) fvar.axes.append(axis) for instance in instances: coordinates = instance.location if "en" not in instance.localisedStyleName: assert instance.styleName localisedStyleName = dict(instance.localisedStyleName) localisedStyleName["en"] = tounicode(instance.styleName) else: localisedStyleName = instance.localisedStyleName psname = instance.postScriptFontName inst = NamedInstance() inst.subfamilyNameID = nameTable.addMultilingualName(localisedStyleName) if psname is not None: psname = tounicode(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = {axes[k].tag:axes[k].map_backward(v) for k,v in coordinates.items()} #inst.coordinates = {axes[k].tag:v for k,v in coordinates.items()} fvar.instances.append(inst) assert "fvar" not in font font['fvar'] = fvar return fvar
def _add_fvar(font, axes, instances): """ Add 'fvar' table to font. axes is an ordered dictionary of DesignspaceAxis objects. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. """ assert axes assert isinstance(axes, OrderedDict) log.info("Generating fvar") fvar = newTable('fvar') nameTable = font['name'] for a in axes.values(): axis = Axis() axis.axisTag = Tag(a.tag) # TODO Skip axes that have no variation. axis.minValue, axis.defaultValue, axis.maxValue = a.minimum, a.default, a.maximum axis.axisNameID = nameTable.addName(tounicode(a.labelNames['en'])) # TODO: # Replace previous line with the following when the following issues are resolved: # https://github.com/fonttools/fonttools/issues/930 # https://github.com/fonttools/fonttools/issues/931 # axis.axisNameID = nameTable.addMultilingualName(a.labelname, font) fvar.axes.append(axis) for instance in instances: coordinates = instance.location name = tounicode(instance.styleName) psname = instance.postScriptFontName inst = NamedInstance() inst.subfamilyNameID = nameTable.addName(name) if psname is not None: psname = tounicode(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = {axes[k].tag:axes[k].map_backward(v) for k,v in coordinates.items()} #inst.coordinates = {axes[k].tag:v for k,v in coordinates.items()} fvar.instances.append(inst) assert "fvar" not in font font['fvar'] = fvar return fvar
def test_toXML_withPostScriptName(self): font = MakeFont() inst = NamedInstance() inst.subfamilyNameID = AddName(font, "Light Condensed").nameID inst.postscriptNameID = AddName(font, "Test-LightCondensed").nameID inst.coordinates = {"wght": 0.7, "wdth": 0.5} writer = XMLWriter(BytesIO()) inst.toXML(writer, font) self.assertEqual([ '', '<!-- Light Condensed -->', '<!-- PostScript: Test-LightCondensed -->', '<NamedInstance postscriptNameID="%s" subfamilyNameID="%s">' % (inst.postscriptNameID, inst.subfamilyNameID), '<coord axis="wght" value="0.7"/>', '<coord axis="wdth" value="0.5"/>', '</NamedInstance>' ], xml_lines(writer))
def test_toXML_withPostScriptName(self): font = MakeFont() inst = NamedInstance() inst.subfamilyNameID = AddName(font, "Light Condensed").nameID inst.postscriptNameID = AddName(font, "Test-LightCondensed").nameID inst.coordinates = {"wght": 0.7, "wdth": 0.5} writer = XMLWriter(BytesIO()) inst.toXML(writer, font) self.assertEqual([ '', '<!-- Light Condensed -->', '<!-- PostScript: Test-LightCondensed -->', '<NamedInstance postscriptNameID="%s" subfamilyNameID="%s">' % ( inst.postscriptNameID, inst.subfamilyNameID), '<coord axis="wght" value="0.7"/>', '<coord axis="wdth" value="0.5"/>', '</NamedInstance>' ], xml_lines(writer))
def _add_fvar(font, axes, instances, axis_map): """ Add 'fvar' table to font. axes is a dictionary mapping axis-id to axis (min,default,max) coordinate values. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. axis_map is an ordered dictionary mapping axis-id to (axis-tag, axis-name). """ assert "fvar" not in font font['fvar'] = fvar = newTable('fvar') nameTable = font['name'] for iden in axis_map.keys(): if iden not in axes: continue axis = Axis() axis.axisTag = Tag(axis_map[iden][0]) axis.minValue, axis.defaultValue, axis.maxValue = axes[iden] axisName = tounicode(axis_map[iden][1]) axis.axisNameID = nameTable.addName(axisName) fvar.axes.append(axis) for instance in instances: coordinates = instance['location'] name = tounicode(instance['stylename']) psname = instance.get('postscriptfontname') inst = NamedInstance() inst.subfamilyNameID = nameTable.addName(name) if psname is not None: psname = tounicode(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = {axis_map[k][0]: v for k, v in coordinates.items()} fvar.instances.append(inst) return fvar
def _add_fvar(font, axes, instances, axis_map): """ Add 'fvar' table to font. axes is a dictionary mapping axis-id to axis (min,default,max) coordinate values. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. axisMap is dictionary mapping axis-id to (axis-tag, axis-name). """ assert "fvar" not in font font['fvar'] = fvar = newTable('fvar') nameTable = font['name'] for iden in sorted(axes.keys(), key=lambda k: axis_map[k][0]): axis = Axis() axis.axisTag = Tag(axis_map[iden][0]) axis.minValue, axis.defaultValue, axis.maxValue = axes[iden] axisName = tounicode(axis_map[iden][1]) axis.axisNameID = nameTable.addName(axisName) fvar.axes.append(axis) for instance in instances: coordinates = instance['location'] name = tounicode(instance['stylename']) psname = instance.get('postscriptfontname') inst = NamedInstance() inst.subfamilyNameID = nameTable.addName(name) if psname is not None: psname = tounicode(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = {axis_map[k][0]:v for k,v in coordinates.items()} fvar.instances.append(inst) return fvar
def _add_fvar_avar(font, axes, instances): """ Add 'fvar' table to font. axes is an ordered dictionary of DesignspaceAxis objects. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. """ assert axes assert isinstance(axes, OrderedDict) log.info("Generating fvar / avar") fvar = newTable('fvar') nameTable = font['name'] for a in axes.values(): axis = Axis() axis.axisTag = Tag(a.tag) axis.minValue, axis.defaultValue, axis.maxValue = a.minimum, a.default, a.maximum axis.axisNameID = nameTable.addName(tounicode(a.labelname['en'])) # TODO: # Replace previous line with the following when the following issues are resolved: # https://github.com/fonttools/fonttools/issues/930 # https://github.com/fonttools/fonttools/issues/931 # axis.axisNameID = nameTable.addMultilingualName(a.labelname, font) fvar.axes.append(axis) for instance in instances: coordinates = instance['location'] name = tounicode(instance['stylename']) psname = instance.get('postscriptfontname') inst = NamedInstance() inst.subfamilyNameID = nameTable.addName(name) if psname is not None: psname = tounicode(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = { axes[k].tag: axes[k].map_backward(v) for k, v in coordinates.items() } fvar.instances.append(inst) avar = newTable('avar') interesting = False for axis in axes.values(): curve = avar.segments[axis.tag] = {} if not axis.map or all(k == v for k, v in axis.map.items()): continue interesting = True items = sorted(axis.map.items()) keys = [item[0] for item in items] vals = [item[1] for item in items] # Current avar requirements. We don't have to enforce # these on the designer and can deduce some ourselves, # but for now just enforce them. assert axis.minimum == min(keys) assert axis.maximum == max(keys) assert axis.default in keys # No duplicates assert len(set(keys)) == len(keys) assert len(set(vals)) == len(vals) # Ascending values assert sorted(vals) == vals keys_triple = (axis.minimum, axis.default, axis.maximum) vals_triple = tuple(axis.map_forward(v) for v in keys_triple) keys = [models.normalizeValue(v, keys_triple) for v in keys] vals = [models.normalizeValue(v, vals_triple) for v in vals] curve.update(zip(keys, vals)) if not interesting: log.info("No need for avar") avar = None assert "fvar" not in font font['fvar'] = fvar assert "avar" not in font if avar: font['avar'] = avar return fvar, avar
def _add_fvar_avar(font, axes, instances): """ Add 'fvar' table to font. axes is an ordered dictionary of DesignspaceAxis objects. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. """ assert axes assert isinstance(axes, OrderedDict) log.info("Generating fvar / avar") fvar = newTable('fvar') nameTable = font['name'] for a in axes.values(): axis = Axis() axis.axisTag = Tag(a.tag) axis.minValue, axis.defaultValue, axis.maxValue = a.minimum, a.default, a.maximum axis.axisNameID = nameTable.addName(tounicode(a.labelname['en'])) # TODO: # Replace previous line with the following when the following issues are resolved: # https://github.com/fonttools/fonttools/issues/930 # https://github.com/fonttools/fonttools/issues/931 # axis.axisNameID = nameTable.addMultilingualName(a.labelname, font) fvar.axes.append(axis) for instance in instances: coordinates = instance['location'] name = tounicode(instance['stylename']) psname = instance.get('postscriptfontname') inst = NamedInstance() inst.subfamilyNameID = nameTable.addName(name) if psname is not None: psname = tounicode(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = {axes[k].tag:axes[k].map_backward(v) for k,v in coordinates.items()} fvar.instances.append(inst) avar = newTable('avar') interesting = False for axis in axes.values(): curve = avar.segments[axis.tag] = {} if not axis.map or all(k==v for k,v in axis.map.items()): continue interesting = True items = sorted(axis.map.items()) keys = [item[0] for item in items] vals = [item[1] for item in items] # Current avar requirements. We don't have to enforce # these on the designer and can deduce some ourselves, # but for now just enforce them. assert axis.minimum == min(keys) assert axis.maximum == max(keys) assert axis.default in keys # No duplicates assert len(set(keys)) == len(keys) assert len(set(vals)) == len(vals) # Ascending values assert sorted(vals) == vals keys_triple = (axis.minimum, axis.default, axis.maximum) vals_triple = tuple(axis.map_forward(v) for v in keys_triple) keys = [models.normalizeValue(v, keys_triple) for v in keys] vals = [models.normalizeValue(v, vals_triple) for v in vals] curve.update(zip(keys, vals)) if not interesting: log.info("No need for avar") avar = None assert "fvar" not in font font['fvar'] = fvar assert "avar" not in font if avar: font['avar'] = avar return fvar,avar
def _add_fvar(font, axes, instances: List[InstanceDescriptor]): """ Add 'fvar' table to font. axes is an ordered dictionary of DesignspaceAxis objects. instances is list of dictionary objects with 'location', 'stylename', and possibly 'postscriptfontname' entries. """ assert axes assert isinstance(axes, OrderedDict) log.info("Generating fvar") fvar = newTable('fvar') nameTable = font['name'] for a in axes.values(): axis = Axis() axis.axisTag = Tag(a.tag) # TODO Skip axes that have no variation. axis.minValue, axis.defaultValue, axis.maxValue = a.minimum, a.default, a.maximum axis.axisNameID = nameTable.addMultilingualName(a.labelNames, font, minNameID=256) axis.flags = int(a.hidden) fvar.axes.append(axis) for instance in instances: # Filter out discrete axis locations coordinates = { name: value for name, value in instance.location.items() if name in axes } if "en" not in instance.localisedStyleName: if not instance.styleName: raise VarLibValidationError( f"Instance at location '{coordinates}' must have a default English " "style name ('stylename' attribute on the instance element or a " "stylename element with an 'xml:lang=\"en\"' attribute).") localisedStyleName = dict(instance.localisedStyleName) localisedStyleName["en"] = tostr(instance.styleName) else: localisedStyleName = instance.localisedStyleName psname = instance.postScriptFontName inst = NamedInstance() inst.subfamilyNameID = nameTable.addMultilingualName( localisedStyleName) if psname is not None: psname = tostr(psname) inst.postscriptNameID = nameTable.addName(psname) inst.coordinates = { axes[k].tag: axes[k].map_backward(v) for k, v in coordinates.items() } #inst.coordinates = {axes[k].tag:v for k,v in coordinates.items()} fvar.instances.append(inst) assert "fvar" not in font font['fvar'] = fvar return fvar