Skip to content

Commit 2e7ff27

Browse files
Merge pull request #57 from BlackFoundryCom/fix56
Reproduce and fix recursion crash
2 parents ed8f326 + 8d81d02 commit 2e7ff27

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

Lib/blackrenderer/font.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ def drawGlyph(self, glyphName, canvas, *, palette=None, textColor=(0, 0, 0, 1)):
125125
palette = self.palettes[0]
126126
self.currentPalette = palette
127127
self.textColor = textColor
128+
self._recursionCheck = set()
128129

129130
glyph = self.colrV1Glyphs.get(glyphName)
130131
if glyph is not None:
@@ -151,7 +152,13 @@ def _drawGlyphCOLRv0(self, layers, canvas):
151152
canvas.drawPathSolid(path, self._getColor(layer.colorID, 1))
152153

153154
def _drawGlyphCOLRv1(self, glyph, canvas):
154-
self._drawPaint(glyph.Paint, canvas)
155+
if glyph.BaseGlyph in self._recursionCheck:
156+
raise RecursionError(f"Glyph '{glyph.BaseGlyph}' references itself")
157+
self._recursionCheck.add(glyph.BaseGlyph)
158+
try:
159+
self._drawPaint(glyph.Paint, canvas)
160+
finally:
161+
self._recursionCheck.remove(glyph.BaseGlyph)
155162

156163
# COLRv1 Paint dispatch
157164

Tests/data/crash.subset.otf

2.14 KB
Binary file not shown.

Tests/test_glyph_render.py

+14
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"mutator": dataDir / "MutatorSans.ttf",
2727
"twemoji": dataDir / "TwemojiMozilla.subset.default.3299.ttf",
2828
"more_samples": dataDir / "more_samples-glyf_colr_1.ttf",
29+
"crash": dataDir / "crash.subset.otf",
2930
}
3031

3132

@@ -176,3 +177,16 @@ def test_vectorBackends(backendName, imageSuffix):
176177
# assert expectedPath.read_bytes() == outputPath.read_bytes()
177178
diff = compareImages(expectedPath, outputPath)
178179
assert diff < 0.00012, diff
180+
181+
182+
def test_recursive():
183+
# https://github.com/BlackFoundryCom/black-renderer/issues/56
184+
# https://github.com/justvanrossum/fontgoggles/issues/213
185+
glyphName = "hah-ar"
186+
font = BlackRendererFont(testFonts["crash"])
187+
boundingBox = font.getGlyphBounds(glyphName)
188+
surfaceClass = getSurfaceClass("svg", ".svg")
189+
surface = surfaceClass()
190+
with surface.canvas(boundingBox) as canvas:
191+
with pytest.raises(RecursionError):
192+
font.drawGlyph(glyphName, canvas)

0 commit comments

Comments
 (0)