colr-gradients-spec
colr-gradients-spec copied to clipboard
Strawman for COLR without CPAL
COLR has long been understood to stand for Composition Of LayeRs :D
Idea is that if CPAL is absent you can safely assume the font paints only the foreground color, much as glyf
or cff
do today. The intent would be to make it plausible for an environment that rejects COLR entirely today to accept it when CPAL is absent.
Inspired by #88.
Edit: I'm increasingly convinced this is a solid idea; removed note about just playing with the idea.
I'm really not convinced that COLR without CPAL is a good idea. Some of the structures we've defined for COLRv1 would be useful for composite glyph descriptions, but I don't think using COLR itself for that purpose is the right approach. I see at least the following issues here:
- Some parts of the COLRv1 formats simply would not be useful for composite monochrome glyph descriptions, and so parsing of COLRv1 would need to be different depending on the context.
- It would conflate two different things into the one table, adding complexity in tooling or in interpreting data in COLR.
- It would create a significant new vector for introducing cycles in the graph: PaintGlyph. That's an added complication when rendering either monochrome or colour glyphs. (It might be inevitable with an extension to monochrome composites, but it doesn't need to be added to COLR processing.)
- Any extension for new monochrome composites will end up resulting in fonts that aren't supported in existing software. If the extensions were, say, in a new glf2 table, then it would be obvious: an existing rasterizer simply wouldn't attempt to render that font. But if an extension is using a combination of existing glyf and COLR tables, then existing software would attempt to render the font producing garbage display results.
@behdad pointed out that rasterizers support foreground+opacity already due to anti-aliasing so I think I've gone too far in my limitations; will revise.
Thinking "aloud", we'll need to review compositing modes to see if any take you to places outside of what you can reach via foreground+opacity. My instinct is that only the non-separable modes are likely to have that issue.
@PeterConstable let's recast this as simply allowing COLR to exist w/o CPAL. I will update to reduce the limitations and we can see if that makes things feel better.
My instinct is that only the non-separable modes are likely to have that issue.
That was my hunch as well. But looking into it, I think all blend-modes are problematic; so only the Porter-Duff compositing modes with normal blend are find. To be verified.
I commented on this in issue 88: I think only the Porter-Duff modes would be relevant for monochrome since the channel values for source and backdrop would always be the same.
I think Peter's last point there is worth discussing. I don't quite follow, peter - isn't this true of any COLR v0 renderer seeing v1 data?
I think all blend-modes are problematic
Agreed; https://www.w3.org/TR/compositing-1/#blendingnormal might be ok but we didn't add that as a composite mode.
PR updated to say COLR without CPAL is ok but you can't have blend modes.
I think Peter's last point there is worth discussing. I don't quite follow, peter - isn't this true of any COLR v0 renderer seeing v1 data?
If an app supports COLR v0 and encounters a COLR v1 colour font, it will ignore any v1 data that it doesn't recognize. Either one of two things happens:
- If the font has some COLR v0 data (as well as v1), the app can display those colour glyphs; it will display the monochrome glyphs for all other glyphs.
- If the font has only v1 data, the app won't see no colour glyph data and display the monochrome glyphs for all glyphs.
So, the app displays reasonable text, it just doesn't utilize the latest capabilities of the font.
if an extension is using a combination of existing glyf and COLR tables, then existing software would attempt to render the font producing garbage display results
So, the app displays reasonable text, it just doesn't utilize the latest capabilities of the font.
It might display reasonable text, subject to the font author spending development time and filesize on good base glyphs.
IIUC the key capability you lose by using COLR vs a new table is that you can't cause a renderer to skip over the font entirely as you could with an entirely new outline table (only true if that table replaces the existing one, if it augments it you have similar problems). That's a tradeoff, but potentially a good one. Do we really want a new table to define outlines, as opposed to adding more sophisticated ways to reuse outlines from the tables we already have? - I like that COLR chose to augment rather than replace what existed before.
Speculating about potential users of COLR for components:
- An OS can have a pretty good idea about what it supports and likely wouldn't ship a font in its stack it knew didn't work.
- A network delivery system can choose to send an alternate version (a less compact glyf/cff equivalent or bitmaps depending on what COLR capabilities were used) to some clients.
- Anything where you need to embed the font and be confident it works on another rendering environment (off-hand pdf, word, printing) might need a way to make an alternate version to embed, a simplified subset if you like
Thinking out loud. Considering:
Some parts of the COLRv1 formats simply would not be useful for composite monochrome glyph descriptions, and so parsing of COLRv1 would need to be different depending on the context.
It would conflate two different things into the one table, adding complexity in tooling or in interpreting data in COLR.
if an extension is using a combination of existing glyf and COLR tables, then existing software would attempt to render the font producing garbage display results.
vs.
If an app supports COLR v0 and encounters a COLR v1 colour font, it will ignore any v1 data that it doesn't recognize. Either one of two things happens:
If the font has some COLR v0 data (as well as v1), the app can display those colour glyphs; it will display the monochrome glyphs for all other glyphs.
If the font has only v1 data, the app won't see no colour glyph data and display the monochrome glyphs for all glyphs.
I think that successful deployment of COLR without CPAL depends on three separate (and somewhat independent) parts of the approach:
- the quality of font design - we've seen plenty of examples when good creative thinking combined with limited existing tools produces wonderful results that push the boundaries of what we considered possible! At the same time, there are plenty of examples of bad designs that simply do not work right.
- the robustness of font tools that translate the design intent into a set of font tables. When the design intent is known, there can be a lot done with the right tools doing the right job, and accounting for limitations of COLR for composite monochrome glyph descriptions could definitely be part of the process.
- the resilience of implementations that need to interpret any possible combination of font tables presented for rendering. I don't think that implementations should be responsible for second-guessing design intent in an attempt to fix what could be a mistake. We just need to make sure that the spec provides a clear guidance on what can be done, and then just let implementations do what they already do - ignore the data that they don't recognize or do not understand, and attempt to render what they can.
I may have misunderstood what others have in mind here. But it appears the suggestion is that there would be two distinct processing modes that involve different validations, hence additional code complexity in implementations.
Suppose we had COLRv1 implementations for the design and functionality in mind before COLR w/o CPAL was considered. With that, a font could be created using COLR v1 formats and a CPAL table that has exactly one palette entry specifying 0xFFFF (foreground colour). COLR v1 processing could be applied normally without needing any special validations. Certain things non-alpha gradients, blend modes) might not be useful, but they would not likely be used for that reason, and also aren't harmful.
In terms of achievable visual results, it seems that would provide the same as what you all have in mind for COLR w/o CPAL. In that case, what benefits would we be after by spec'ing COLR w/o CPAL and two distinct processing modes?
I may have misunderstood what others have in mind here.
I think you are. For a client that implements the colorful model, there's no modification needed whatsoever. We are however, sanctioning conditions that a COLRv1 font can constrain itself to, to be usable in colorless contexts.
Suppose we had COLRv1 implementations for the design and functionality in mind before COLR w/o CPAL was considered. With that, a font could be created using COLR v1 formats and a CPAL table that has exactly one palette entry specifying 0xFFFF (foreground colour).
You seem to have misunderstood the COLR/CPAL model. 0xFFFF is used in lieu of a palette entry index...
You seem to have misunderstood the COLR/CPAL model. 0xFFFF is used in lieu of a palette entry index...
Fine, small memory lapse. Revise my scenario to the font having a CPAL with whatever (or no) entries, with only palette entry index 0xFFFF used.
We are however, sanctioning conditions that a COLRv1 font can constrain itself to, to be usable in colorless contexts.
So, in implementation contexts that don't support colour, but that support this different usage of COLR. What's the benefit of having the relevant data in the COLR table versus using a subset of the formats in a distinct table for this particular purpose?
Also, suppose the graph contains a PaintGlyph, but that glyph ID has an entry in the BaseGlyphV1List: Does the graph then incorporate the graph for that glyph ID (i.e., PaintGlyph now duplicates the functionality of PaintColrGlyph)?
What's the benefit of having the relevant data in the COLR table versus using a subset of the formats in a distinct table for this particular purpose?
The intent of the proposed change is a small subset of COLR is excised in a scenario where it doesn't make sense, IMHO not enough to justify forking the table. If we were stripping out and modifying COLR substantially I'd agree with making a new table.
Intended benefit is ease of implementation for people who support both modes and lack of an almost duplicate table. If you add another table that supports non-color glyphs, can it be a base glyph for COLR? - I think things get weird with two tables that are mostly identical.
suppose the graph contains a PaintGlyph, but that glyph ID has an entry in the BaseGlyphV1List: Does the graph then incorporate the graph for that glyph ID
I don't see a need to change the behavior of PaintGlyph? - COLR is still built on top of an outline table, PaintGlyph still sources from there.
I don't see a need to change the behavior of PaintGlyph? - COLR is still built on top of an outline table, PaintGlyph still sources from there.
But isn't the point to have a new way to define composites? In a colour font, a PaintGlyph could reference a glyf entry that is a composite, and the outline of the composite glyph is used as a clip path. But now we want a different way to define composites.
So, suppose (for sake of discussion) GID 42 is to be a composite defined using the COLR mechanism. It has an entry in the BaseGlyphV1List. But suppose I also want to use that composite outline as a clip path in another COLR glyph definition. I can't use outline data for gid 42 from the glyf table since any outline data there is not the composite outline that I want.
And what does glyf entry 42 contain anyway? For the COLR definition, we require it to have a bounding box. So, maybe it has two points for diagonal opposite corners. But then it's not a composite from the glyf perspective; how does the app know that it should not use that glyf data directly? Does it just see that there's a COLR without CPAL and then, based on that heuristic, it's expected to look first for GID 42 in a COLR BaseGlyphV1List and, only if not found there, then look at the glyf data?
If so, is such an implicit heuristic what we want to use in the format going forward, rather than explicit declarations?
But isn't the point to have a new way to define composites?
Maybe "composite" is a bit overloaded in the font context. I see this as looking at what we did for COLR v1 and realizing what we have is useful for non-color (only foreground + alpha) scenarios if we do two things:
- Offer a well defined way to indicate this font shouldn't be deemed colorful (today COLR == colorful according to https://github.com/googlefonts/colr-gradients-spec/issues/3#issuecomment-690847840)
- This PR proposes (as suggested by @behdad in https://github.com/googlefonts/colr-gradients-spec/issues/88#issuecomment-742830535) that COLR without CPAL indicates a non-color (drab?) nature
- Ensure we really are non-color when CPAL is absent
- We have given the user tools to reach colors that violate our definition of "non-color" so we take those away when non-color
Maybe "composite" is a bit overloaded in the font context....
I get that much. I definitely see value in leveraging parts of COLRv1 for monochrome fonts; especially
- P-D compositing modes
- transforms
- variation integration for transforms
- re-use mechanisms
I'm just not yet convinced by the approach (e.g., compat issues).
For the scenario I mentioned, using a COLR "composites" as a clip region, you'd have to add to descriptions of PaintGlyph that, in a +COLR/-CPAL font, when a PaintGlyph is encountered the app must look for a COLR definition for that glyph and, if present, compute the outline for that glyph, then use that as the clip path. Unless we don't want to allow that (it might be that the same results could always be achieved in a slightly different way that utilizes PaintColrLayers or PaintColrGlyph), in which case some additional validation might be needed to say that a PaintGlyph must not reference a glyph that is a COLRv1 base glyph.
using a COLR "composites" as a clip region
I would have expected this to be done via PaintComposite with no change to the definition of PaintGlyph but perhaps I'm missing a reason that doesnt' work?
PaintComposite takes rendered source and backdrop bitmaps and combines them. PaintGlyph provides a clip path. The scenario I'm referring to would be if the glyph outline you want for the clip path is something constructed using COLR.
As I say, it may be that the desired result can always be obtained by extending the graph in some way and not referring to a glyph using PaintGlyph. But in any case, it seems like something would need to be said about a case in which a PaintGlyph refers to a GID that itself is a base glyph in the BaseGlyphV1List.
PaintComposite takes rendered source and backdrop bitmaps and combines them. PaintGlyph provides a clip path.
I think I'm beginning to see. A few thoughts that may or may not help :)
- The authors intent was that PaintGlyph "Paint a non-COLR glyph" (from https://github.com/googlefonts/colr-gradients-spec#c-structures)
- I don't immediately see that we need to change that intent
- 5.7.11.2.5.5 says it shall be a valid gid with an outline in glyf, cff, or cff2; maybe that should be more explicit that it does not reference COLR glyphs?
- I don't think we should fixate too much on PaintGlyph clipping being different than a clip via PaintComposite (e.g. Source In)
- Think of it as described in the C++ structures (non-ISO content) section:
// Paint a non-COLR glyph, filled as indicated by paint.
- PaintGlyph could be implemented using the composite operations if one really wanted.
- Think of it as described in the C++ structures (non-ISO content) section:
- I'm not immediately seeing a reason the PaintGlyph clipping would be superior to PaintComposite?
- Bear in mind an implementation doesn't have to compute PaintComposite as two bitmaps getting merged. For example, it could recognize it would be better setup a clip path in some cases.
- If there is a problem here I don't think it's limited to the COLR without CPAL scenario
- Using a COLR glyph to clip or mask another COLR glyph should be achievable regardless of CPAL presence
That leads me to think that if there is a problem we should file a separate issue for it because the problem exists regardless of whether COLR is valid without CPAL.
Per VC with Peter, Cosimo:
- 5.7.11.2.5.5 should spell out that it does NOT match COLR glyphs
- 5.7.11.2.5.11 should say "conceptually" rendered into two bitmaps
I'm still against saying color index is ignored and 0xFFFF assumed.
Here's counterproposal: keep out-of-bounds color indices illegal. Make a nullptr Paint offset mean a solid foreground paint. That saves much more.
Per VC with Peter, Cosimo:
* 5.7.11.2.5.5 should spell out that it does NOT match COLR glyphs
PR #216
* 5.7.11.2.5.11 should say "conceptually" rendered into two bitmaps
Commit added to PR #214
Make a nullptr Paint offset mean a solid foreground paint
Much better, made it so, thank you.