Skip to content

Commit

Permalink
Merge pull request #1037 from googlefonts/propagete-contextual-anchors
Browse files Browse the repository at this point in the history
propagate_anchors: fix handling of contextual anchors
  • Loading branch information
anthrotype authored Oct 8, 2024
2 parents 9d5828d + 1832f83 commit 1cb4fc5
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 5 deletions.
7 changes: 6 additions & 1 deletion Lib/glyphsLib/builder/transformations/propagate_anchors.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ def origin_adjusted_anchors(anchors: list[GSAnchor]) -> Iterable[GSAnchor]:
GSAnchor(
name=a.name,
position=Point(a.position.x - origin.x, a.position.y - origin.y),
userData=dict(a.userData),
)
for a in anchors
if a.name != "*origin"
Expand Down Expand Up @@ -398,7 +399,11 @@ def get_component_layer_anchors(
if layer_anchors is not None:
# return a copy as they may be modified in place
layer_anchors = [
GSAnchor(name=a.name, position=Point(a.position.x, a.position.y))
GSAnchor(
name=a.name,
position=Point(a.position.x, a.position.y),
userData=dict(a.userData),
)
for a in layer_anchors
]
return layer_anchors
Expand Down
6 changes: 4 additions & 2 deletions Lib/glyphsLib/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2787,13 +2787,15 @@ def _serialize_to_plist(self, writer):
_parent = None
_defaultsForName = {"position": Point(0, 0)}

def __init__(self, name=None, position=None):
def __init__(self, name=None, position=None, userData=None):
self.name = "" if name is None else name
self._userData = None
if position is None:
self.position = copy.deepcopy(self._defaultsForName["position"])
else:
self.position = position
self._userData = None
if userData is not None:
self.userData = userData

def __repr__(self):
return '<{} "{}" x={:.1f} y={:.1f}>'.format(
Expand Down
64 changes: 62 additions & 2 deletions tests/builder/transformations/propagate_anchors_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,13 @@ def add_component_anchor(self, name: str) -> Self:
component.anchor = name
return self

def add_anchor(self, name: str, pos: tuple[float, float]) -> Self:
anchor = GSAnchor(name, Point(*pos))
def add_anchor(
self,
name: str,
pos: tuple[float, float],
userData: dict | None = None,
) -> Self:
anchor = GSAnchor(name, Point(*pos), userData=userData)
self.current_layer.anchors.append(anchor)
return self

Expand Down Expand Up @@ -193,6 +198,7 @@ def assert_anchors(actual, expected):
for a, e in zip(actual, expected):
assert a.name == e[0]
assert a.position == Point(*e[1])
assert dict(a.userData) == (e[2] if len(e) > 2 else {})


def test_no_components_anchors_are_unchanged():
Expand Down Expand Up @@ -611,6 +617,60 @@ def test_origin_anchor():
)


def test_contextual_anchors():
glyphs = (
GlyphSetBuilder()
.add_glyph(
"behDotless-ar.init",
lambda glyph: (
glyph.add_anchor("bottom", (50, 0))
.add_anchor(
"*bottom",
(95, 0),
userData={"GPOS_Context": "* behDotless-ar.medi"},
)
.add_anchor("top", (35, 229))
),
)
.add_glyph(
"behDotless-ar.medi",
lambda glyph: (
glyph.add_component("behDotless-ar.init", (0, 0)).add_anchor(
"*bottom",
(95, 0),
userData={"GPOS_Context": "* behDotless-ar.fina"},
)
),
)
.add_glyph(
"behDotless-ar.fina",
lambda glyph: glyph.add_component("behDotless-ar.init", (0, 0)),
)
.build()
)
propagate_all_anchors_impl(glyphs)

new_glyph = glyphs["behDotless-ar.medi"]
assert_anchors(
new_glyph.layers[0].anchors,
[
("bottom", (50, 0)),
("*bottom", (95, 0), {"GPOS_Context": "* behDotless-ar.fina"}),
("top", (35, 229)),
],
)

new_glyph = glyphs["behDotless-ar.fina"]
assert_anchors(
new_glyph.layers[0].anchors,
[
("bottom", (50, 0)),
("*bottom", (95, 0), {"GPOS_Context": "* behDotless-ar.medi"}),
("top", (35, 229)),
],
)


def test_invert_names_on_rotation():
# derived from the observed behaviour of glyphs 3.2.2 (3259)
glyphs = (
Expand Down

0 comments on commit 1cb4fc5

Please sign in to comment.