When using an acrylic brush, there is math applied to the color value, tint value, and luminosity value that change these values to make the acrylic work more like rs4 acrylic - this conversion changes our desired results, and means designers literally cannot achieve their designs - the values they hand off to code do not get reproduced by the brush. not only that, because there are value caps in place, certain values are not achievable at all.
This conversion logic is not desired by designers, and is almost entirely unknown so it cannot be worked around by many. This needs to be an option to opt in or opt out option, or a new version produced that does not have this conversion built in so expected results can be achieved.
The conversion is not documented, and is currently ignored by MS! Lets fix this to make design achievable and the brush simpler!
Describe the bug
There is "auto-magic" logic built into the current Acrylic brush (that was put in place to replicate the RS4 acrylic visual appearance at the time), that now conflicts with the contrast ratios needed in order to pass WCAG 2.1 accessibility requirements.
This logic affects the color of the luminosity blend mode and the tint color properties and sets them automatically based on the tint color of the brush.
Steps to reproduce the bug
Steps to reproduce the behavior:
TintLuminosityOpacity
to below #202020 and observe that it will lock at that value instead, regardless of what you put it's hex color value to.Expected behavior
If TintLuminosityOpacity
property is set, then all automatic RS4 logic will be be ignored, and the values specified by the user will be set in the brush 1:1.
Screenshots
Version Info
NuGet package version:
| Windows 10 version | Saw the problem? |
| :--------------------------------- | :-------------------- |
| Insider Build (xxxxx) | 19493 |
| May 2019 Update (18362) | |
| October 2018 Update (17763) | |
| April 2018 Update (17134) | |
| Fall Creators Update (16299) | |
| Creators Update (15063) | |
| Device form factor | Saw the problem? |
| :-------------------- | :------------------- |
| Desktop | yes |
| Mobile | yes |
| Xbox | yes |
| Surface Hub | yes |
| IoT | yes |
Per email discussion it sounds like the request is to do the color adjustment only when TintLuminosityOpacity = 1.0. If TintLuminosityOpacity < 1 then don't adjust the color. Seems simple enough? Adding help wanted. :)
Its this, if no TintLuminosity value is supplied, letconversion logic is applied, if any value at all is supplied (0 - 1.0) do not use the conversion logic.
Cheers,
S
@jevansaks, that's correct. Please see the Expected Behavior section of this bug - tried to supply the behavior desired.
Hi Kiki, just pinging y'all on this!
S
Hi @SpencerHurd , I would like to look into this issue, however I am not quite sure how I would be able to test/verify a suitable fix. Do you have a demo or a code snippet that I could try or use?
Also I assume with LuminosityTintColor
you mean TintColor
?
Thanks @spencerhurd - in the future please refrain from posting internal email on issues - just for other people's privacy. :)
I have not been able to loop back on this since you first requested it. So I have no updates.
@chingucoding - he's actually referring to the property on Acrylic called TintLuminosityOpacity
- which I now realize is a bug in the initial report above, I will fix.
@kikisaints Thanks for the clarification!
I鈥檓 sorry I don鈥檛 know what you mean? I filed the big the way you wanted, then emailed you to follow up on it 馃槉.
How do we get this tackled? This is causing accessibility problems.
S
Hi @chingucoding! Fantastic you are interested in helping, thank you so much! Sorry for the delayed response - I was figuring out how to use Github.
The issue: its kind of hard to describe whats happening. I am a designer and cannot refer to the code of it. But Ill describe it as best I can. The acrylic brush has is comprised of a few layers that stack together to create the effect, from top to bottom:
When using the brush, developers may supply a tint color, a tint opacity, and a luminosity opacity.
The tint color is supplied by the develop and fed to the color value in both the #2 Tint layer, and the #3 Luminosity layer. However the luminosity layer caps how bright and dark the color can get (it cannot get to black or white).
The tint opacity is supplied by the developer, then the brush adjusts it via some fancy math, and the new value is fed to the #2 tint layer (the value you input is not the value used by the brush).
The luminosity opacity is an optional value, if it is not supplied by the developer then the opacity is mathematically derived from the tint color and opacity. If it is supplied then the value provided by the developer is fed directly to the #3 luminosity layer unaltered.
So there is a lot of mathematical stuff happening inside the brush that changes the values supplied to the brush. There is a reason for this - all the conversions and adjustments occur in order to make the acrylic brush look like the original acrylic brush. However the bug is this: when the luminosity opacity value is supplied, all the fancy math logic should not be used. When luminosity opacity is provided by the developer we don't want it to look like the original acrylic, we want the values provided used unaltered by the brush.
So: if no luminosity opacity value is supplied, leave the current system in place.
The following should happen
I hope this helps!
Spencer
@SpencerHurd Thank you for the detailed explanation! This sure helps a lot. So the expected behavior is the following:
_No luminosity opacity specified:_ Color will be taken if V (from HSV) is between 0.125 and 0.96, otherwise take the closest of those values.
_Luminosity opacity specified:_ Take opacity and color as is, no "bounds" checking. (Currently this case also does bounds checking, which is not what we want)
Is this correct?
If that's the case, I would like to fix this, as long as its fine with @jevansaks, @kikisaints and @ranjeshj .
@chingucoding your summary is correct to my understanding of the problem. If you'd like to go ahead and take this bug/issue, that's more than okay with me :smile: design has been looking forward to this change for a little bit now.
@chingucoding What you are saying is correct, if _Luminosity Opacity_ is specified then we want to remove the bounds on the luminosity color value so it inherits the tint color value unaltered. We also want to make sure tint opacity uses the supplied _tint opacity_ value unaltered.
Very cool, thank you!
From the source code, it seems like the tint opacity does get in fact get altered, when we use it for the tint layer:
For the luminosity layer, we are using the "raw" value i.e. we take the tint color and set its alpha value to the tint opacity value, and then continue calculating the luminosity color.
Is this what you would expect @SpencerHurd ?
Lets see 'm not 100% sure.
Once luminosity opacity is supplied:
So we want to remove all adjustments to values if _luminosity opacity_ is supplied by the dev.
Tint Color = Original Tint Color
Tint opacity = Original Tint Opacity
Luminosity color = Original Tint Color
Luminosity Opacity = Original Luminosity Opacity
Does that answer the question? From how I understand what I'm seeing (I'm sorry I don't know code :/), the tint opacity is being altered, and the luminosity layer is being affected by the tint layer opacity. I suspect the brightness cap is also still in play on luminosity color.
It's important to call out, since we don't want to eliminate any pre-existing behavior that app developers may be relying on, that:
Yes the only case where we want to change stuff is when luminosity opacity is actively set.
Yes this whole maths is a bit complicated. So summary:
The Luminosity layer should behave the following:
tint color
, tint opacity
and luminosity opacity
all unmodifiedThe other layers are already correct as they are. Is this correct @SpencerHurd and @kikisaints ?
@chingucoding that looks correct to me. That you for summarizing.
That is correct! Love it! thanks for stating it so simply.