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

[buildcff2vf] unexpected behavior for non-interpolating glyph #1655

Open
frankrolf opened this issue May 22, 2023 · 2 comments
Open

[buildcff2vf] unexpected behavior for non-interpolating glyph #1655

frankrolf opened this issue May 22, 2023 · 2 comments

Comments

@frankrolf
Copy link
Member

I have a designspace like this:

๐Ÿ‘พโ”โ”๐Ÿ‘พโ”โ”๐Ÿ‘พ
โ”ƒ    โ”ƒ    โ”ƒ
๐Ÿ‘พโ”โ”๐ŸŒžโ”โ”๐Ÿ‘พ
โ”ƒ    โ”ƒ    โ”ƒ
๐Ÿ‘พโ”โ”๐Ÿ‘พโ”โ”๐Ÿ‘พ

2 axes, 9 sources, the middle source (๐ŸŒž) is my default.
I have one interpolating glyph (o), and a generic glyph (โ„ฎ).

In my opinion, the most obvious approach for a generic glyph would be having it in the default source only.
However, in the case of this designspace, this approach fails:

Traceback (most recent call last):
  File "3.10.9/bin/buildcff2vf", line 8, in <module>
    sys.exit(main())
  File "3.10.9/lib/python3.10/site-packages/afdko/buildcff2vf.py", line 593, in main
    varFont.save(options.var_font_path)
  File "3.10.9/lib/python3.10/site-packages/fontTools/ttLib/ttFont.py", line 185, in save
    writer_reordersTables = self._save(tmp)
  File "3.10.9/lib/python3.10/site-packages/fontTools/ttLib/ttFont.py", line 225, in _save
    self._writeTable(tag, writer, done, tableCache)
  File "3.10.9/lib/python3.10/site-packages/fontTools/ttLib/ttFont.py", line 658, in _writeTable
    tabledata = self.getTableData(tag)
  File "3.10.9/lib/python3.10/site-packages/fontTools/ttLib/ttFont.py", line 680, in getTableData
    return self.tables[tag].compile(self)
  File "3.10.9/lib/python3.10/site-packages/fontTools/ttLib/tables/_h_e_a_d.py", line 72, in compile
    bounds = charString.calcBounds(charStrings)
  File "3.10.9/lib/python3.10/site-packages/fontTools/misc/psCharStrings.py", line 1012, in calcBounds
    self.draw(boundsPen)
  File "3.10.9/lib/python3.10/site-packages/fontTools/misc/psCharStrings.py", line 1007, in draw
    extractor.execute(self)
  File "3.10.9/lib/python3.10/site-packages/fontTools/misc/psCharStrings.py", line 528, in execute
    super().execute(charString)
  File "3.10.9/lib/python3.10/site-packages/fontTools/misc/psCharStrings.py", line 302, in execute
    rv = handler(index)
  File "3.10.9/lib/python3.10/site-packages/fontTools/misc/psCharStrings.py", line 588, in op_rmoveto
    self.rMoveTo(self.popallWidth())
  File "3.10.9/lib/python3.10/site-packages/fontTools/misc/psCharStrings.py", line 487, in popallWidth
    assert self.defaultWidthX is not None, "CFF2 CharStrings must not have an initial width value"
AssertionError: CFF2 CharStrings must not have an initial width value

I was curious what exactly goes wrong โ€“ it turns out that having the generic glyph in any other source but the generic one will build a proper CFF2 VF. Also, any combination of same-glyph-in-two-sources will build the CFF2.
While this failure may have to do with my specific designspace setup (and some behind-the-scenes designspace shuffling), I think this smells like a bug.

Attached is a project which simulates all 45 possible scenarios (generic glyph in one or two sources) within this designspace, and attempts to build a CFF2 VF from it. Really, only the most obvious approach fails. ๐Ÿ˜…

Thanks to @nicksherman who ran into this issue IRL, and thus sparked this exploration.

test_sparsity.zip

@skef
Copy link
Collaborator

skef commented May 22, 2023

Now that I've been looking at the relevant fontTools code in the hope of mimicking its effects, I might be able to say a bit about this.

Broadly speaking I agree that a glyph only defined in the default master should "work". That may require special alternative handling in the fontTools model code, or outside of that code to avoid instantiating a model in the first place.

However, I suspect that the fact that things work when you add the glyph to any additional master is basically a coincidence. Before a certain point in fontTools development you needed to have at least one master on the edge of every axis. From what I can tell they changed that in order to support certain HOI cases where supplying those masters would be ugly, effectively by pretending that the default master was reproduced in those locations.

It is a little strange that this hasn't been thought of/requested before, as it seems like something that would have come up. Maybe there's some way to request "special handling" that is implemented for glyf/loca but not CFF. We can check that.

@nicksherman
Copy link

Adding a bit more context here in the hopes that it might lead to a faster resolution โ€ฆ

I originally asked @frankrolf about this issue after running in to it when adding some new glyphs in the default source of a project I'm working on. The curious thing is that before that, the project already had many other glyphs that only existed in the default source, and it had never been an issue before. And, in fact, I tried removing the new glyphs in the process of trouble shooting and was able to generate the variable font again, even though those older default-only glyphs were still in place.

Of course as you might imagine I did lots of troubleshooting to see if it was something about the specific glyphs I was adding, but the only thing new that came from that exploration was that if I kept the glyphs in place but removed all the contours inside, the font would sometimes generate.

After that point Frank made his more controlled test suite to recreate the issue, but I have a strange sense that there may be some other factors at play than it appears, otherwise โ€“ as @skef said โ€“ I would have expected the issue to come up before.

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

No branches or pull requests

3 participants