mirror of
https://github.com/charmbracelet/lipgloss.git
synced 2024-09-11 22:17:12 +03:00
fix: RGBA implementations for non-hex color values
This commit is contained in:
parent
cabfd38a13
commit
651d1265e7
55
color.go
55
color.go
@ -1,7 +1,6 @@
|
|||||||
package lipgloss
|
package lipgloss
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image/color"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/muesli/termenv"
|
"github.com/muesli/termenv"
|
||||||
@ -144,7 +143,7 @@ func (c Color) color() termenv.Color {
|
|||||||
//
|
//
|
||||||
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFF.
|
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFF.
|
||||||
func (c Color) RGBA() (r, g, b, a uint32) {
|
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
|
// 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.
|
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFF.
|
||||||
func (ac AdaptiveColor) RGBA() (r, g, b, a uint32) {
|
func (ac AdaptiveColor) RGBA() (r, g, b, a uint32) {
|
||||||
cf := hexToColor(ac.value())
|
return termenv.ConvertToRGB(ac.color()).RGBA()
|
||||||
return cf.RGBA()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompleteColor specifies exact values for truecolor, ANSI256, and ANSI color
|
// 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
|
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF
|
||||||
func (c CompleteColor) RGBA() (r, g, b, a uint32) {
|
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
|
// 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
|
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF
|
||||||
func (cac CompleteAdaptiveColor) RGBA() (r, g, b, a uint32) {
|
func (cac CompleteAdaptiveColor) RGBA() (r, g, b, a uint32) {
|
||||||
return hexToColor(cac.value()).RGBA()
|
return termenv.ConvertToRGB(cac.color()).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
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package lipgloss
|
package lipgloss
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image/color"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/muesli/termenv"
|
"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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user