Skip to content

Instantly share code, notes, and snippets.

@arialcrime
Created February 7, 2023 16:25
Show Gist options
  • Select an option

  • Save arialcrime/d2fa5b7abaee7f8dba9bdf40c74d8894 to your computer and use it in GitHub Desktop.

Select an option

Save arialcrime/d2fa5b7abaee7f8dba9bdf40c74d8894 to your computer and use it in GitHub Desktop.
make adjustments to an existing designspace file
import pathlib
from fontTools.designspaceLib import (DesignSpaceDocument, AxisDescriptor,
SourceDescriptor, InstanceDescriptor)
remap_dict = {
'weight': {
50: ['air', 'hairline'],
100: ['thin'],
200: ['ultralight', 'extralight'],
300: ['light'],
400: ['regular'],
450: ['book'],
500: ['medium'],
600: ['semibold'],
700: ['bold'],
800: ['extrabold'],
900: ['black']
}
}
rename_stylenames_dict = {
'Semi Bold': 'Semibold',
}
def sort(elements, axisname=None):
return sorted(elements, key=lambda e: e.location[axisname])
def sort_sources_instances(doc, axisname):
if not axisname:
axisname = doc.axes[0].name
doc.sources = sort(doc.sources, axisname)
doc.instances = sort(doc.instances, axisname)
def remap_source_instance(items_list, axis_name):
mapping_values = []
for i in items_list:
style_name = i.styleName.replace(' Italic','').replace(' ','').lower()
new_value = next((key for key,values in remap_dict[axis_name].items() if style_name in values), None)
if new_value:
mapping_values.append((new_value, i.location[axis_name]))
return sorted(mapping_values)
def write_axis_map(doc):
for a in doc.axes:
if a.name == "weight":
axis_name = a.name
# we assume here that all masters have an instance too
# otherwise we’d need to loop through doc.sources too
a.map = remap_source_instance(doc.instances, axis_name)
# fix min/max/defaults since they thould be user-values
a.minimum = a.map[0][0]
a.maximum = a.map[-1][0]
a.default = next((t[0] for t in a.map if t[1] == a.default), a.default)
# rename source files in path
def rename_sources(doc):
doc_path = pathlib.Path(doc.path)
dir_path = doc_path.parent
# get the ufo paths
if 'italic' in doc_path.name.lower():
source_ufo_paths = [u for u in dir_path.glob(f'*.ufo') if 'italic' in u.name.lower()]
ita = '-Italic'
else:
source_ufo_paths = [u for u in dir_path.glob(f'*.ufo') if not 'italic' in u.name.lower()]
ita = ''
# find out index of file in designspace doc
source_filenames = [s.filename for s in doc.sources]
for source_ufo_path in source_ufo_paths:
if source_ufo_path.name in source_filenames:
i = source_filenames.index(source_ufo_path.name)
new_source_name = f'{source_ufo_path.name.split("-")[0]}{ita}_{i}.ufo'
new_source_path = pathlib.Path(source_ufo_path.parent, new_source_name)
source_ufo_path.rename(new_source_path)
doc.sources[i].path = str(new_source_path)
#doc.sources[i].name = new_source_name
def fix_instances(doc):
doc_path = pathlib.Path(doc.path)
dir_path = doc_path.parent
for i in doc.instances:
# fix styleName
if i.styleName.title() != i.styleName:
i.styleName = i.styleName.title()
if i.styleName in rename_stylenames_dict:
i.styleName = rename_stylenames_dict[i.styleName]
ps_styleName = i.styleName.replace(" Italic","It")
ps_familyName = i.familyName.replace("\'","").replace(" ","")
# fix path
instance_path = dir_path / f'../Instances/{ps_styleName}/font.ufo'
i.path = str(instance_path.resolve())
i.postScriptFontName = f'{ps_familyName}-{ps_styleName}'
if __name__ == "__main__":
root_path = pathlib.Path(__file__).parent
dsp_path = "../path/to/your.designspace"
input_path = root_path / dsp_path
input_path = input_path.resolve() #
doc = DesignSpaceDocument.fromfile(input_path)
write_axis_map(doc)
sort_sources_instances(doc, axisname=None) # sorts by first axis if none given
rename_sources(doc)
fix_instances(doc)
output_name = input_path.stem + "_relocated" + input_path.suffix
output_path = input_path.parent / output_name
doc.write(output_path)
print(f"Saved {output_path.name}.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment