For a web app I need a way to prevent that a browser falls back to another font if my web font doesn't include a character. It seems the only way to do this is to add another font to the fontstack which includes "all" possible characters .
There are already existing fallback fonts, but those are more debug helpers as they show the codepoint as number, therefore they are much to heavy (>2MB).
The fallback font for my use case should just show something like a box to signal a missing character.
My idea was to generate a simple font with only one glyph and apply a feature file which will substitute all glyphs with this one.
My script for fontforge:
import fontforge import fontTools.feaLib.builder as feaLibBuilder from fontTools.ttLib import TTFont font_name = 'maeh.ttf' font = fontforge.font() glyph = font.createChar(33, "theone") pen = glyph.glyphPen() pen.moveTo((100,100)) pen.lineTo((100,500)) pen.lineTo((500,500)) pen.lineTo((500,100)) pen.closePath() for i in range(34, 99): glyph = font.createChar(i) glyph.width=10 font.cidConvertTo('Adobe', 'Identity', 0) # doesn't make a difference font.generate(font_name) font = TTFont(font_name) feaLibBuilder.addOpenTypeFeatures(font, 'fallback.fea') font.save("fea_"+font_name)
My feature file:
languagesystem DFLT dflt; @all=[\00035-\00039]; #@all=[A-Z] this works feature liga { sub @all by theone; } liga;
For testing I target not 'all' glyphs, only the range from 33-99.
But the above results in a
KeyError: ('cid00037', 'SingleSubst[0]', 'Lookup[0]', 'LookupList')
with changing numbers for cid00037
.
If I use the out commented class definition A-Z from the Feature file it works, so this approach doesn't seem to be completely wrong. But how to create a class this way which includes 'all' possible 'glyphs'.
Why can't fonttools find the glyphs if I specify the range in CID notation? Is there another way to crate a class for the OpenType feature file which includes all glyphs?
I use 'liga' in the feature file as this seems to be the most supported tag. Is there a more appropriated one.
Comments
Wouldn’t it make more sense to build a CMAP table that maps all possible codepoints to a single glyph outline?
Since then, Ken Lunde created Adobe NotDef which does the same thing. Set it as the fallback font immediately after your font. Ken wrote an introduction post about it.
At Jeff Kellem, thank you for hint, because that is just what I was looking for and what I would have tried to accomplish with the Adobe Blank. But my result wouldn't have been as compact as this one and this way I will save time of course. And your link to the Blog helped to understand why the Blank font is structured as it is.
To create the woff file I used sfnt2woff from the woff-tools package. For the woff2 file I used https://github.com/google/woff2.
As Georg says, these fonts have very unusual, carefully optimized (sometimes by hand) internal structures.
Blank solution (prevent to type/copypaste unacceptable characters):
https://jsfiddle.net/pj2sbcz1/
NotDef solution (replace unacceptable characters with .notdef glyph):
https://jsfiddle.net/9n5oeaLm/