fix: RGBA implementations for non-hex color values

This commit is contained in:
Christian Muehlhaeuser 2022-09-30 04:40:12 +02:00
parent cabfd38a13
commit 651d1265e7
2 changed files with 50 additions and 51 deletions

View File

@ -1,7 +1,6 @@
package lipgloss
import (
"image/color"
"sync"
"github.com/muesli/termenv"
@ -144,7 +143,7 @@ func (c Color) color() termenv.Color {
//
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFF.
func (c Color) RGBA() (r, g, b, a uint32) {
return hexToColor(c.value()).RGBA()
return termenv.ConvertToRGB(c.color()).RGBA()
}
// AdaptiveColor provides color options for light and dark backgrounds. The
@ -175,8 +174,7 @@ func (ac AdaptiveColor) color() termenv.Color {
//
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFF.
func (ac AdaptiveColor) RGBA() (r, g, b, a uint32) {
cf := hexToColor(ac.value())
return cf.RGBA()
return termenv.ConvertToRGB(ac.color()).RGBA()
}
// CompleteColor specifies exact values for truecolor, ANSI256, and ANSI color
@ -209,7 +207,7 @@ func (c CompleteColor) color() termenv.Color {
//
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF
func (c CompleteColor) RGBA() (r, g, b, a uint32) {
return hexToColor(c.value()).RGBA()
return termenv.ConvertToRGB(c.color()).RGBA()
}
// CompleteColor specifies exact values for truecolor, ANSI256, and ANSI color
@ -236,50 +234,5 @@ func (cac CompleteAdaptiveColor) color() termenv.Color {
//
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF
func (cac CompleteAdaptiveColor) RGBA() (r, g, b, a uint32) {
return hexToColor(cac.value()).RGBA()
}
// hexToColor translates a hex color string (#RRGGBB or #RGB) into a color.RGB,
// which satisfies the color.Color interface. If an invalid string is passed
// black with 100% opacity will be returned: or, in hex format, 0x000000FF.
func hexToColor(hex string) (c color.RGBA) {
c.A = 0xFF
if hex == "" || hex[0] != '#' {
return c
}
const (
fullFormat = 7 // #RRGGBB
shortFormat = 4 // #RGB
)
switch len(hex) {
case fullFormat:
const offset = 4
c.R = hexToByte(hex[1])<<offset + hexToByte(hex[2])
c.G = hexToByte(hex[3])<<offset + hexToByte(hex[4])
c.B = hexToByte(hex[5])<<offset + hexToByte(hex[6])
case shortFormat:
const offset = 0x11
c.R = hexToByte(hex[1]) * offset
c.G = hexToByte(hex[2]) * offset
c.B = hexToByte(hex[3]) * offset
}
return c
}
func hexToByte(b byte) byte {
const offset = 10
switch {
case b >= '0' && b <= '9':
return b - '0'
case b >= 'a' && b <= 'f':
return b - 'a' + offset
case b >= 'A' && b <= 'F':
return b - 'A' + offset
}
// Invalid, but just return 0.
return 0
return termenv.ConvertToRGB(cac.color()).RGBA()
}

View File

@ -1,6 +1,7 @@
package lipgloss
import (
"image/color"
"testing"
"github.com/muesli/termenv"
@ -225,3 +226,48 @@ func TestRGBA(t *testing.T) {
}
}
}
// hexToColor translates a hex color string (#RRGGBB or #RGB) into a color.RGB,
// which satisfies the color.Color interface. If an invalid string is passed
// black with 100% opacity will be returned: or, in hex format, 0x000000FF.
func hexToColor(hex string) (c color.RGBA) {
c.A = 0xFF
if hex == "" || hex[0] != '#' {
return c
}
const (
fullFormat = 7 // #RRGGBB
shortFormat = 4 // #RGB
)
switch len(hex) {
case fullFormat:
const offset = 4
c.R = hexToByte(hex[1])<<offset + hexToByte(hex[2])
c.G = hexToByte(hex[3])<<offset + hexToByte(hex[4])
c.B = hexToByte(hex[5])<<offset + hexToByte(hex[6])
case shortFormat:
const offset = 0x11
c.R = hexToByte(hex[1]) * offset
c.G = hexToByte(hex[2]) * offset
c.B = hexToByte(hex[3]) * offset
}
return c
}
func hexToByte(b byte) byte {
const offset = 10
switch {
case b >= '0' && b <= '9':
return b - '0'
case b >= 'a' && b <= 'f':
return b - 'a' + offset
case b >= 'A' && b <= 'F':
return b - 'A' + offset
}
// Invalid, but just return 0.
return 0
}