You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
1.9 KiB
71 lines
1.9 KiB
package state
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Color is an internal representation of an RGBA8888 color.
|
|
type Color struct {
|
|
// R is the red component of the color.
|
|
R uint8
|
|
// G is the green component of the color.
|
|
G uint8
|
|
// B is the blue component of the color.
|
|
B uint8
|
|
// A is the alpha component of the color.
|
|
A uint8
|
|
}
|
|
|
|
var TransparentColor = Color{R: 0, G: 0, B: 0, A: 0}
|
|
var ErrInvalidColorString = errors.New("color strings must start with # and be followed by 3, 4, 6, or 8 hex digits")
|
|
|
|
func ColorFromString(s string) (Color, error) {
|
|
if !strings.HasPrefix(s, "#") {
|
|
return TransparentColor, ErrInvalidColorString
|
|
}
|
|
hex := s[1:]
|
|
v, err := strconv.ParseUint(hex, 16, 64)
|
|
if err != nil {
|
|
return TransparentColor, ErrInvalidColorString
|
|
}
|
|
switch len(hex) {
|
|
case 3:
|
|
return ColorFromRGBA4444(uint16(v<<4 | 0xF)), nil
|
|
case 4:
|
|
return ColorFromRGBA4444(uint16(v)), nil
|
|
case 6:
|
|
return ColorFromRGBA8888(uint32(v<<8 | 0xFF)), nil
|
|
case 8:
|
|
return ColorFromRGBA8888(uint32(v)), nil
|
|
default:
|
|
return TransparentColor, ErrInvalidColorString
|
|
}
|
|
}
|
|
|
|
// String prints the Color in an abbreviated notation.
|
|
// Specifically, short form is used when possible (i.e., when all components are evenly divisible by 0x11).
|
|
// The alpha component is left out if it's 0xFF.
|
|
func (c Color) String() string {
|
|
if c.R%0x11 == 0 && c.G%0x11 == 0 && c.B%0x11 == 0 && c.A%0x11 == 0 {
|
|
// Short form works.
|
|
if c.A == 0xFF {
|
|
// It's great when it's easy!
|
|
return fmt.Sprintf("#%01X%01X%01X", c.R/0x11, c.G/0x11, c.B/0x11)
|
|
} else {
|
|
// Just need to add the alpha.
|
|
return fmt.Sprintf("#%01X%01X%01X%01X", c.R/0x11, c.G/0x11, c.B/0x11, c.A/0x11)
|
|
}
|
|
} else {
|
|
// Gotta use long form.
|
|
if c.A == 0xFF {
|
|
// Can skip the alpha channel, though.
|
|
return fmt.Sprintf("#%02X%02X%02X", c.R, c.G, c.B)
|
|
} else {
|
|
// Doing things the hard way.
|
|
return fmt.Sprintf("#%02X%02X%02X%02X", c.R, c.G, c.B, c.A)
|
|
}
|
|
}
|
|
}
|
|
|