Closed twardoch closed 2 years ago
Thanks, yes, this is a known issue, I think we mention also in the README https://github.com/googlefonts/nanoemoji#adding-color-tables-to-existing-fonts
cc @drott
note maximum_color
only adds a CBDT table if --bitmaps
flag is passed, so one can omit that when building the hybrid font if not desired. The Fonts API will subset and keep only one table depending on the user agent.
OK, good!
I never quite liked the hacking that went on regarding the relationship between CBDT and outline formats. The original monochrome spec for EBDT had the EBSC table, where you could describe (only within the uint8
range of ppms) if some other ppms should use another ppm range. But this table didn’t allow for specifying ranges, so a fully-compatible CBSC
wouldn’t be practical. Which I guess why Google never suggested it.
But then FreeType originally had this behavior that if CBDT
existed together with glyf
, then FreeType would only show the color bitmaps at the specified ppm, and use glyf
for all other ppms. This was, I guess, because that’s how the monochrome counterpart (EBDT
) behaved, and rightly so. But EBDT was a "fine-tuned" variant of the glyf
outlines while CBDT
provided, well, something else. AFAIR, FreeType showed the CBDT
in all ppms only if the font had no glyf
table.
Then Microsoft’s support for CBDT
was different than Android’s, I guess.
And now we’re facing this again. Prioritizing COLR
over CBDT
is sensible, and not too-many hybrid color fonts have been built in the past. I did experiment with hybrid color fonts some 6-7 years ago, putting practically all formats into one file, but I never proceeded with it — because there was no native SVG support on Apple (just sbix), and without COLRv1, any reasonable expressive font would have to pack SVG+sbix (ideally in high res)+CBDT, but that made the fonts so huge that it surely wasn’t sensible.
But now, with sbix practically out of the picture, CBDT relegated to a somewhat temporary backwards polyfill a la kern
table, we’re kind of entering the "max_color" time with at least two flavors (COLRv1 and SVG) being feasibly present in one SFNT resource. Obviously, the GF API is going to serve the right flavor only, but I’d like to see a less-hacky solution for the co-existence of the two outline flavors.
OK, in the immediate situation, some engines only do COLRv1 and some engines only do SVG. But what if someone (say Mozilla) implements both? What would be the criteria of choosing COLRv1 over SVG or the other way around, if a hybrid font is shown?
Keep in mind that it’s no easy answer. COLRv1 may be faster, and has variable capabilities, so some may think "OK, that's the better format, and SVG is just a polyfill". But on the other hand, SVG has the richer capabilities. It may combine vectors and bitmaps, so for example an SVG glyph might use a bitmap drop shadow or some intricate bitmap detail, which then the COLRv1 could simulate with simpler means.
There is a fair number of OpenType+SVG fonts already released (for example on Creative Market) which utilize SVG as a container for essentially bitmaps glyphs.
Something like Greg Nicholls’ Take Charge is actually something I hoped would emerge with color fonts, and in the end it did (I’ve used it on the BitFonter website, although as a pre-rendered image).
This type of font is a good candidate for an SVG+CBDT hybrid, but there may be others where the COLRv1 version is "80% of the intended design" and SVG is "100%" (because it adds some bitmap stuff vector content.
From the point of view of the spec and the renderers, it would be good if a font could somehow include some indicators on the preferred usage. We have the meta
table which can differentiate between "design" and "supported" languages. This rightly realizes that in some fonts, some glyphs may be done really well, and some may be stubs or generics.
Perhaps the meta
table would be the right place to specify the order of preference of implementations present in the font — it could give preference to COLR
vs. SVG
(or vice versa), and even to morx
vs. GSUB
.
But maybe it’s dumb and overcomplicated to introduce this kind of selection mechanism. In the end, we get more and more towards dynamic asset serving via the web, and even for offline use, vendors can always provide single-flavor versions. :)
It's plausible to add a PaintBitmap to allow a bitmap to be pulled into a COLR graph (https://github.com/googlefonts/colr-gradients-spec/issues/272) but we don't really have any data to help drive the decision. I don't know how many actively used ot-svg fonts exist, and of those how many are completely bitmap, completely vector, or vector/bitmap hybrids.
Optimistic hat on, perhaps a vendor with access to a lot of ot-svg fonts (is Adobe the only one?) might be willing to let us poke through them to better understand how ot-svg is actually used.
I was going to continue onboarding Blaka Ink to Google Fonts, running maximum_color
on it to add the tables as per @rsheeter’s suggestion in the email thread, only to find that the font already exists.
What’s more surprising tho is that I can't reproduce the SVG version in the same way as the one that Adam linked at the top. I used nanoemoji
from both PyPi as well as Github directly. This is how my SVG version renders in Safari (and other macOS environments such as the Finder preview):
Rod also said that running it through maximum_color
is optional, I suppose because he can maximize the color fonts properly and I can continue onboarding the simple COLRv1 font, but I wanted to alert everyone here of the fact that the conversion isn't reliable. Happy to try out anything on my end to get it to work.
Thanks for the report, sounds like a bug in maximum_color. I filed a separate issue for that.
Rod also said that running it through maximum_color is optional
Maybe I should nuance that more. Try max color, if it fails or does something dumb file a bug and proceed. In time we'll want to take a harder line but for now that tool is barely past experimental so I don't want anyones workflow to be blocked when it fails.
In re-reading this I believe there is nothing to do for this issue in this repo, the work will be done on https://bugs.chromium.org/p/skia/issues/detail?id=12945. Closing, please reopen if you believe there is something to be done in nanoemoji wrt Chrome preference for CBDT over COLR.
The BlakaInk-Regular.ttf font includes three color flavors: SVG (the
SVG
table), COLRv1 (theCOLR
andCPAL
tables) and CBDT (theCBDT
andCBLC
tables).The BlakaInk-Regular-color-multiflavor.zip contains the same font (as
SVG-COLRv1-CBDT
), and also aSVG-COLRv1
font where I removed the CBDT flavor withsfntedit -d CBDT,CBLC BlakaInk-Regular-SVG-COLRv1.ttf
.On my macOS 12.3.1:
Firefox 100.0b3
Firefox renders the SVG flavor for both fonts:
Safari
Safari Technology Preview Release 143 (Safari 15.4, WebKit 17614.1.7.7), and Safari Version 15.4 (17613.1.17.1.13) render the SVG flavor for both fonts:
Chrome Canary
Chrome Canary Version 102.0.4999.0 (Official Build) canary (x86_64) renders the low-res bitmap version (the CBDT flavor) for the
SVG-COLRv1-CBDT
font — that’s NOT GOOD:It only renders the vector COLRv1 flavor for the
SVG-COLRv1
font, which does not contain theCBDT
andCBLC
tables:So Chrome needs to be fixed — it should give preference to COLRv1 flavor even if the CBDT flavor exists in the font.
I guess this is an issue that should be filed into the Chrome project, but I’m not sure how to do it. (Or perhaps this is already filed, but feel free to add a link to this very report there).