Skip to content

Instantly share code, notes, and snippets.

@mathieureguer
Created September 30, 2022 11:13
Show Gist options
  • Save mathieureguer/e33100f745ff476b5b7d65806c31b5ce to your computer and use it in GitHub Desktop.
Save mathieureguer/e33100f745ff476b5b7d65806c31b5ce to your computer and use it in GitHub Desktop.
"""
This is very barebones, but it allows changing one or several locations
within a designspace while preerving an identical output.
(hey, it's hard to plan a designspace exactly right from the start :)
ie. changing a source location from weight:1200 to weight:1000 will recalculate all the other locations
so that the resulting instances remain the same as before.
Set your relocation_map below.
"""
# ----------------------------------------
import pathlib
from mutatorMath.objects.mutator import buildMutator
from mutatorMath.objects.location import Location
from ufoProcessor import DesignSpaceDocument
# ----------------------------------------
DESIGN_SPACE_PATH = "../30 ufos/sources/Dulux-A.designspace"
"""
This list should map tuples of existing locations in the designspace to their desired new locations,
-> (existing_location, desired_location)
If you want a existing location to remain the unchanged, it should be featured in this list,
with existing location and desired location being the same
-> (existing_location, exiting_location)
Any location, source or instance, not present in this list will be recalculated.
"""
relocation_map = [
(Location(weight=0, width=0), Location(weight=0, width=0)),
(Location(weight=1200, width=0), Location(weight=1000, width=0)),
(Location(weight=0, width=1000), Location(weight=0, width=1000)),
(Location(weight=1000, width=1000), Location(weight=1000, width=1000)),
]
round_new_locations = True
# ----------------------------------------
def offset_location(source_or_instance, offset_space, rounded=False, verbose=True):
offset = offset_space.makeInstance(source_or_instance.location)
new_loc = Location(**source_or_instance.location) + offset
if round_location:
new_loc = round_location(new_loc)
if verbose:
print(f"offseting {source_or_instance.familyName}-{source_or_instance.styleName}:")
print(f"{Location(**source_or_instance.location)} -> {new_loc}")
print()
source_or_instance.location = new_loc
def round_location(location):
data = {a: round(v) for a, v in location.items()}
return Location(**data)
# ----------------------------------------
root_path = pathlib.Path(__file__).parent
input_path = root_path / DESIGN_SPACE_PATH
offset_loc = [(old_loc, new_loc-old_loc) for old_loc, new_loc in relocation_map]
bias, offset_space = buildMutator(offset_loc)
original_space = DesignSpaceDocument()
original_space.read(DESIGN_SPACE_PATH)
print("Relocating sources")
for source in original_space.sources:
offset_location(source, offset_space, rounded=round_new_locations)
print("Relocating instances")
for instance in original_space.instances:
offset_location(instance, offset_space, rounded=round_new_locations)
output_name = input_path.stem + "_relocated" + input_path.suffix
output_path = input_path.parent / output_name
original_space.write(output_path)
print(f"Saved {output_path.name}.")
@LettError
Copy link

Should be tested with the upcoming DS5 update for ufoProcessor: https://github.com/LettError/ufoProcessor/tree/ds5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment