Interpolating Ubuntu Mono fails with "Errors calculating 427 glyphs" due to IndexError in "fontMath/mathGlyph.py"
See original GitHub issueHi there,
This looks like a really cool project. I tried to get a feel of how it works by interpolating a semi-bold version of Ubuntu Mono. I used FontForge to convert the TTFs to UFO:
font = fontforge.open("UbuntuMono-R.ttf")
font.generate("UbuntuMono-R.ufo")
font.close()
Then I made the following designspace file:
<?xml version="1.0" ?>
<designspace format="3">
<sources>
<source filename="sources/ufos/UbuntuMono-R.ufo" name="ubuntu_mono_regular">
<lib copy="1"/>
<groups copy="1"/>
<info copy="1"/>
<location>
<dimension name="weight" xvalue="400"/>
</location>
</source>
<source filename="sources/ufos/UbuntuMono-B.ufo" name="ubuntu_mono_bold">
<location>
<dimension name="weight" xvalue="700"/>
</location>
</source>
</sources>
<instances>
<instance familyname="Ubuntu Mono" filename="outputs/UbuntuMono-M.ufo" stylename="Medium">
<location>
<dimension name="weight" xvalue="500"/>
</location>
<info/>
<kerning/>
</instance>
<instance familyname="Ubuntu Mono" filename="outputs/UbuntuMono-SB.ufo" stylename="SemiBold">
<location>
<dimension name="weight" xvalue="600"/>
</location>
<info/>
<kerning/>
</instance>
</instances>
</designspace>
Finally, I ran MutatorMath like this:
from mutatorMath.ufo import build
build("ubuntu-mono.designspace")
Unfortunately, this failed to generate a valid font; the log says:
2016-10-25 01:05:26,775 MutatorMath Executing designspace document: ubuntu-mono.designspace
2016-10-25 01:05:26,800 MutatorMath Writing UbuntuMono-M.ufo to outputs/UbuntuMono-M.ufo
2016-10-25 01:05:27,849 MutatorMath Multiple unicode values for glyph nonmarkingreturn: 9, 13
2016-10-25 01:05:27,850 MutatorMath Multiple unicode values for glyph .null: 8, 0, 29
2016-10-25 01:05:29,731 MutatorMath outputs/UbuntuMono-M.ufo:
Errors calculating 427 glyphs:
[…]
I removed the catch-all exception handler around _calculateGlyph in ufo/instance.py
and got the following backtrace:
Traceback (most recent call last):
File "./buildinstances.py", line 19, in <module>
main()
File "./buildinstances.py", line 16, in main
build("ubuntu-mono.designspace")
File "./deps/MutatorMath/Lib/mutatorMath/ufo/__init__.py", line 56, in build
reader.process()
File "./deps/MutatorMath/Lib/mutatorMath/ufo/document.py", line 418, in process
self.readInstances(makeGlyphs=makeGlyphs, makeKerning=makeKerning, makeInfo=makeInfo)
File "./deps/MutatorMath/Lib/mutatorMath/ufo/document.py", line 572, in readInstances
self._readSingleInstanceElement(instanceElement, makeGlyphs=makeGlyphs, makeKerning=makeKerning, makeInfo=makeInfo)
File "./deps/MutatorMath/Lib/mutatorMath/ufo/document.py", line 631, in _readSingleInstanceElement
instanceObject.addGlyph(n, unicodeValue)
File "./deps/MutatorMath/Lib/mutatorMath/ufo/instance.py", line 345, in addGlyph
self._calculateGlyph(glyphObject, instanceLocation, glyphMasters)
File "./deps/MutatorMath/Lib/mutatorMath/ufo/instance.py", line 371, in _calculateGlyph
bias, m = buildMutator(items, warpDict=self.warpDict)
File "./deps/MutatorMath/Lib/mutatorMath/objects/mutator.py", line 46, in buildMutator
onx.append((lb, obj-m.getNeutral()))
File "./deps/fontMath/Lib/fontMath/mathGlyph.py", line 167, in __sub__
self._processMathOne(copiedGlyph, otherGlyph, subPt, sub)
File "./deps/fontMath/Lib/fontMath/mathGlyph.py", line 178, in _processMathOne
copiedGlyph.contours = _processMathOneContours(self.contours, otherGlyph.contours, ptFunc)
File "./deps/fontMath/Lib/fontMath/mathGlyph.py", line 516, in _processMathOneContours
pt2 = points2[index][1]
IndexError: list index out of range
Here’s the context in which this error occurred, courtesy of PDB:
(Pdb) pprint(locals())
{'contour1': {'identifier': None,
'points': [('qcurve', (249, 499), False, None, None),
(None, (239, 464), False, None, None),
(None, (222, 401), False, None, None),
(None, (207, 340), False, None, None),
(None, (194, 278), False, None, None),
('qcurve', (188, 245), False, None, None),
(None, (188, 245), False, None, None),
(None, (309, 245), False, None, None),
('curve', (309, 245), False, None, None),
(None, (303, 278), False, None, None),
(None, (291, 340), False, None, None),
(None, (276, 401), False, None, None),
(None, (259, 464), False, None, None)]},
'contourIdentifier': None,
'contours1': [{'identifier': None,
'points': [('curve', (359, 0), False, None, None),
(None, (359, 0), False, None, None),
(None, (330, 143), False, None, None),
('curve', (330, 143), False, None, None),
(None, (330, 143), False, None, None),
(None, (165, 143), False, None, None),
('curve', (165, 143), False, None, None),
(None, (165, 143), False, None, None),
(None, (137, 0), False, None, None),
('curve', (137, 0), False, None, None),
(None, (137, 0), False, None, None),
(None, (9, 0), False, None, None),
('curve', (9, 0), False, None, None),
(None, (53, 183), False, None, None),
(None, (143, 484), False, None, None),
('qcurve', (185, 619), False, None, None),
(None, (185, 619), False, None, None),
(None, (319, 619), False, None, None),
('curve', (319, 619), False, None, None),
(None, (363, 483), False, None, None),
(None, (450, 178), False, None, None),
('qcurve', (491, 0), False, None, None),
(None, (491, 0), False, None, None),
(None, (359, 0), False, None, None)]},
{'identifier': None,
'points': [('qcurve', (249, 499), False, None, None),
(None, (239, 464), False, None, None),
(None, (222, 401), False, None, None),
(None, (207, 340), False, None, None),
(None, (194, 278), False, None, None),
('qcurve', (188, 245), False, None, None),
(None, (188, 245), False, None, None),
(None, (309, 245), False, None, None),
('curve', (309, 245), False, None, None),
(None, (303, 278), False, None, None),
(None, (291, 340), False, None, None),
(None, (276, 401), False, None, None),
(None, (259, 464), False, None, None)]}],
'contours2': [{'identifier': None,
'points': [('curve', (404, 0), False, None, None),
(None, (404, 0), False, None, None),
(None, (367, 162), False, None, None),
('curve', (367, 162), False, None, None),
(None, (367, 162), False, None, None),
(None, (129, 162), False, None, None),
('curve', (129, 162), False, None, None),
(None, (129, 162), False, None, None),
(None, (93, 0), False, None, None),
('curve', (93, 0), False, None, None),
(None, (93, 0), False, None, None),
(None, (9, 0), False, None, None),
('curve', (9, 0), False, None, None),
(None, (26, 66), False, None, None),
(None, (68, 220), False, None, None),
(None, (117, 382), False, None, None),
(None, (171, 545), False, None, None),
('qcurve', (201, 619), False, None, None),
(None, (201, 619), False, None, None),
(None, (303, 619), False, None, None),
('curve', (303, 619), False, None, None),
(None, (332, 545), False, None, None),
(None, (385, 382), False, None, None),
(None, (432, 220), False, None, None),
(None, (474, 66), False, None, None),
('qcurve', (491, 0), False, None, None),
(None, (491, 0), False, None, None),
(None, (404, 0), False, None, None)]},
{'identifier': None,
'points': [('qcurve', (249, 547), False, None, None),
(None, (226, 484), False, None, None),
(None, (172, 318), False, None, None),
('qcurve', (148, 230), False, None, None),
(None, (148, 230), False, None, None),
(None, (348, 230), False, None, None),
('curve', (348, 230), False, None, None),
(None, (325, 320), False, None, None),
(None, (272, 487), False, None, None)]}],
'func': <function subPt at 0x7f7f3bbefc80>,
'identifier': None,
'index': 9,
'name': None,
'point': (None, (303, 278), False, None, None),
'points1': [('qcurve', (249, 499), False, None, None),
(None, (239, 464), False, None, None),
(None, (222, 401), False, None, None),
(None, (207, 340), False, None, None),
(None, (194, 278), False, None, None),
('qcurve', (188, 245), False, None, None),
(None, (188, 245), False, None, None),
(None, (309, 245), False, None, None),
('curve', (309, 245), False, None, None),
(None, (303, 278), False, None, None),
(None, (291, 340), False, None, None),
(None, (276, 401), False, None, None),
(None, (259, 464), False, None, None)],
'points2': [('qcurve', (249, 547), False, None, None),
(None, (226, 484), False, None, None),
(None, (172, 318), False, None, None),
('qcurve', (148, 230), False, None, None),
(None, (148, 230), False, None, None),
(None, (348, 230), False, None, None),
('curve', (348, 230), False, None, None),
(None, (325, 320), False, None, None),
(None, (272, 487), False, None, None)],
'pprint': <function pprint at 0x7f7f3a2fc378>,
'pt': (37, -242),
'pt1': (303, 278),
'pt2': (272, 487),
'result': [{'identifier': None,
'points': [('curve', (-45, 0), False, None, None),
(None, (-45, 0), False, None, None),
(None, (-37, -19), False, None, None),
('curve', (-37, -19), False, None, None),
(None, (-37, -19), False, None, None),
(None, (36, -19), False, None, None),
('curve', (36, -19), False, None, None),
(None, (36, -19), False, None, None),
(None, (44, 0), False, None, None),
('curve', (44, 0), False, None, None),
(None, (44, 0), False, None, None),
(None, (0, 0), False, None, None),
('curve', (0, 0), False, None, None),
(None, (27, 117), False, None, None),
(None, (75, 264), False, None, None),
('qcurve', (68, 237), False, None, None),
(None, (14, 74), False, None, None),
(None, (118, 0), False, None, None),
('curve', (118, 0), False, None, None),
(None, (60, -136), False, None, None),
(None, (147, -441), False, None, None),
('qcurve', (159, -545), False, None, None),
(None, (106, -382), False, None, None),
(None, (-73, -220), False, None, None)]}],
'resultPoints': [('qcurve', (0, -48), False, None, None),
(None, (13, -20), False, None, None),
(None, (50, 83), False, None, None),
(None, (59, 110), False, None, None),
(None, (46, 48), False, None, None),
('qcurve', (-160, 15), False, None, None),
(None, (-160, 15), False, None, None),
(None, (-16, -75), False, None, None),
('curve', (37, -242), False, None, None)],
'segmentType': None,
'smooth': False}
Am I doing something wrong? Thanks for this cool project!
Issue Analytics
- State:
- Created 7 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
No results found
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
It’s possible to do this, but it wasn’t a goal of fontMath back when I wrote it. My goal was to have extremely predictable interpolation. I’ve thought about adding support for forcing compatibility by inserting points + flattening to equal numbers of line segments, but I’ve never had time to write it. I’d be happy to accept a patch that implements this (as long as it is optional and off by default, to maintain existing behavior).
Thanks for explaining! I understand. I don’t think this is something I could figure out myself in a small amount of time, but hopefully someone will 😃