~eliasnaur/gio#169: 
Material switch widget track is invisible on a white background

So I'm working to understand why the material.Switch track is now invisible when rendered atop a white backround (this makes the whole switch almost invisible, though you can see the "head" of the switch as a faint gray circle).

git bisect reveals that it occurred in this commit:

commit 4bab6fcf322d4b5fc0e2e6fd3132965fea6aefa5
Author: Elias Naur <mail@eliasnaur.com>
Date:   Mon Sep 28 09:02:38 2020 +0200

    internal/f32color: add colorspace-correct function for alpha scaling

So after some digging, I think I might understand the issue. It's here.

Using f32color.MulAlpha to alpha-premultiply the color seems like it ought to work, but it results in an invalid alpha-premultiplied color (R,G, and B are all higher than A). Looking further, this implementation appears to return colors in SRGB, whereas gio's paint.ColorOp expects linear RGB.

Additionally, as I think about it, I'm not sure I follow why we are using alpha to derive the track color. It already starts off as white, and making that white translucent doesn't make it any darker, so it still won't show up on a dark background. Before the commit mentioned above, the colorspace errors in the old mulAlpha had the side-effect of darkening the color, which I think is why it was used here.

Anyway, I'm posting to see if someone can sanity-check my thinking about this. I believe the correct fix is to derive the track color for the switch via some other mechanism (maybe the material.Palette that I'm working on) instead of messing with the alpha of the primary color.

I also think that f32color.MulAlpha returns colors in the wrong colorspace to be used with paint.ColorOp, though I confess that I'm pretty ignorant about colorspaces and may just be misunderstanding the code.

Status
REPORTED
Submitter
~whereswaldon
Assigned to
No-one
Submitted
2 months ago
Updated
2 months ago
Labels
No labels applied.

~eliasnaur 2 months ago

Good catch!

On Sun Nov 8, 2020 at 14:59, ~whereswaldon wrote:

So I'm working to understand why the material.Switch track is now invisible when rendered atop a white backround (this makes the whole switch almost invisible, though you can see the "head" of the switch as a faint gray circle).

git bisect reveals that it occurred in this commit:

commit 4bab6fcf322d4b5fc0e2e6fd3132965fea6aefa5
Author: Elias Naur <mail@eliasnaur.com>
Date:   Mon Sep 28 09:02:38 2020 +0200

    internal/f32color: add colorspace-correct function for alpha scaling

So after some digging, I think I might understand the issue. It's here.

Using f32color.MulAlpha to alpha-premultiply the color seems like it ought to work, but it results in an invalid alpha-premultiplied color (R,G, and B are all higher than A). Looking further, this implementation appears to return colors in SRGB, whereas gio's paint.ColorOp expects linear RGB.

Gio assumes all color.RGBA values, including paint.ColorOp's color parameter, to be in sRGB. f32.RGBA, on the other hand, is in linear RGB.

Additionally, as I think about it, I'm not sure I follow why we are using alpha to derive the track color. It already starts off as white, and making that white translucent doesn't make it any darker, so it still won't show up on a dark background. Before the commit mentioned above, the colorspace errors in the old mulAlpha had the side-effect of darkening the color, which I think is why it was used here.

Absolutely. I remember wanting to have something like your Palette available, but opted for a quick alpha hack that looked good at the time.

Anyway, I'm posting to see if someone can sanity-check my thinking about this. I believe the correct fix is to derive the track color for the switch via some other mechanism (maybe the material.Palette that I'm working on) instead of messing with the alpha of the primary color.

Indeed, Switch and many other widgets need proper color adjustment.

I also think that f32color.MulAlpha returns colors in the wrong colorspace to be used with paint.ColorOp, though I confess that I'm pretty ignorant about colorspaces and may just be misunderstanding the code.

I believe you're incorrect: paint.ColorOp takes a color.RGBA which is assumed to be in sRGB.

~whereswaldon 2 months ago

Gio assumes all color.RGBA values, including paint.ColorOp's color parameter, to be in sRGB. f32.RGBA, on the other hand, is in linear RGB.

This is good to know, but I can't find it documented anywhere. rg -i colorspace in the root of gio's source returns almost no hits, and none of them are relevant. Searching all of our non-source documentation for the word color likewise has no relevant hits. I think I've seen colorspaces discussed exclusively in Slack, so I recommend that we take a few minutes to document this expectation. I would do it, but I clearly don't actually know enough about colorspaces to feel confident that I'm doing it right.

Indeed, Switch and many other widgets need proper color adjustment.

I'll try to work this into my palette patches, though I might do something naive at first.

I believe you're incorrect: paint.ColorOp takes a color.RGBA which is assumed to be in sRGB.

Yeah, seems so. :D I can't figure out where I got that assumption, as it is nowhere in the docs that I can find.

~eliasnaur 2 months ago

On Sun Nov 8, 2020 at 6:46 PM CET, ~whereswaldon wrote:

Gio assumes all color.RGBA values, including paint.ColorOp's color parameter, to be in sRGB. f32.RGBA, on the other hand, is in linear RGB.

This is good to know, but I can't find it documented anywhere. rg -i colorspace in the root of gio's source returns almost no hits, and none of them are relevant. Searching all of our non-source documentation for the word color likewise has no relevant hits. I think I've seen colorspaces discussed exclusively in Slack, so I recommend that we take a few minutes to document this expectation. I would do it, but I clearly don't actually know enough about colorspaces to feel confident that I'm doing it right.

Indeed, Switch and many other widgets need proper color adjustment.

I'll try to work this into my palette patches, though I might do something naive at first.

I believe you're incorrect: paint.ColorOp takes a color.RGBA which is assumed to be in sRGB.

Yeah, seems so. :D I can't figure out where I got that assumption, as it is nowhere in the docs that I can find.

I've added a short notive in gioui.org/commit/8b5c0d8. It's not much, but the external API is quite simple: all values are in sRGB. The consequences are subtle (blending, alpha multiplication), but that's better documented by adding an srgb package.

Elias

Register here or Log in to comment, or comment via email.