Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generating fonts from Designspace failed: Tried to end an empty contour. #1001

Closed
clauseggers opened this issue May 31, 2023 · 6 comments · Fixed by fonttools/fonttools#3145

Comments

@clauseggers
Copy link

I’m trying to generate a VF from a Glyphs project, but I’m getting this error:

ERROR:root:In 'Playfair-2_1-Roman.glyphs' -> 'master_ufo/Playfair.designspace': Generating fonts from Designspace failed: Tried to end an empty contour.

--verbose DEBUG is not helpful. Is there a way to be clued in on what and/or where the issue specifically occur?

@anthrotype
Copy link
Member

thanks. what's the full traceback for the error that you get when you run in --verbose DEBUG?

@anthrotype
Copy link
Member

it must come from the TTGlyphPointPen.endPath method:

https://github.com/fonttools/fonttools/blob/0bf84f9c7b2f8804f944ee68a56b493a077fd776/Lib/fontTools/pens/ttGlyphPen.py#L329

@jenskutilek do you remember why you added that check for empty contours in the TTGlyphPointPen? I would think that it's ok if we simply ignore these when creating a TTGlyph, they should be harmless

@clauseggers
Copy link
Author

The full log is 28 MB. Which snippet do you want? Here is the last part:

DEBUG:glyphsLib.filters.eraseOpenCorners:Considering line segment (941,0)-(941,70)
DEBUG:glyphsLib.filters.eraseOpenCorners:Crossing points (894, 2) and (821, 73) were not on same side of line segment
DEBUG:glyphsLib.filters.eraseOpenCorners:Considering line segment (803,156)-(803,452)
DEBUG:glyphsLib.filters.eraseOpenCorners:Crossing points (803, 84) and (803, 527) were not on same side of line segment
DEBUG:glyphsLib.filters.eraseOpenCorners:Considering line segment (911,538)-(911,608)
DEBUG:glyphsLib.filters.eraseOpenCorners:Crossing points (813, 535) and (872, 606) were not on same side of line segment
DEBUG:glyphsLib.filters.eraseOpenCorners:Considering line segment (502,608)-(502,538)
DEBUG:glyphsLib.filters.eraseOpenCorners:Crossing points (539, 606) and (600, 535) were not on same side of line segment
DEBUG:glyphsLib.filters.eraseOpenCorners:Considering line segment (610,452)-(610,156)
DEBUG:glyphsLib.filters.eraseOpenCorners:Crossing points (610, 527) and (610, 82) were not on same side of line segment
DEBUG:glyphsLib.filters.eraseOpenCorners:Considering line segment (472,70)-(472,0)
DEBUG:glyphsLib.filters.eraseOpenCorners:Crossing points (596, 73) and (514, 2) were not on same side of line segment
DEBUG:glyphsLib.filters.eraseOpenCorners:All done, count of segments now: 14
DEBUG:glyphsLib.filters.eraseOpenCorners:Segments: [((472, 0), (514, 2), (594, 3), (707, 3)), ((707, 3), (815, 3), (894, 2), (941, 0)), ((941, 0), (941, 70)), ((941, 70), (821, 73), (803, 84), (803, 156)), ((803, 156), (803, 452)), ((803, 452), (803, 527), (813, 535), (911, 538)), ((911, 538), (911, 608)), ((911, 608), (872, 606), (802, 605), (707, 605)), ((707, 605), (608, 605), (539, 606), (502, 608)), ((502, 608), (502, 538)), ((502, 538), (600, 535), (610, 527), (610, 452)), ((610, 452), (610, 156)), ((610, 156), (610, 82), (596, 73), (472, 70)), ((472, 70), (472, 0))]
DEBUG:ufo2ft.timer:Took 0.423s to run EraseOpenCornersFilter on 33 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-NeedlepointSemiCondensed
DEBUG:ufo2ft.timer:Took 0.001s to run DecomposeComponentsFilter on 6 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-NeedlepointSemiExpanded
DEBUG:ufo2ft.timer:Took 0.001s to run DecomposeComponentsFilter on 6 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-NeedlepointBlackSemiCondensed
DEBUG:ufo2ft.timer:Took 0.001s to run DecomposeComponentsFilter on 6 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-NeedlepointBlackSemiExpanded
DEBUG:ufo2ft.timer:Took 0.003s to run DecomposeComponentsFilter on 6 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-AgateSemiCondensed
DEBUG:ufo2ft.timer:Took 0.001s to run DecomposeComponentsFilter on 6 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-AgateSemiExpanded
DEBUG:ufo2ft.timer:Took 0.001s to run DecomposeComponentsFilter on 6 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-AgateBlackSemiCondensed
DEBUG:ufo2ft.timer:Took 0.001s to run DecomposeComponentsFilter on 6 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-AgateBlackSemiExpanded
DEBUG:ufo2ft.timer:Took 0.001s to run DecomposeComponentsFilter on 6 glyphs
INFO:cu2qu.ufo:New spline lengths: 1: 144, 2: 5262, 3: 2728, 4: 333, 5: 53, 6: 33
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-NeedlepointSemiCondensed
DEBUG:ufo2ft.timer:Took 0.027s to run DecomposeComponentsFilter on 175 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-NeedlepointSemiExpanded
DEBUG:ufo2ft.timer:Took 0.024s to run DecomposeComponentsFilter on 175 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-NeedlepointBlackSemiCondensed
DEBUG:ufo2ft.timer:Took 0.023s to run DecomposeComponentsFilter on 175 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-NeedlepointBlackSemiExpanded
DEBUG:ufo2ft.timer:Took 0.023s to run DecomposeComponentsFilter on 175 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-AgateSemiCondensed
DEBUG:ufo2ft.timer:Took 0.023s to run DecomposeComponentsFilter on 175 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-AgateSemiExpanded
DEBUG:ufo2ft.timer:Took 0.022s to run DecomposeComponentsFilter on 175 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-AgateBlackSemiCondensed
DEBUG:ufo2ft.timer:Took 0.022s to run DecomposeComponentsFilter on 175 glyphs
INFO:ufo2ft.filters:Running DecomposeComponentsFilter on Playfair-AgateBlackSemiExpanded
DEBUG:ufo2ft.timer:Took 0.022s to run DecomposeComponentsFilter on 175 glyphs
DEBUG:ufo2ft.timer:Took 6.984s to preprocess UFO
INFO:ufo2ft:Building OpenType tables for Playfair-NeedlepointSemiCondensed
ERROR:root:In 'Playfair-2_1-Roman.glyphs' -> 'master_ufo/Playfair.designspace': Generating fonts from Designspace failed: Tried to end an empty contour.
Traceback (most recent call last):
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/fontmake/font_project.py", line 1127, in run_from_designspace
    self._run_from_designspace_interpolatable(
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/fontmake/font_project.py", line 1223, in _run_from_designspace_interpolatable
    self.build_variable_fonts(
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/fontmake/font_project.py", line 420, in build_variable_fonts
    fonts = ufo2ft.compileVariableTTFs(
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/__init__.py", line 626, in compileVariableTTFs
    vfNameToBaseUfo = _compileNeededSources(
                      ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/__init__.py", line 830, in _compileNeededSources
    ttfDesignSpace = compileInterpolatableFunc(
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/__init__.py", line 405, in compileInterpolatableTTFsFromDS
    for source, ttf in zip(result.sources, ttfs):
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/__init__.py", line 322, in compileInterpolatableTTFs
    ttf = call_outline_compiler(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/fontTools/misc/loggingTools.py", line 375, in wrapper
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/__init__.py", line 83, in call_outline_compiler
    return outlineCompiler.compile()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/outlineCompiler.py", line 159, in compile
    self.setupTable_head()
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/outlineCompiler.py", line 339, in setupTable_head
    xMin, yMin, xMax, yMax = self.fontBoundingBox
                             ^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/outlineCompiler.py", line 238, in fontBoundingBox
    self._fontBoundingBox = self.makeFontBoundingBox()
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/outlineCompiler.py", line 224, in makeFontBoundingBox
    for glyphBox in self.glyphBoundingBoxes.values():
                    ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/outlineCompiler.py", line 212, in glyphBoundingBoxes
    self._glyphBoundingBoxes = self.makeGlyphsBoundingBoxes()
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/outlineCompiler.py", line 1467, in makeGlyphsBoundingBoxes
    ttGlyphs = self.getCompiledGlyphs()
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/outlineCompiler.py", line 192, in getCompiledGlyphs
    self._compiledGlyphs = self.compileGlyphs()
                           ^^^^^^^^^^^^^^^^^^^^
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufo2ft/outlineCompiler.py", line 1449, in compileGlyphs
    glyph.drawPoints(pen)
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufoLib2/objects/glyph.py", line 355, in drawPoints
    contour.drawPoints(pointPen)
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/ufoLib2/objects/contour.py", line 184, in drawPoints
    pointPen.endPath()
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/fontTools/pens/ttGlyphPen.py", line 329, in endPath
    raise PenError("Tried to end an empty contour.")
fontTools.pens.basePen.PenError: Tried to end an empty contour.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/fontmake/__main__.py", line 656, in main
    project.run_from_glyphs(inputs.glyphs_path, **args)
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/fontmake/font_project.py", line 839, in run_from_glyphs
    self.run_from_designspace(
  File "/Users/claus/.local/virtualenv/fontmake/venv/lib/python3.11/site-packages/fontmake/font_project.py", line 1142, in run_from_designspace
    raise FontmakeError(
fontmake.errors.FontmakeError: In 'Playfair-2_1-Roman.glyphs' -> 'master_ufo/Playfair.designspace': Generating fonts from Designspace failed: Tried to end an empty contour.

@anthrotype
Copy link
Member

anthrotype commented May 31, 2023

Thanks, I made this PR in fonttools to ignore such empty contours: fonttools/fonttools#3145

it's weird that you end up with these. I hacked ufo2ft to print the name of the glyph where that exception occurs and it gave me "zero.dnom.afrc", but I can't see any empty contours in there.. probably because they are empty! 😅

I'd be curious to know how one ends up with these..

@clauseggers
Copy link
Author

Alright. I had a look and zero.dnom.afrc has zero.numr.afrc placed as a component, and all the afrc glyphs have a zero advance width to make the feature work. When I opened the glyph all the layers were missing from the layers palette. Looked like corrupted data, which is possibly the fault of either Glyphs or git which I manhandled yesterday.

In any even, I deleted the glyph and made it again. Some of the other .dnom.afrc had incorrect advance width, so I fixed those too.

I don’t know what to say … we are dealing with Glyphs here.

So after this operation I got a lot further in the process.

@jenskutilek
Copy link

it must come from the TTGlyphPointPen.endPath method:

https://github.com/fonttools/fonttools/blob/0bf84f9c7b2f8804f944ee68a56b493a077fd776/Lib/fontTools/pens/ttGlyphPen.py#L329

@jenskutilek do you remember why you added that check for empty contours in the TTGlyphPointPen? I would think that it's ok if we simply ignore these when creating a TTGlyph, they should be harmless

Ha, you already said back then that the error may be too harsh :)

fonttools/fonttools#2205 (comment)

I'm fine with dropping the assertion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants