New family check: No styles in a font family (or VF) should have Agrave bounds that exceed hhea.ascent
Observed behaviour
For a long time, I struggled with https://github.com/arrowtype/recursive/issues/308, wherein just a few styles of Recursive were given unexpected default line heights on macOS.

Last week, I discovered that this was due to Latin Basic (single-accent) uppercase characters exceeding the hhea.ascent value. When this was the case ā as it was in my Linear ExtraBold sources (and therefore styles nearby) ā macOS disregards the specified hhea values, and instead seems to use yMin & yMax values to determine default line height. In turn, this negatively affects the font usability in programs like Keynote & Sketch.
Expected behaviour
FontBakery could use a check that:
- Runs through all instances of a font
- Checks whether the
hhea.ascentis exceed by the yMax bound of any characters in Latin Basic
Something that might be challenging about this: how can we check for yMax in non-default instances of a variable font? Would this check have to calculate all deltas for instances? Is there any kind of quick way to do that?
Resources and exact process needed to replicate
This issue was discovered at v1.030 and existed up to v1.073. So, this can be reproduced with the variable and static fonts in any release of Recursive prior to v1.074, where it was fixed by making uppercase accents slightly shorter.
This issue exists on macOS Catalina (10.15) and to a slightly lesser extent macOS 11 Big Sur. (In Big Sur, it doesnāt happen in Sketch, but does occur in Keynote and presumably also other apps).
From the tests I have done, Mac OS only looks at Agrave. So basically, the hheaAscent (and TypoAscent, since we want them equal), needs to be higher than yMax of Agrave.
I would like to take this as an opportunity to add more details to a v-metric check:
- [ ]
hheaAscent = typoAscent > y-max Agrave - [ ]
hheaDescent = typoDescent - [ ]
hheaLineGap = typoLinegap = 0 - [ ] CAPS ARE CENTRED :
capsHeight - typoAscent ~= - typoDescent
Yes to the above!
I might also add...
- [ ] line height is reasonable*
- āreasonableā is within the ballpark of Roboto / SF / IBM Plex / Source Sans.
Two challenges:
- These parameters are fairly Latin-centric, and would need to be handled differently for other scripts. E.g. āCaps are centeredā is quite nice in European-language design, but may not be feasible in Arabic or even for Latin-script Vietnamese design. As one reference point, Segoe takes a different strategy, which leaves much more room above caps, when I last tried it out (a couple of years ago).
- These parameters are somewhat centered on typical sans-serif / serif text designs. I bet things may need to be different for a design like Zapfino, with really long flourishes on ascenders/descenders.
The challenges donāt suggest that we shouldnāt use these parameters, but more that the check should probably include an explanation of which kinds of fonts it applies to (and possibly result in a SKIP if a font is determined to not be Latin-focuses).
I believe the Noto project has different metric guidance for compact scripts (e.g. Latin) vs taller scripts (e.g. Arabic).
āreasonableā is within the ballpark of Roboto / SF / IBM Plex / Source Sans
Recommended 120%-130% of UPM size ? Should there be a recommended max?
These parameters are fairly Latin-centric
True, although it works for greek and cyrillic which have same caps metrics as Latin. +1 for the skip if not-latin-greek-cyrillic focused.
I've just made a quick test to test whether the Agrave is used to determine the positioning of the first line of text. Unfortunately, it isn't as simple as we hoped.
In glyphsapp: Agrave glyph with lines drawn each spaced 100 units apart (starting at 1000 units) In textedit: Agrave glyph repeated several times. We can clearly see that the whole glyph isn't visible
My custom Agrave is only displaying 3 lines, this means it's getting clipped at 1200 units. Perhaps the heuristic could be first_line_pos = min(upm * 1.2, Agrave.yMax)
I'm using Big Sur so if someone could test this on an older version, I'd be most grateful.
cc @RosaWagner
I only see 3 in Mojave too
Also, there is the test I have made to see how first base line is changing according to Agrave and typoAscender value.
In 1-3: typoAscender=1000 In 4-7: typoAscender=1400 In 1-2, Agrave in the font, tin two last examples, Agrave not in font. In 2, 3 and 4, when Agrave yMax < TypoAscender or Agrave not in font, first base line is respecting typoAscender. In 1, when Agrave yMax > typoAscender, first base line is calculated by the app.

And other test confirming the limits Marcs pointed out.

Hey! Iāve been thinking on this check lately, and I have some questions Are we sure this should go into the Universal profile. Is not a designer decisition how small or big you want the default line spacing? eg. all caps fonts intended to be set with very tight leading. Doing this workaround is not a solution just to circunvent an Apple specific odd implementation?