diff options
Diffstat (limited to 'vendor/gioui.org/internal/f32color/rgba.go')
-rw-r--r-- | vendor/gioui.org/internal/f32color/rgba.go | 128 |
1 files changed, 115 insertions, 13 deletions
diff --git a/vendor/gioui.org/internal/f32color/rgba.go b/vendor/gioui.org/internal/f32color/rgba.go index efaa1fb..eecf018 100644 --- a/vendor/gioui.org/internal/f32color/rgba.go +++ b/vendor/gioui.org/internal/f32color/rgba.go @@ -7,7 +7,7 @@ import ( "math" ) -// RGBA is a 32 bit floating point linear space color. +// RGBA is a 32 bit floating point linear premultiplied color space. type RGBA struct { R, G, B, A float32 } @@ -23,30 +23,90 @@ func (col RGBA) Float32() (r, g, b, a float32) { } // SRGBA converts from linear to sRGB color space. -func (col RGBA) SRGB() color.RGBA { - return color.RGBA{ - R: uint8(linearTosRGB(col.R)*255 + .5), - G: uint8(linearTosRGB(col.G)*255 + .5), - B: uint8(linearTosRGB(col.B)*255 + .5), +func (col RGBA) SRGB() color.NRGBA { + if col.A == 0 { + return color.NRGBA{} + } + return color.NRGBA{ + R: uint8(linearTosRGB(col.R/col.A)*255 + .5), + G: uint8(linearTosRGB(col.G/col.A)*255 + .5), + B: uint8(linearTosRGB(col.B/col.A)*255 + .5), A: uint8(col.A*255 + .5), } } +// Luminance calculates the relative luminance of a linear RGBA color. +// Normalized to 0 for black and 1 for white. +// +// See https://www.w3.org/TR/WCAG20/#relativeluminancedef for more details +func (col RGBA) Luminance() float32 { + return 0.2126*col.R + 0.7152*col.G + 0.0722*col.B +} + // Opaque returns the color without alpha component. func (col RGBA) Opaque() RGBA { col.A = 1.0 return col } -// RGBAFromSRGB converts from SRGBA to RGBA. -func RGBAFromSRGB(col color.RGBA) RGBA { - r, g, b, a := col.RGBA() +// LinearFromSRGB converts from col in the sRGB colorspace to RGBA. +func LinearFromSRGB(col color.NRGBA) RGBA { + af := float32(col.A) / 0xFF return RGBA{ - R: sRGBToLinear(float32(r) / 0xffff), - G: sRGBToLinear(float32(g) / 0xffff), - B: sRGBToLinear(float32(b) / 0xffff), - A: float32(a) / 0xFFFF, + R: sRGBToLinear(float32(col.R)/0xff) * af, + G: sRGBToLinear(float32(col.G)/0xff) * af, + B: sRGBToLinear(float32(col.B)/0xff) * af, + A: af, + } +} + +// NRGBAToRGBA converts from non-premultiplied sRGB color to premultiplied sRGB color. +// +// Each component in the result is `sRGBToLinear(c * alpha)`, where `c` +// is the linear color. +func NRGBAToRGBA(col color.NRGBA) color.RGBA { + if col.A == 0xFF { + return color.RGBA(col) + } + c := LinearFromSRGB(col) + return color.RGBA{ + R: uint8(linearTosRGB(c.R)*255 + .5), + G: uint8(linearTosRGB(c.G)*255 + .5), + B: uint8(linearTosRGB(c.B)*255 + .5), + A: col.A, + } +} + +// NRGBAToLinearRGBA converts from non-premultiplied sRGB color to premultiplied linear RGBA color. +// +// Each component in the result is `c * alpha`, where `c` is the linear color. +func NRGBAToLinearRGBA(col color.NRGBA) color.RGBA { + if col.A == 0xFF { + return color.RGBA(col) + } + c := LinearFromSRGB(col) + return color.RGBA{ + R: uint8(c.R*255 + .5), + G: uint8(c.G*255 + .5), + B: uint8(c.B*255 + .5), + A: col.A, + } +} + +// RGBAToNRGBA converts from premultiplied sRGB color to non-premultiplied sRGB color. +func RGBAToNRGBA(col color.RGBA) color.NRGBA { + if col.A == 0xFF { + return color.NRGBA(col) + } + + linear := RGBA{ + R: sRGBToLinear(float32(col.R) / 0xff), + G: sRGBToLinear(float32(col.G) / 0xff), + B: sRGBToLinear(float32(col.B) / 0xff), + A: float32(col.A) / 0xff, } + + return linear.SRGB() } // linearTosRGB transforms color value from linear to sRGB. @@ -73,3 +133,45 @@ func sRGBToLinear(c float32) float32 { return float32(math.Pow(float64((c+0.055)/1.055), 2.4)) } } + +// MulAlpha applies the alpha to the color. +func MulAlpha(c color.NRGBA, alpha uint8) color.NRGBA { + c.A = uint8(uint32(c.A) * uint32(alpha) / 0xFF) + return c +} + +// Disabled blends color towards the luminance and multiplies alpha. +// Blending towards luminance will desaturate the color. +// Multiplying alpha blends the color together more with the background. +func Disabled(c color.NRGBA) (d color.NRGBA) { + const r = 80 // blend ratio + lum := approxLuminance(c) + return color.NRGBA{ + R: byte((int(c.R)*r + int(lum)*(256-r)) / 256), + G: byte((int(c.G)*r + int(lum)*(256-r)) / 256), + B: byte((int(c.B)*r + int(lum)*(256-r)) / 256), + A: byte(int(c.A) * (128 + 32) / 256), + } +} + +// Hovered blends color towards a brighter color. +func Hovered(c color.NRGBA) (d color.NRGBA) { + const r = 0x20 // lighten ratio + return color.NRGBA{ + R: byte(255 - int(255-c.R)*(255-r)/256), + G: byte(255 - int(255-c.G)*(255-r)/256), + B: byte(255 - int(255-c.B)*(255-r)/256), + A: c.A, + } +} + +// approxLuminance is a fast approximate version of RGBA.Luminance. +func approxLuminance(c color.NRGBA) byte { + const ( + r = 13933 // 0.2126 * 256 * 256 + g = 46871 // 0.7152 * 256 * 256 + b = 4732 // 0.0722 * 256 * 256 + t = r + g + b + ) + return byte((r*int(c.R) + g*int(c.G) + b*int(c.B)) / t) +} |