fonttools / fontbakery

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

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

Open davelab6 opened 4 months ago

davelab6 commented 4 months 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 4 months 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 4 months 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 4 months 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 4 months 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 4 months 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 4 months ago

I like creativity, though!

khaledhosny commented 4 months 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 4 months ago

GF could remove .notdef and let ufo2ft draw it.

davelab6 commented 4 months 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 4 months ago

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

simoncozens commented 4 months 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 4 months 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 4 months 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 4 months ago

It does, but not the one we want.

moyogo commented 4 months ago

It does, but not the one we want.

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

rimas-kudelis commented 1 month ago

I'd just like to point out that the OpenType spec, linked in the initial post here, actually shows three different example variations of .notdef, all equally acceptable:

image

Why would you demand exactly one specific shape?

Also, the idea of removing the glyph if it exists and then replacing it with another automatically inserted glyph sounds a bit weird to me, because such process would most likely disregard font properties like it's typical character weight, width, height etc.

felipesanches commented 1 month ago

In my opinion, .notdef should be treated is a manner similar to a standardized road sign: formalized and extremely clear to recognize. It's purpose is to indicate a font problem (the font is "broken" for the purpose of rendering this specific piece of text).

So, I believe that having a single design that is widely recognized is better than having a design that blends well with the rest of the glyphs in the font.

For that reason, I think the "cute" tofu-like glyph used on Google Fonts UI was perhaps a nice touch, but still a mistake.

rimas-kudelis commented 1 month ago

I'm not talking about cute tofu-like glyphs. I'm talking about rectangles which aren't cute at all and are already recognized well enough.

felipesanches commented 1 month ago

Why would you demand exactly one specific shape?

@davelab6 said:

rimas-kudelis commented 1 month ago

Okay, that is fair enough.