Skip to content

Commit

Permalink
Merge pull request #626 from googlefonts/reproduce-issue-621
Browse files Browse the repository at this point in the history
Add reproducer for issue #621
  • Loading branch information
anthrotype authored Jun 22, 2022
2 parents 42257bc + 0750dd5 commit ebd6035
Showing 1 changed file with 91 additions and 0 deletions.
91 changes: 91 additions & 0 deletions tests/filters/decomposeTransformedComponents_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,94 @@ def test_decompose_compatibly(self, FontClass):
).process()
assert len(glyphsets[0]["base"]) == 1
assert len(glyphsets[1]["base"]) == 1

def test_decompose_compatibly_nested_transformed_components(self, FontClass):
# This replicates three glyphs from the 'changa.zip' test fonts at
# https://github.com/googlefonts/ufo2ft/issues/621
# In both fonts, the "exclam" glyph is made of one simple contour and one
# component ("period"); "exclamdown" in turn is made of one "exclam" component
# that is flipped vertically and horizontally; "period" is a single contour.
# But only in the Bold.ufo, the "exclam" contains a scaled down "period"; in
# the Regular.ufo, the "period" component only has an offset.
# This would previously trigger a situation whereby after "exclamdown" was
# decomposed, its points were no longer interpolation compatible across masters
# because the order in which the contours were decomposed was different.
# This is because filters used to modify glyphs in-place in alphabetical order,
# so 'exclam' comes before 'exclamdown', and in the Bold.ufo, 'exclam' has
# a 2x3 transform so is decomposed (with the period appended at the end), but
# then 'exclamdown' needs decomposing as well (for it's flipped) and the
# already decomposed 'exclam' contours are drawn onto it in the same order;
# whereas in Regular.ufo, the 'exclam' does not contain transformed components
# so it's kept as composite (for the time being, it will be decomposed later on
# because it's mixed), but when it's the turn of 'exclamdown', the period's
# contour gets appended to it before the rest of the rest of the 'exclam'
# (deepCopyContours follows a post-order depth-first traversal so the children
# get decomposed before the parent) -- leading to cu2qu crashing... Pfew!
regular_ufo = FontClass()
period = regular_ufo.newGlyph("period")
period.width = 230
pen = period.getPen()
pen.moveTo((50, 62))
pen.curveTo((50, 13), (61, -6), (115, -6))
pen.curveTo((168, -6), (180, 13), (180, 62))
pen.curveTo((180, 110), (168, 131), (115, 131))
pen.curveTo((61, 131), (50, 110), (50, 62))
pen.closePath()

exclam = regular_ufo.newGlyph("exclam")
exclam.width = 250
pen = exclam.getPen()
pen.moveTo((93, 196))
pen.lineTo((156, 196))
pen.lineTo((186, 627))
pen.curveTo((186, 637), (181, 645), (161, 645))
pen.lineTo((87, 645))
pen.curveTo((67, 645), (63, 637), (63, 627))
pen.closePath()
pen.addComponent("period", (1, 0, 0, 1, 10, 0))

exclamdown = regular_ufo.newGlyph("exclamdown")
exclamdown.width = 250
pen = exclamdown.getPen()
pen.addComponent("exclam", (-1, 0, 0, -1, 250, 509))

bold_ufo = FontClass()
period = bold_ufo.newGlyph("period")
period.width = 277
pen = period.getPen()
pen.moveTo((30, 99))
pen.curveTo((30, 23), (50, -6), (139, -6))
pen.curveTo((227, -6), (247, 23), (247, 99))
pen.curveTo((247, 175), (227, 206), (139, 206))
pen.curveTo((50, 206), (30, 175), (30, 99))
pen.closePath()

exclam = bold_ufo.newGlyph("exclam")
exclam.width = 297
pen = exclam.getPen()
pen.moveTo((84, 230))
pen.lineTo((214, 230))
pen.lineTo((254, 618))
pen.curveTo((254, 633), (247, 645), (217, 645))
pen.lineTo((81, 645))
pen.curveTo((51, 645), (44, 633), (44, 618))
pen.closePath()
pen.addComponent("period", (0.87, 0, 0, 0.87, 28, -1))

exclamdown = bold_ufo.newGlyph("exclamdown")
exclamdown.width = 297
pen = exclamdown.getPen()
pen.addComponent("exclam", (-1, 0, 0, -1, 298, 509))

# We test that, even with DecomposeTransformedComponentsFilter(pre=True) and
# the above nested/transformed/mixed component setup, we don't crash cu2qu
# with errors about masters with inconsistent contour order after decomposition
# of "exclamdown".
glyphsets = TTFInterpolatablePreProcessor(
[regular_ufo, bold_ufo],
filters=[DecomposeTransformedComponentsFilter(pre=True)],
).process()
assert len(glyphsets[0]["exclam"]) == 2
assert len(glyphsets[0]["exclamdown"]) == 2
assert len(glyphsets[1]["exclam"]) == 2
assert len(glyphsets[1]["exclamdown"]) == 2

0 comments on commit ebd6035

Please sign in to comment.