diff --git a/Tests/pens/ttGlyphPen_test.py b/Tests/pens/ttGlyphPen_test.py index e508b2bfd..4cc43bd00 100644 --- a/Tests/pens/ttGlyphPen_test.py +++ b/Tests/pens/ttGlyphPen_test.py @@ -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.