fonttools / fontbakery

🧁 A font quality assurance tool for everyone
https://fontbakery.readthedocs.io
Apache License 2.0
533 stars 99 forks source link

New GF check: Notdef glyphs conform to the best standard design, the rect with diagonals #4770

Open davelab6 opened 1 week ago

davelab6 commented 1 week ago

Observed behaviour

Someone at a major hardware vendor reported to me that some fonts (unclear which in GF collection) have funky glyph drawings encoded in the notdef character. Fun ones include a QR code for a page on the foundry website telling them to commission glyph set extensions, things that relate to "missing" or "redacted" concepts and the theme of the typeface, or more fresh designs of the classic notdef designs that relate more closely to the typeface styles itself.

The problem with those, for the rationale here, is that readers can not unambiguously decipher when they are getting back a notdef; not only human users but also OCR robot users :)

The classic designs are shown in https://learn.microsoft.com/en-us/typography/opentype/spec/recom#glyph-0-the-notdef-glyph and I think the best design is the rectangle with diagonals. The vendor person showed me their analysis which found a large collection of popular CJK fonts all using that design with no exceptions - only small variety of W:H proportions.

I also think it ought to be consistently singular in W:H and stroke width, in all styles of a family (similar to the original Euro symbol ;) I think variation within a family is OK, and I'm not ready to impose a single design on all GF families, but I expect that in future it may be that text engines ignore the notdef glyphs in fonts to get better uniformity.

Expected behaviour

I would like a GF check that WARNs when GF families do not have a 5 contour notdef design (the rectangle with the two diagonal lines, the 1 outer contour and then the 4 counters on each side).

felipesanches commented 1 week ago

Instead of creating a new check, (in the spirit of issue #4735), I think this should be an additional validation on com.google.fonts/check/mandatory_glyphs:

@check(
    id="com.google.fonts/check/mandatory_glyphs",
    rationale="""
        The OpenType specification v1.8.2 recommends that the first glyph is the
        '.notdef' glyph without a codepoint assigned and with a drawing:

        The .notdef glyph is very important for providing the user feedback
        that a glyph is not found in the font. This glyph should not be left
        without an outline as the user will only see what looks like a space
        if a glyph is missing and not be aware of the active font’s limitation.

        https://docs.microsoft.com/en-us/typography/opentype/spec/recom#glyph-0-the-notdef-glyph

        Pre-v1.8, it was recommended that fonts should also contain 'space', 'CR'
        and '.null' glyphs. This might have been relevant for MacOS 9 applications.
    """,
    proposal="legacy:check/046",
)
davelab6 commented 1 week ago

@felipesanches good suggestion :)

This is the design I mentioned, as "a 5 contour notdef design", but there are a few other things that the vendor person has pointed out about the geometry of this glyph design which can be used in a check to ensure it is what we want:

Screenshot 2024-06-20 at 10 26 00 PM

Additionally, the glyph design has some interesting properties for the bounding boxes of the 5 paths:

Screenshot 2024-06-20 at 10 30 10 PM

While I had noted "it ought to be consistently singular in W:H and stroke width, in all styles of a family", an exception to that is with italic styles, since those are typically slanted, but an unslanted notdef glyph will perhaps collide with adjacent glyphs (like /H/notdef/H/). The bounding boxes are interesting in this case because they are robust against slanting and weight stress:

Screenshot 2024-06-20 at 10 30 13 PM

This leaves a nice number of things that are straightforward to check with Python code:

Finally, for the rationale, this design is expected by Google Fonts because it is

simoncozens commented 1 week ago

I think in this case it's looking at something very different (design not just existence) so a separate check is fine. In fact, the idea that we need to do different code in different profiles is a good indicator that it should be a separate check.

vv-monsalve commented 1 week ago

I would like a GF check that WARNs when GF families do not have a 5 contour notdef design (the rectangle with the two diagonal lines, the 1 outer contour and then the 4 counters on each side).

How to reconcile this expectation with the fact that our UI actually uses a different shape, one that could fall into the "creative" category?

This is the one used there

image

Jua-Whoowahan-Brothers
davelab6 commented 1 week ago

2 wide aspect ratio contained; paths are non-overlapping 2 tall aspect ratio contained; paths are also non-overlapping

Also: Aspect Ratio = width / height, so:

How to reconcile this expectation with the fact that our UI actually uses a different shape, one that could fall into the "creative" category?

I will file an internal bug report ;)

vv-monsalve commented 1 week ago

I like creativity, though!

khaledhosny commented 6 days ago

but I expect that in future it may be that text engines ignore the notdef glyphs in fonts to get better uniformity.

That is already the case in Firefox and Pango, they both ignore the .notdef glyph in the font and show a hex box of the codepoint of the character.

moyogo commented 6 days ago

GF could remove .notdef and let ufo2ft draw it.

davelab6 commented 6 days ago

@vv-monsalve I can connect you to the vendor person if you would like :)

@moyogo Is that a Builder feature for @simoncozens ?

simoncozens commented 6 days ago

We could write a ufo2ft filter and let the builder call it. And yes, we probably should.

simoncozens commented 6 days ago

Incidentally flag this up as yet another "things we want a font compiler to do that not everyone wants a font compiler to do."

felipesanches commented 6 days ago

Incidentally flag this up as yet another "things we want a font compiler to do that not everyone wants a font compiler to do."

FontBakery's concept of a profile should be adopted on font editors and font compilers as well

moyogo commented 6 days ago

GF could remove .notdef and let ufo2ft draw it.

We could write a ufo2ft filter

utfo2ft.outlineCompiler will draw a .notdef when there is none.

simoncozens commented 5 days ago

It does, but not the one we want.

moyogo commented 4 days ago

It does, but not the one we want.

It sounds like it’s not the one ufo2ft should draw either.