buttonRenderer's buttonColor can generate out of range alpha values when hovered (might affect RGB too?) #2222
Description
Describe the bug:
The math in widget/button.go's buttonRenderer's buttonColor() for color calculations while hovering appears to be very wrong (in addition to being affected by #2220), but I'm not sure what it is actually trying to do.
At present it is doing this when a button is hovered:
bg := theme.ButtonColor()
if r.button.Importance == HighImportance {
bg = theme.PrimaryColor()
}
dstR, dstG, dstB, dstA := bg.RGBA()
srcR, srcG, srcB, srcA := theme.HoverColor().RGBA()
srcAlpha := float32(srcA) / 0xFFFF
dstAlpha := float32(dstA) / 0xFFFF
targetAlpha := 1 - srcAlpha*dstAlpha
outAlpha := srcAlpha + targetAlpha
outR := (srcAlpha*float32(srcR) + targetAlpha*float32(dstR)) / outAlpha
outG := (srcAlpha*float32(srcG) + targetAlpha*float32(dstG)) / outAlpha
outB := (srcAlpha*float32(srcB) + targetAlpha*float32(dstB)) / outAlpha
return color.RGBA{R: uint8(uint32(outR) >> 8), G: uint8(uint32(outG) >> 8), B: uint8(uint32(outB) >> 8), A: uint8(outAlpha * 0xFF)}
The problem here is that the math doesn't make any sense, even if it's accounting for premultiplication (I'm not sure if it is or not). You can see that if you just look at what's going on with the alpha values:
Let's assume srcA=51, dstA=204.
srcAlpha will be 0.2, and dstAlpha will be 0.8.
targetAlpha = 1 - 0.2 * 0.8 = 0.84
outAlpha = 0.2 + 0.84 = 1.04
The alpha value that is used in the new color.RGBA will be uint8(1.04*0xFF).
1.04*0xFF is 265.2, or 0x109, and so when it's cut off to just 8 bits, the color.RGBA will have an alpha value of 0x09, which is equivalent to if outAlpha had been 0.035.
So that seems like an obvious bug, but less obvious is what the code is supposed to be doing.
I checked all the other things that can be hovered, but they pretty much all just set their color to HoverColor. This seems to be something new.
(This doesn't even get into how the alpha calculations may be screwing up the colors too - they'd be screwed up anyways from just having alpha due to #2220, which I haven't fixed for this method)
To Reproduce:
Steps to reproduce the behaviour:
- If you want to see it visually, try creating a theme whose background color is 0xff0000, button color is 0x00ff00 with alpha 204, and hover color is 0x0000ff with alpha 51, and a window with a button on it that you can move the mouse over to see what happens. Given that Themed resources are drawn with the wrong colors if a theme's Color() method returns certain types of Colors #2220 also applies, the results will probably be confusing. Also you can't actually see the alpha values this way, you'd have to try to infer them, which would be difficult given that the color values won't necessarily make any sense either...
Device (please complete the following information):
- OS: Windows 10 Pro
- Version: 20H2
- Go version: 1.16.3 windows/amd64
- Fyne version: 083f034