typemytype/drawbot

variable font is not able to add glyphs by glyphName

Opened this issue · 17 comments

When adding a glyphName in as.appendGlyph("a") a warning is raised and no glyph is added. The font clearly contains the requested glyph.

This seems to work fine when adding a glyph by index.

This seems to work fine with "Skia" but not with AdobeVFPrototype.ttf. I guess the rvrn substitution is the main difference here..

Tested on macOS 13.5.2

s = FormattedString()

path = 'AdobeVFPrototype.ttf'

s.font(path)
s.fontSize(300)

s.fontVariations(wght=675)
s += "$¢ "

print(s.listFontGlyphNames().index("glyph00312"))
s.appendGlyph("glyph00312")
s.appendGlyph(311) # by index
s.appendGlyph("A")
s.appendGlyph(24) # by index

text(s, (54, 102))

I get this:

Traceback (most recent call last):
  File "<untitled>", line 11, in <module>
ValueError: 'glyph00312' is not in list

This is on macOS 14.0.

When I make a TTX dump of the font, I see indeed that it doesn't contain a glyph named "glyph00312".

Could it be you're looking at a different version of the font, perhaps one with a post 3 table?

It seems that appendGlyph() uses the OS way to refer to a glyph by name, but listFontGlyphNames() uses fonttools. This should work well as long as the font has a post table that that contains glyph names, but may lead to discrepancies when the post table does not contain glyph names (post format 3).

If I comment out line 11, the image l get is this:
image

But I also get a warning:

*** DrawBot warning: font 'AdobeVFPrototype-Default_wght2A30000_CNTR' has no glyph with the name 'glyph00312' ***

But that probably matches what you're seeing?

It works for me if I use "cent" and "cent.nostroke" for the glyph names.

super strange, testing it directly with fontTools inside the script

image

I'm getting this:

>>> from fontTools.ttLib import TTFont
>>> path = '/Users/just/Downloads/AdobeVFPrototype (1).ttf'
>>> ft = TTFont(path)
>>> print("glyph00312" in ft.getGlyphOrder())
False
from fontTools.ttLib import TTFont
path = '/Users/just/Downloads/AdobeVFPrototype (1).ttf'
ft = TTFont(path)
print("glyph00312" in ft.getGlyphOrder())
print(ft["head"].fontRevision)
print(ft["head"].modified)

Output:

False
1.003997802734375
3634020435

🤯

True
1.003997802734375
3669988076

different modified value

Ahhh, I downloaded 1.004, not 1.005a.

And yes, 1.005a has a post table format 3.

Apologies for the mixup, my brain went for the blue download links, which is 1.004 as it's the latest non-pre-release...
image

We could fix appendGlyph() by using the TTFont instance to convert the glyph name to glyph ID (ft.getGlyphID()).

my first thought was idd to use fontTools to get the glyph index...

and glyphWithName_ is deprecated
https://developer.apple.com/documentation/appkit/nsfont/1530847-glyphwithname?language=objc

Ok, that's another reason to use fonttools for this.

The hard part: it looks like we use fonttools in many places, but don't keep the TTFont instance around, but we should for this use case.

mmm must be something similar to this: https://github.com/typemytype/drawbot/blob/master/drawBot/context/baseContext.py#L1852-L1867

where we need the fontPath, fontNumber, res_name_or_index

adding a memoized function to cache the ttFont object similar as to getNSFontFromNameOrPath