Elstob-font
Elstob-font copied to clipboard
STAT version
STAT version is 1.1, but 4 seems to offer better functionality.
The fvar
table has a lot of Named Instances, but it would be better to offer those via STAT v4 and then only have a curated set, say max 20, in fvar, for legacy apps.
I suppose you're talking about STAT format 4 (not version)?
I don't see a way to produce a format 4 STAT table with fontmake. In the script gftools-fix-vf-meta.py, producing a format 4 STAT table is on the "to-do" list, so I suppose it's not doing that yet. (I'm having trouble running it, since it crashes with "KeyError: '18pt'").
Is there another tool that will produce a format 4 STAT table? I'm not sure I'm savvy enough to hand-edit the ttx.
There are currently 24 named instances. Very glad to get a smaller number, but would like some advice concerning which ones to trim (i.e. which are least likely to be useful).
Okay, I've found statmake, which can apparently generate a STAT table with format 4 axis definitions. I'm working through the well-annotated sample StyleSpace file. But I've run across this note:
ATTENTION: Using format 4 axis values bumps the STAT table version from 1.1 to
1.2. At the time of this writing (February 2019), version 1.2 is not supported by
Windows.
Leaving me to wonder if the time is right to go to this format of STAT table. Will it break under Windows, or is it backwards compatible?
statmake runs against the designspace for a font, and it drops any location that doesn't correspond to an instance defined in the designspace file. Thus decoupling the locations in STAT from the instances in fvar is not straightforward. I tried running statmake against a fuller version of the designspace file than that used to generate the font, with partial success: it is dropping the Grade location, even though it is retaining the others. Not sure yet what's goihg ont.
Statmake is also checking against the fvar table and dropping anything it finds that's not an instance there; so my scheme to fool it with a doctored designspace file is foiled again. I know how to fake up a format 4 STAT table now, and merge via ttx, but that would also mean manually adding entries in the name table, and, well, that's looking like quite a tangle--perhaps a thing one might do at the very end of the process. I think the thing to do is to cut back the number of instances, and if a fuller STAT table is wanted, use statmake to create a format 2 table. I'll leave this issue open in case anyone wanders by with a suggestion, but I've spent enough time on it for now.
I am trying out fonttools builder buildStatTable.
Okay, that worked well. Two simple scripts now in the repository, mkromanSTAT.py and mkitalicSTAT.py, replace the STAT table generated by fontmake with a v 1.2 format 4 STAT table. This has all combinations of wght and opsz, plus "Grade" or "Grade Italic" where the "Grade" axis is at its max of 1.
Tested the result in Samsa, which seems happy.
Number of instances is down to 17: ExtraLight, Light, Regular, Medium, SemiBold, Bold, ExtraBold; and then the full range of optical sizes is available only for Regular and Bold weights. No "Grade" instance, as the assumption is that this axis will be accessed more or less exclusively via CSS.
STAT version is 1.1, but 4 seems to offer better functionality.
The
fvar
table has a lot of Named Instances, but it would be better to offer those via STAT v4 and then only have a curated set, say max 20, in fvar, for legacy apps.
STAT v4?? Or AxisValue format 4? Perhaps it would be better to wait for @davelab6 to clarify his thought (no Google Fonts VF uses AxisValue format 4 yet).
Currently, if I look at version 1.009 of the VFs in the repo, the lack of a nameID 25, and postscriptNameID for the fvar
table, prevents fonts from working well in InDesign and Photoshop. It's among other things what gftools fix-vf-meta
is supposed to fix.
I looked at gftools-fix-vf-meta.py, but the comment at the top said it worked only for fonts with a single axis, and that's not this one. The good that's come out of the present thread is that I've learned to use fontTools.otlLib.builder, with which I'm confident that I can produce whatever format of STAT table GF wants in an hour or so: see the files sources/mk*py. I read through the TypeDrawers thread on problems with InDesign, and as a result added these lines to the roman script:
ttfont['name'].setName("ElstobRegular", 25, 1, 0, 0)
ttfont['name'].setName("ElstobRegular", 25, 3, 1, 0x409)
and the corresponding lines for italic. I haven't gotten around to the fvar problem, but I don't guess it's going to be too hard to fix. Which I've got to do, because I've (finally) been upgraded to InDesign 15.1.2, and Elstob is still not working!
Dave seems to be pushing hard to expand GF's ability to handle multiple axes and establish new standards for GF fonts; but he also seems to be stretched very thin ...
Yes, I mentioned it on TypeDrawers: InDesign was insanely requesting VFs to be made exactly like Adobe one's (going up to requesting AxisValue format 2), while Illustrator was much more forgiving, and Photoshop in between. InDesign 15.1.12 is like Photoshop on this point, now.
Currently a NamedInstance in your fvar table is like that (in TTX format):
<NamedInstance flags="0x0" subfamilyNameID="260">
For working with InDesign and Photoshop, the same example should be:
<NamedInstance flags="0x0" postscriptNameID="301" subfamilyNameID="260">
And in the name table:
<namerecord nameID="301" platformID="3" platEncID="1" langID="0x409">
ElstobRoman-6pt
</namerecord>
(for this particular example, nameID 301 = nameID 25 + nameID 260, without space).
I looked at gftools-fix-vf-meta.py, but the comment at the top said it worked only for fonts with a single axis, and that's not this one.
Marc Foley, its author, used it to fix Roboto v3.002, which has two axis (he asked me to check the output results, before publishing the fonts, but I don't know if he released his version of the script).
Ah, the version has been published, but you're right, you can't use it for multiples axis: https://github.com/googlefonts/gftools/commit/6bb2264e6cb7777de86943f2e9061dbb84656d08
For variable fonts with multiple axes, write a python script which
uses fontTools.otlLib.builder.buildStatTable e.g
https://github.com/googlefonts/literata/blob/master/sources/gen_stat.py
When I can, I'll try writing a script that will iterate through the namedInstances building the postscriptNames. So the rule should be: nameID 25 + "-" + subfamilyNameID with any spaces stripped out?
So, e.g., where subfamilyNameID is "6pt Bold," postscriptName should be "ElstobRegular-6ptBold"?
So, e.g., where subfamilyNameID is "6pt Bold," postscriptName should be "ElstobRegular-6ptBold"?
Yes, exactly. It will be a bit trickier for italics, as it would not be very clean (although fundamentally not incorrect) to repeat "Italic" in the name, so not "ElstobItalic-6ptBoldItalic", but rather "ElstobItalic-6ptBold".
Yes. Thanks for the tip about the italic. Which "Italic" to omit from the name is exactly the kind of question that ties me up in knots.
Where the subfamilyName is "Italic," what should the postscriptName be? I'm supposing it has to be matched to a postscriptName in the roman font. So should it be ElstobItalic, ElstobItalic-Italic, ElstobItalic-Regular?
The most important is the difference of the part before the hyphen, and a hyphen is needed. So: ElstobItalic-Regular.
It's easier to create when you have AxisValues of format 1, 2 or 3: with these formats, you must not mix the names of the axes (as we do for the fvar table): no AxisValue should be call "Axis 1 Axis 2", like "Condensed Bold" or "Bold Italic", because it's up to a STAT-based UI (like Samsa https://lorp.github.io/samsa/src/samsa-gui.html — you can try the result of a STAT table on this page) to aggregate styles (while NamedInstance have aggregated names).
So, with these formats, you have entries in the name table that will have only one style name, per axis ("Condensed", "Expanded", "Light", "SemiBold", "Regular", " Roman "," Italic " — this is also why using the name" Roman" distinguishes it from other "Regular"). And it is thus easier to compose the entry of the name table corresponding to the postscriptNameID.
To be more concrete, you can look at how Roboto VF v3.002 https://github.com/google/fonts/tree/master/apache/roboto is made: it works perfectly in InDesign or Samsa.
I added the postscriptNames with these fragments of code (having changed nameID 25 in the roman from ElstobRegular to ElstobRoman:
for inst in ttfont['fvar'].instances:
subfamilyName = ttfont['name'].getName(inst.subfamilyNameID,1,0,0).toUnicode().replace(" ","")
newID = ttfont['name'].addName("ElstobRoman" + "-" + subfamilyName)
inst.postscriptNameID = newID
for inst in ttfont['fvar'].instances:
subfamilyName = ttfont['name'].getName(inst.subfamilyNameID,1,0,0).toUnicode().replace(" Italic","").replace(" ","")
if subfamilyName == "Italic":
subfamilyName = "Regular"
newID = ttfont['name'].addName("ElstobItalic" + "-" + subfamilyName)
inst.postscriptNameID = newID
Which seems to work fine, giving me these postscriptNames (to select a sample):
ElstobRoman-Regular, ElstobItalic-Regular ElstobRoman-6pt, ElstobItalic-6pt ElstobRoman-ExtraLight, ElstobItalic-ExtraLight ElstobRoman-6ptBold, ElstobItalic-6ptBold etc.
which seems to agree well enough with the usage of Roboto and SourceSerif. But it's still not working in InDesign (fine in Illustrator and PhotoShop):
leading me to wonder if the problem now lies with the format 4 STAT table rather than my names.
I also wonder if it's worth going to a lot of trouble to get this font working in InDesign when the fact that it works perfectly in every other app (including Samsa) seems to indicate that the handling of variable fonts in InDesign (which only added the capability a few months ago) is very far from mature.
The InDesign team needs time to get its act together. They should probably spend some of that time having a little talk with the Illustrator team.
I'll drop the current variable fonts (with these changes) into the fonts/ttf folder of the repository.
I'll drop the current variable fonts (with these changes) into the fonts/ttf folder of the repository.
Your VFs seems perfectly fine, indeed. 😀
leading me to wonder if the problem now lies with the format 4 STAT table rather than my names.
Yes. Previous versions of InDesign 2020 only correctly worked with VFs done "Adobe style" (nameID 25 + postscriptNameID in fvar + AxisValue format 2). Version 15.1.12 seems to accept AxisValue format 1 and 3. I wouldn't be surprised if it doesn't accept Format 4. And likewise, I wouldn't be surprised if your fonts, made in Format 1, work (that's why I have doubts about Dave's exact request).
The InDesign team needs time to get its act together. They should probably spend some of that time having a little talk with the Illustrator team.
I agree!
Thanks for having a look! I may try out format 2 or 3 when I get a little extra time; but given that the InDesign programmers are working on variable font handling now, an equally valid approach may be to wait and see what happens a few versions down the road.
Taking a closer look: an Italic axis is missing.
I had an italic axis in both faces, but fontmake dropped it, so I figured it wasn't wanted. Roboto has an italic axis in STAT but not in fvar: why is that okay?
I've added an italic axis to the STAT table. It doesn't fix the problem with InDesign, but it seems worth having.
I had an italic axis in both faces, but fontmake dropped it, so I figured it wasn't wanted. Roboto has an italic axis in STAT but not in fvar: why is that okay?
The two tables work differently. fvar
dates back to TrueType GX from Mac OS 8 (still used in Apple Skia, without a STAT table).
I quickly did a "proof of concept" with AxisValue in format 2 (to be on the safe side, but it could work with format 1 and 3), rather crude (we would have to clean up the name table, and a few other things) but it was to show that it works: the attached files work in InDesign.
Note that the STAT table is much simpler like this (and would be even simpler with format 1).
Oh, this is so excellent! I was just working on this and had a ton of questions which your example is answering. So many thanks!
What is the advantage of format2 over format1? Are there apps that actually make use of the rangeValues?
Apart from Samsa, no app offers a STAT-based UI (it might come, and it's a bit expected, but for now there isn't one).
In this thread https://github.com/google/fonts/issues/2391, John Hudson intervened to discuss Format 2. The discussion is interesting (with Marc, we continued the discussion elsewhere, and he was finally persuaded to adopt Format 2 — at the speed that InDesign bugs are fixed, it was perhaps better).
I can scarcely believe this, but the font is now working in InDesign 15.1.2, with one small glitch: when the "Grade" slider is all the way to the right, the outlines snap back to the zero position (if that makes any sense).
Thanks for the link to the discussion of STAT in Google Fonts. Some of it went over my head, but I got the gist, I think, and got the very concrete fact that I should have included a format 3 AxisValue for Regular Weight. Testing in Samsa, I see the point of the format 1 or 2 AxisValue in a way I didn't before: users can (if apps cooperate) get a very clean interface, selecting from short lists of axis values instead of long jumbles of instances.
Since the STAT tables for roman and italic are mostly the same, I've combined my scripts for generating STAT and adjusting names into one. I've pushed all changes to the repo.
Note that if you include a format 3 for Regular (to make the link with Bold), it will be in addition to format 2, which doesn't have this property (this need to duplicate the same AxisValue, in format 2 and in format 3 , is one of the drawbacks of format 2, format 1 doesn't have this drawback since an AxisValue in format 3 completely replaces an AxisValue in format 1).
Yes, that's what I've got:
commonWeightDict = dict(
tag="wght",
name="Weight",
values=[
dict(nominalValue=200, name="ExtraLight", rangeMinValue=200, rangeMaxValue=250),
dict(nominalValue=300, name="Light", rangeMinValue=250, rangeMaxValue=350),
dict(nominalValue=400, name="Regular", flags=0x2, rangeMinValue=350, rangeMaxValue=450),
dict(nominalValue=500, name="Medium", rangeMinValue=450, rangeMaxValue=550),
dict(nominalValue=600, name="SemiBold", rangeMinValue=550, rangeMaxValue=650),
dict(nominalValue=700, name="Bold", rangeMinValue=650, rangeMaxValue=750),
dict(nominalValue=800, name="ExtraBold", rangeMinValue=750, rangeMaxValue=800),
dict(value=400, name="Regular", linkedValue=700, flags=0x2)
]
)
I missed that this was the situation in Roboto because I didn't know it was possible, so wasn't looking for it! But it was discussed in the thread you linked to.
I'm going to leave this issue open because it's @davelab6's issue, and I don't know but what he may look in at some point. But we've clearly reached a point of equilibrium, thanks entirely to @thlinard, to whom I'm extremely grateful. I've learned more about the STAT table (especially best practices connected with it) in the last three days than I have in the two years I've been working on this variable font.
Thank you for your kind words!