Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding transparency info in COLR duplicates alpha in CPAL: need to be clear about interaction #10

Closed
PeterConstable opened this issue Jun 2, 2020 · 17 comments · Fixed by #46
Milestone

Comments

@PeterConstable
Copy link
Collaborator

The spec needs to be clear as to how the transparency values that go with each paletteIndex should interact with alpha values in CPAL entries. If they are combined, how they combine needs to be made clear.

@PeterConstable
Copy link
Collaborator Author

More thoughts on this: the rationale Behdad gave is that, if you need the same RGB value with multiple alpha levels, you have to expand the number of palette entries. But the counter-argument is that you end up doing the same thing regardless; it's only a matter of whether those entries live in CPAL or in COLR.

Note also that the color structure in the proposed spec is very inefficient for non-variable fonts:

  • 2 bytes for palette index
  • 2 bytes for alpha (duplicating bytes already in CPAL)
  • 4 bytes for unused variation index

20% efficiency.

Also, note: the color structures in the proposed spec occur sequentially—they're not tables referenced by offset. So, if the same palette index is used with the same alpha in two different color stops, the data will be repeated. (ColorLine is a table referenced by offset, though, so duplication of the same color line data is not an issue.)

Coming back to the rationale: supposed benefit if the same RGB is used with many different alphas. On the other hand, if the same RGB/A is used in multiple color stops (in non-identical color lines), then there will be duplication, which is a downside.

So, is there any data available to indicate how common it will be to have a given RGB with many different alphas, each used in few instance, versus the same RGB/A used in many instances?

@behdad
Copy link
Collaborator

behdad commented Jun 8, 2020

More thoughts on this: the rationale Behdad gave is that, if you need the same RGB value with multiple alpha levels, you have to expand the number of palette entries. But the counter-argument is that you end up doing the same thing regardless; it's only a matter of whether those entries live in CPAL or in COLR.

No.

The CPAL colors are exposed to users, whereas COLR are not. So your argument is false IMO.

@behdad
Copy link
Collaborator

behdad commented Jun 8, 2020

Unless you are saying that the CPAL idea of multiple and custom palettes was a bad idea, to which I agree.

@PeterConstable
Copy link
Collaborator Author

That was just one part of my comment.

There's still an aspect of duplication of Color data inside COLR. Even if we agree that paletteIndex/alpha should be in COLR, another possible approach (from what's in the draft) would be to have an array of these inside COLR, and then instead of having a Color for every stop (8 bytes) you could reduce that to a 2-byte index into that array.

The point is, there are different possible approaches, each with pros and cons. I only mean to raise the questions:

  • Have different possible designs and their pros/cons been considered?
  • Is there data available that might inform the assessment of pros/cons?

@behdad
Copy link
Collaborator

behdad commented Jun 8, 2020

You are mixing various issues. I'm happy to discuss them one by one, but not all as a pile.

Having arrays of things that are referred to by index is inherently suboptimal. It requires custom logic to compile, to use, and is an anti-pattern in my opinion that should be avoided when possible.

Currently, ColorLine is reused via offset. I have a hard time imagining that reusing Color is worth the trouble.

@behdad
Copy link
Collaborator

behdad commented Jun 8, 2020

An even worse anti-pattern is the way COLRv0 combines all layers of all glyphs into one array.

Again, I'll try to reply to other issues you filed about deviating from OpenType norms. OpenType is full of bad design. Many of which happened because they never received any widespread review. I don't think we should repeat bad design for the sake of consistency.

@behdad
Copy link
Collaborator

behdad commented Jun 8, 2020

Back to your interaction question, the two alpha values get multiplied. I don't think it needs to be specified though since that's how you paint a color with an alpha.

Again, a recurring problem with OpenType spec is that instead of specifying logic or constraints in one place and then referring to them, it copies the constraint in every reference site. For example, see khaledhosny/ots#210

Whereas name table should say "nameIDs < 256 are reserved; nameIDs > 32768 are invalid", it also goes on and at various other tables says "nameID must be > 256 and < 32768". That is BAD DESIGN. The purpose of reserving nameIDs < 256 is for future extensions of the spec. Other tables should be allowed to use any nameIDs if the referenced name is what the desire. We need to take off policing hat when designing OpenType and put on engineering hat on.

@PeterConstable
Copy link
Collaborator Author

I have a hard time imagining that reusing Color is worth the trouble.

This is why I wondered if there might be data indicative one way or another. E.g., if someone might have done an analysis of a corpus of emoji SVGs. I'm not trying to push one way or another; just noting that there are tradeoffs either way and wondering how to determine that we'll be on the right side of history.

I can imaging someone making a font with a few thousand colour glyphs and a number of them being, say, faces of different kinds but with the same gradient for the base layer of the face. However many color stops there are, the same Paint table or, at least, ColorLine could be referenced for all of them, so no duplication. But I could also imagine there being certain shades of green that recur in different pictographs of plants or food items: same shades, but not the same ColorLine or Paint.

Again, wondering, but not arguing to change.

@PeterConstable
Copy link
Collaborator Author

An even worse anti-pattern is the way COLRv0 combines all layers of all glyphs into one array.

Yes, it's not exactly typical.

@rsheeter
Copy link
Contributor

rsheeter commented Jun 9, 2020

analysis of a corpus of emoji SVGs

Working on it :) We need a few more things in place for the result to be interesting, then we'll start building and examining at least Noto Emoji and Twemoji. For example, we only just added in-glyph and inter-glyph shape reuse to https://github.com/googlefonts/nanoemoji and still need to do so for SVG if the sizes are to be in any way comparable.

Another one I'm curious about is the value of being able to have a LayerV1Record tied to a transform. We'd need to look over sample corpora to know if it's useful in reality.

@PeterConstable
Copy link
Collaborator Author

Cool! Thanks for doing that analysis.

Another one I'm curious about is the value of being able to have a LayerV1Record tied to a transform.

In the current draft spec, a transform is only used in PaintFormat3. Are you suggesting it be bumped up to the LayerV1Record so that any Paint could have a transform? (Not sure what that would add to formats 1 or 2.)

@rsheeter
Copy link
Contributor

rsheeter commented Jun 9, 2020

The current proposal has a layer that specifies "glyph x with paint y." Extending that to support "glyph x, transform y, paint z" feels fairly natural. Things like hearts, tears, hands, and the like come to mind. For example (rendering will vary by platform):

💕 🥰😻😂😹😢😿

@PeterConstable
Copy link
Collaborator Author

So applying a transform to the geometry of the referenced glyph ID for that layer, not to the gradient?

There's some sense to that idea. The constructs in COLR are in a way analogous to composite glyphs in the glyf table, and that supports a 2x2 transform for each component glyph.

The idea could potentially be extended further: We've had ideas around supporting glyf-internal variations (with variation axes not exposed to the user) to allow a composite glyph to pull in a particular instance of a component glyph. If that were supported in a future glyf update, it would equally make sense in COLR.

@PeterConstable
Copy link
Collaborator Author

Back to the original point: interaction of colorIndex.alpha and the alpha in a CPAL entry: see related discussion in the SVG table on interaction of CPAL alpha with SVG element opacities.

"When a CPAL color entry is applied to a fill or stroke property of a shape element, to the stop-color of a gradient stop element, or to the flood-color property of an feFlood filter element, then the alpha value from that palette entry must be converted to a value in the range [0.0 – 1.0] and multiplied into the corresponding fill-opacity, stroke-opacity, stop-opacity or flood-opacity property of the same element."

@rsheeter
Copy link
Contributor

Assuming optimistically we merge some variant of #37 are there remaining concerns here? - seems to me it gives sufficient freedom that a compiler can do a pretty good job of optimizing reuse of things.

@davelab6 davelab6 added this to the COLRv1 milestone Sep 18, 2020
@rsheeter
Copy link
Contributor

Upon re-reading I believe #37 has resolved the discussion of reuse, transforms, etc. The only remaining issue appears to be adding a note to clarify the ColorIndex alpha is multiplied into the CPAL color. This is standard for alpha handling but I don't think there is any harm in adding a note.

@rsheeter
Copy link
Contributor

Please reopen if the update is unsatisfactory

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants