[ttGlyphPen_test] Add bounds test for 'nested' composite glyph

This is a regression introduced with https://github.com/fonttools/fonttools/pull/3750

The test currently fails because we are now applying rounding to the
coordinates extracted from each component of a composite glyph, *before*
these are transformed; with nested components of components with non trivial transforms, the rounding errors compound leading to incorrect bounds.
This commit is contained in:
Cosimo Lupo 2025-01-24 14:40:21 +00:00
parent 48a4b76332
commit e02349c7ce

View File

@ -614,6 +614,52 @@ class TTGlyphPointPenTest(TTGlyphPenTestBase):
# these are the expected bounds as computed from the rounded coordinates
self.assertGlyphBoundsEqual(compositeGlyph, (74, 680, 329, 834))
def test_composite_bounds_with_nested_components(self):
# The following test case is taken from Joan.glyphs at
# https://github.com/PaoloBiagini/Joan
# There's a composite glyph 'bullet.sc' which contains a transformed
# component 'bullet', which in turn is a composite glyph referencing
# another transformed components ('period'). The two transformations
# combine to produce the final transformed coordinates, but the necessary
# rounding should only happen at the end, and not at each intermediate
# level of the nested component tree.
glyphSet = {}
pen = TTGlyphPointPen(glyphSet)
pen.beginPath()
pen.addPoint((141.0, -8.0), "qcurve")
pen.addPoint((168.0, -8.0), None)
pen.addPoint((205.0, 30.5), None)
pen.addPoint((205.0, 56.0), "qcurve")
pen.addPoint((205.0, 82.25), None)
pen.addPoint((168.0, 118.0), None)
pen.addPoint((141.0, 118.0), "qcurve")
pen.addPoint((114.0, 118.0), None)
pen.addPoint((78.0, 79.5), None)
pen.addPoint((78.0, 54.0), "qcurve")
pen.addPoint((78.0, 27.75), None)
pen.addPoint((114.0, -8.0), None)
pen.endPath()
glyphSet["period"] = pen.glyph()
pen.addComponent("period", (1.6, 0, 0, 1.6, -41, 140))
glyphSet["bullet"] = pen.glyph()
pen.addComponent("bullet", (0.9, 0, 0, 0.9, 9, 49))
compositeGlyph = glyphSet["bullet.sc"] = pen.glyph()
# this is the xMin of 'bullet.sc' glyph if coordinates were left unrounded
coords, _, _ = compositeGlyph.getCoordinates(glyphSet)
assert pytest.approx(min(x for x, y in coords)) == 84.42033
compositeGlyph.recalcBounds(glyphSet)
# if rounding happened at intermediate stages (i.e. after extracting transformed
# coordinates of 'period' component from 'bullet', before transforming 'bullet'
# component in 'bullet.sc'), the rounding errors would compound leading to xMin
# incorrectly be equal to 85. Whereas 84.42033 should round down to 84.
self.assertGlyphBoundsEqual(compositeGlyph, (84, 163, 267, 345))
def test_open_path_starting_with_move(self):
# when a contour starts with a 'move' point, it signifies the beginnig
# of an open contour.