Skip to content

Commit

Permalink
work around MutatorMath warping sources/instances locations
Browse files Browse the repository at this point in the history
MutatorMath assumes that the masters and instances' locations are in
user-space coordinates -- whereas they actually are in internal design-space
coordinates, and thus they do not need any 'bending'. To work around this we
we create a temporary designspace document without the axis maps, and with the
min/default/max triplet mapped "forward" from user-space coordinates (input)
to internal designspace coordinates (output).

Related issues:
LettError/designSpaceDocument#16
fonttools/fonttools#1395
  • Loading branch information
anthrotype committed May 17, 2019
1 parent f5e65cf commit 52b1f02
Showing 1 changed file with 61 additions and 13 deletions.
74 changes: 61 additions & 13 deletions Lib/fontmake/font_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import shutil
import tempfile
from collections import OrderedDict
from contextlib import contextmanager
from copy import deepcopy
from functools import partial, wraps

import ufo2ft
Expand Down Expand Up @@ -90,6 +92,48 @@ def wrapper(*args, **kwargs):
return wrapper


@contextmanager
def temporarily_disabling_axis_maps(designspace):
"""Context manager to prevent MutatorMath from warping designspace locations.
MutatorMath assumes that the masters and instances' locations are in
user-space coordinates -- whereas they actually are in internal design-space
coordinates, and thus they do not need any 'bending'. To work around this we
we create a temporary designspace document without the axis maps, and with the
min/default/max triplet mapped "forward" from user-space coordinates (input)
to internal designspace coordinates (output).
Args:
designspace: A DesignSpaceDocument object
Yields:
A temporary path string to the thus modified designspace document.
After the context is exited, it restores the original axes and removes the
temporary file.
Related issues:
https://github.com/LettError/designSpaceDocument/issues/16
https://github.com/fonttools/fonttools/pull/1395
"""
original_axes = deepcopy(designspace.axes)
try:
for axis in designspace.axes:
axis.minimum = axis.map_forward(axis.minimum)
axis.default = axis.map_forward(axis.default)
axis.maximum = axis.map_forward(axis.maximum)
del axis.map[:]

fd, temp_designspace_path = tempfile.mkstemp()
os.close(fd)
try:
designspace.write(temp_designspace_path)
yield temp_designspace_path
finally:
os.remove(temp_designspace_path)
finally:
designspace.axes = original_axes


class FontProject(object):
"""Provides methods for building fonts."""

Expand Down Expand Up @@ -755,19 +799,23 @@ def interpolate_instance_ufos(
"attribute"
)

# TODO: replace mutatorMath with ufoProcessor?
builder = DesignSpaceDocumentReader(
designspace.path, ufoVersion=3, roundGeometry=round_instances, verbose=True
)
logger.info("Interpolating master UFOs from designspace")
if include is not None:
instances = self._search_instances(designspace, pattern=include)
for instance_name in instances:
builder.readInstance(("name", instance_name))
filenames = set(instances.values())
else:
builder.readInstances()
filenames = None # will include all instances
with temporarily_disabling_axis_maps(designspace) as temp_designspace_path:
builder = DesignSpaceDocumentReader(
temp_designspace_path,
ufoVersion=3,
roundGeometry=round_instances,
verbose=True,
)
logger.info("Interpolating master UFOs from designspace")
if include is not None:
instances = self._search_instances(designspace, pattern=include)
for instance_name in instances:
builder.readInstance(("name", instance_name))
filenames = set(instances.values())
else:
builder.readInstances()
filenames = None # will include all instances

logger.info("Applying instance data from designspace")
instance_ufos = apply_instance_data(designspace, include_filenames=filenames)

Expand Down

0 comments on commit 52b1f02

Please sign in to comment.