w3c/css-houdini-drafts

[css-paint-api][css-typed-om] Current Color as an input to paint worklets

nucliweb opened this issue · 7 comments

Hi!

I want to use Paint API to generate a random background-color in an element, but I would like to get the currentColor of context to generate a random color with contrast.

Can I access to the currentColor?

Thanks

If your paint module code specifically wants the current color (ie, to always match current color), you can declare a dependency on the color property via the inputProperties getter.

However, it gets more complicated if your module is dependent on another color input (a parameter, custom property, or another property like border-color) & the website CSS uses currentColor as the input value. Since currentColor is a valid computed value, that styleMap that gets passed to your paint code will only have the keyword, instead of the final used color.

If you try to use the keyword directly in your painting code, it's currently specified to behave as solid black. Which is surely not what you intended when you passed currentColor as a parameter to your paint function.

Exactly, what I want is to be able to obtain the computed color of currentColor, since it would be the inherited color. I do not want to have to force to indicate the color in the element where the Paint API is being used.

Thanks @AmeliaBR

Btw, I tried to access to `styleMap` in Chrome but I don't get anything.

Btw, I tried to access to styleMap in Chrome but I don't get anything.

The name styleMap is just an example from the specs, the name you use will depend on how you name the parameters in your paint function. In the examples later in the spec, they are named properties. Either way, it is the third parameter passed to your paint function.

That allows you to get a CSSStyleValue object representing the color value. But, the Typed OM spec doesn't yet define a specific type for a CSSColorValue object, so you need to parse the string value yourself.

I put together a demonstration, to test out how difficult it was to do (parsing the color string is the worst part) & to see how an explicit currentColor value messes things up:

Chrome, it turns out, still returns RGB values for currentColor, so there's nothing special there. (This isn't Paint-specific, you can also see it if you call computedStyleMap() on the element from the main document.) But, if they matched the spec and returned currentColor as a CSS keyword value, then you wouldn't be able to do any color math whatsoever.

Thinking over what to do about this when we actually do define CSSColorValue types:

currentColor is defined to be a keyword at computed time so that it inherits as a keyword. But there isn't any reason that the actual color value can't be known at computed time. Maybe it would be better to think of currentColor in Typed OM as a full color object (e.g., that represents a specific RGB color) that also has a flag that says "but this is a currentColor special color" for inheritance and serialization.

Until we figure out the best way to handle CSS colors that inherit as keywords (which may one day include other keywords), I think we should remove all the property-specific rules in CSS Typed OM that require currentColor to be returned as a CSSKeywordValue object.

There's clearly no web-compat obstacle to changing it at this point. And we may have web compat problems in the future if Chrome tries to follow the current spec, since that would break paint worklets that are using currentColor as a value to regular CSS properties that are then input into the worklet.

I don't know what an ideal Typed OM representation of currentColor (or buttonFace) will be, but I think it should be a subclass of a CSSColorValue object, not a generic keyword. (Also, if the decision is to handle it as a keyword, that shouldn't be dealt with via "property-specific rules", but by general rules for handling computed values of colors.)

Thanks a lot @AmeliaBR, for the extended explanation and for the great example 😊

You're breathtaking 🤘🏼

Agenda+ to discuss this.

There's no reason we couldn't give the painter used-value colors; it's an endpoint and that's fine and appropriate. (It's how all the other built-in painters work.)

However, we don't have the infrastructure set up thru the specs to generally give access to a UsedStylePropertyMap object; that requires a lot of design work to rigorously define used values in all circumstances.

We might be able to offer color-resolving abilities thru a TypedOM API; it just needs an element for context, so it can check 'color' and 'color-scheme'.

Worst case, we can offer a special-purpose API to the PaintWorklet that resolves colors for you.

We have two factors at this point to consider:

  • Web compat with existing content built for the shipped Chrome implementation, that expect the toString() result of the CSSStyleValue object for color properties to always return an rgb() or rgba() function. (Most such content wouldn't need to parse the function like my demo did, but they would need it to be valid when used directly to set a canvas API color property.)

  • The long-term goals of (a) having currentColor inherit as a keyword on all browsers, and (b) having a useful CSSColorValue object that can represent all color syntaxes (keywords and functions) and maybe do useful things like converting between function types.

I think these constraints can be satisfied if we say that:

  • currentColor is first and formost a color value, rather than a generic keyword. In Typed OM, it will be represented by CSSColorValue, just like other color keywords will be, not by CSSKeywordValue.

  • the future CSSColorValue type will have some way of associating it (maybe an internal slot, maybe exposed by the API) with an palette of resolvable values for currentColor and the system color keywords, and these values will automatically be filled in when the color value is part of a computed style.

  • the stringifier for CSSColorValue should return resolved rgb/rgba values whenever possible, using the associated element palette if it exists.

Worst case, we can offer a special-purpose API to the PaintWorklet that resolves colors for you.

This is an alternative. Or just allow the paint context APIs to take contextual color keywords and resolve them against the element being painted.

The CSS Working Group just discussed Current Color as an input to paint worklets, and agreed to the following:

  • RESOLVED: Specify that the PaintWorklet's canvas-ish methods can take color keywords and do the right thing
  • RESOLVED: Fix Typed OM spec to ensure that currentcolor and system color keywords reify as CSSStyleValue, not CSSKeywordValue, until we have CSSColorValue for them to reify as.
The full IRC log of that discussion <dael> Topic: Current Color as an input to paint worklets
<dael> github: https://github.com//issues/921#issuecomment-546459060
<dael> AmeliaBR: Related to what we talked about earlier. About CurrentColor having a computed value of the keyword
<dael> AmeliaBR: For typedOM it's supposed to expose computed values, not resolved. TypedOM doens't have a proper model for a color value so for the Houdini APIs that are getting computed values using TypedOM objects they're jsut getting the superclass version.
<dael> AmeliaBR: The issue is what happens if your Paint API relies upon a color property and author uses CurrentCOlor. Example: Use Paint API for a fancy border and relying on border color property. What happens if border color is default currentColor?
<dael> AmeliaBR: IN Houdini currently that's exposed as a keyword and then in your Paint worklet you'd need to depend on color to get the keyword's value
<dael> AmeliaBR: IN shipped Chrome the value exposed isn't a keyword but it's where two string is rgb function which means current Paint worklets are happily using that as a color string they can pass to canvas. but it doesn't match spec
<dael> AmeliaBR: Suggestions are first we change the spec to not talk about currentColor as a keyword which means for now currentColor is treated as a vague superclass where all youg et is a string. Eventually when we have a color value class defined currentColor would be represented in the class same as any other color type.
<dael> AmeliaBR: Somehow at time we define this we make sure two string value always gives us rgb function when applied to computed style object
<dael> TabAtkins: Want to avoid inventing new resolved style. As much as possible I'd like to keep computed style map returning computed styles. That means Chrome impl is wrong and needs to be changed
<dael> TabAtkins: Happy with currentColor becoming a CSS color value. It's compat with that. I don't want to have the value coming out of computed style map be a used value.
<dael> TabAtkins: It is clunky, but I prefer to provide a function that lets you resolve color values in Paint worklets
<dael> AmeliaBR: Other option is to say Paint worklet knows how to resolve keyword values. Covers most cases where someone grabs computed style and uses it directly in the Paint commands. So long as whatever string from typed OM is valid in Paint commands covers most use cases. Wouldn't cover parse and do math, but that's rarer
<dael> TabAtkins: Sounds good too. WE can cover all use cases by having Paint API canvas painting methods be able to take contextual keywprds directly and have Paint worklet have a function to manuallyr esolve colors into rgb for you. Then keep computed style map actually a computed style
<dael> AmeliaBR: Are you okay...right now there's text in Typed OM that curretnColor is a css value keyword object can we say it returns as superclass css value type even if string reflects string of keyword until color models are specced?
<dael> TabAtkins: Yes, I think we should
<dael> TabAtkins: Need to make sure system colors do same thing
<TabAtkins> 1. Specify that the PaintWorklet's canvas-ish methods can take color keywords and do the right thing.
<dael> AmeliaBR: Actual change at this point would be remove all property specific rules in typed om that require currentColor to be returned as a css key value
<TabAtkins> 2. Add a PaintWorklet global function that can resolve color keywords into RGB.
<dael> AmeliaBR: Separate note for Chrome impl to match spec as far as returning computed values which happens at same time as change to paint API which allows keywords to be used in the paint color properties. That's the other normative change
<TabAtkins> 3. Fix Typed OM spec to ensure that currentcolor and system color keywords reify as CSSStyleValue, not CSSKeywordValue, until we have CSSColorValue for them to reify as.
<dael> smfr: Other cases where authors want to convert currentColor to rgb? Only Paint worklets sounds limited
<dael> TabAtkins: Problem is that if we want computedStyleMap to return computedStyles we're going to have these cases where some values at time being passed can't be resolved further because of state. Layout worklets might want this. OTher worklets are in the same boat.
<dael> TabAtkins: Similar to resolving % and other use time values that are useful.
<dael> TabAtkins: Colors are resolvable jsut after inheritience so might be a special case that's handled badly by concept of computed values
<dael> TabAtkins: UNless we define a 4th value mode and say computed style map returns that I'd rather less conevnient but consistent rather then arbitrary mismatch
<dael> AmeliaBR: smfr had good point about universal way to get resolved color keywords relative to context elements
<dael> AmeliaBR: WOuld expect that's part of spec how colros work in TypedOM and also part of other color format conversations
<dael> AmeliaBR: With that in mind maybe don't do gloabl function in Paint worklet.
<dael> AmeliaBR: What we do need in short term is simple case within PAint workelt if you use currentColor it works correctly
<dael> TabAtkins: Issue with resolve agaisnt element wedon't pass anything that's an element into a worklet. Can implicitly resolve with a context. I think works for custom Functions
<dael> AmeliaBR: Model I suggested in issue for resolving values is that the computed color value object is associated with a palette that defines what color values represent for keywords so it's passed in at that time
<dael> TabAtkins: At computedv alue time we don't know that yet. You could say here's the possible values, but you don't know what it ends up as. Unless we have anothe value stage between computed and used we can't express that in a meaningful way
<dael> AmeliaBR: When you know computed values you also know value for color and color shceme. From those you know the palatte that desc what kewyrods mean for any other color property
<dael> TabAtkins: I think you're right. I take it back. We can call this a computed value that knows it's a keyword, but it knows what it will turn into b/c we know other valyes
<dael> TabAtkins: Implies new dependency edges and need to think about how to do those
<dael> TabAtkins: I do think there's a path forward
<dael> TabAtkins: THe used value time colors should downgrade to generic supercalss. Paint API takes those and acts appropriately. I'll work on how to solve getting you the colors properly
<TabAtkins> 1. Specify that the PaintWorklet's canvas-ish methods can take color keywords and do the right thing.
<dael> TabAtkins: I listed several things, I'll put 2 to resolve on
<TabAtkins> 2. Fix Typed OM spec to ensure that currentcolor and system color keywords reify as CSSStyleValue, not CSSKeywordValue, until we have CSSColorValue for them to reify as.
<dael> AmeliaBR: Do the right thing means when you use...
<dael> Rossen_: I jsut wanted to know if we were resolving. If not, we can just resolve on these
<dael> Rossen_: propsed resolution 1 is Specify that the PaintWorklet's canvas-ish methods can take color keywords and do the right thing
<dael> Rossen_: Objections?
<dael> AmeliaBR: Do we understand do the right thing in this context? It's using context of element you're painting
<dael> RESOLVED: Specify that the PaintWorklet's canvas-ish methods can take color keywords and do the right thing
<dael> Rossen_: Second is Fix Typed OM spec to ensure that currentcolor and system color keywords reify as CSSStyleValue, not CSSKeywordValue, until we have CSSColorValue for them to reify as.
<dael> fantasai:This is change to typed OM?
<dael> TabAtkins: Yes. Currently says it's css keyword and we're going to superclass instead
<dael> fantasai: Wasn't point of typed OM is when you ask for comptued you get computed
<AmeliaBR> s/css keyword/CSSKeywordValue/
<dael> TabAtkins: Yes, which is currentColor keyword. But we used the superclass when we don't have something represented specifically
<dael> fantasai: It's a keyword but expose as somethign else?
<dael> AmeliaBR: As a generic css computed value where all you can do is expose the string
<dael> fantasai: Okay, gotcha.
<dael> Rossen_: Prop: Fix Typed OM spec to ensure that currentcolor and system color keywords reify as CSSStyleValue, not CSSKeywordValue, until we have CSSColorValue for them to reify as.
<dael> Rossen_: Objections?
<dael> RESOLVED: Fix Typed OM spec to ensure that currentcolor and system color keywords reify as CSSStyleValue, not CSSKeywordValue, until we have CSSColorValue for them to reify as.
<dael> AmeliaBR: All other things will turn into a proposal for L2
<dael> TabAtkins: Or L1, but later.