2020-05-28 14:21:20 +03:00
|
|
|
module gx
|
|
|
|
|
|
|
|
pub const (
|
2022-01-29 22:40:02 +03:00
|
|
|
black = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 0
|
|
|
|
g: 0
|
2022-01-29 22:40:02 +03:00
|
|
|
b: 0
|
|
|
|
}
|
|
|
|
gray = Color{
|
|
|
|
r: 128
|
|
|
|
g: 128
|
|
|
|
b: 128
|
|
|
|
}
|
|
|
|
white = Color{
|
|
|
|
r: 255
|
|
|
|
g: 255
|
2020-10-18 09:48:13 +03:00
|
|
|
b: 255
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
red = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 255
|
|
|
|
g: 0
|
|
|
|
b: 0
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
green = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 0
|
|
|
|
g: 255
|
|
|
|
b: 0
|
|
|
|
}
|
2022-01-29 22:40:02 +03:00
|
|
|
blue = Color{
|
|
|
|
r: 0
|
|
|
|
g: 0
|
|
|
|
b: 255
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
yellow = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 255
|
|
|
|
g: 255
|
|
|
|
b: 0
|
|
|
|
}
|
2022-01-29 22:40:02 +03:00
|
|
|
magenta = Color{
|
|
|
|
r: 255
|
|
|
|
g: 0
|
|
|
|
b: 255
|
|
|
|
}
|
|
|
|
cyan = Color{
|
|
|
|
r: 0
|
|
|
|
g: 255
|
|
|
|
b: 255
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
orange = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 255
|
|
|
|
g: 165
|
|
|
|
b: 0
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
purple = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 128
|
|
|
|
g: 0
|
|
|
|
b: 128
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
indigo = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 75
|
|
|
|
g: 0
|
|
|
|
b: 130
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
pink = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 255
|
|
|
|
g: 192
|
|
|
|
b: 203
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
violet = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 238
|
|
|
|
g: 130
|
|
|
|
b: 238
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
dark_blue = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 0
|
|
|
|
g: 0
|
|
|
|
b: 139
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
dark_gray = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 169
|
|
|
|
g: 169
|
|
|
|
b: 169
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
dark_green = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 0
|
|
|
|
g: 100
|
|
|
|
b: 0
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
dark_red = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 139
|
|
|
|
g: 0
|
|
|
|
b: 0
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
light_blue = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 173
|
|
|
|
g: 216
|
|
|
|
b: 230
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
light_gray = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 211
|
|
|
|
g: 211
|
|
|
|
b: 211
|
|
|
|
}
|
|
|
|
light_green = Color{
|
|
|
|
r: 144
|
|
|
|
g: 238
|
|
|
|
b: 144
|
|
|
|
}
|
2021-05-08 13:32:29 +03:00
|
|
|
light_red = Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: 255
|
|
|
|
g: 204
|
|
|
|
b: 203
|
|
|
|
}
|
2020-05-28 14:21:20 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// Color represents a 32 bit color value in sRGB format
|
|
|
|
pub struct Color {
|
|
|
|
pub mut:
|
2022-04-15 18:25:45 +03:00
|
|
|
r u8
|
|
|
|
g u8
|
|
|
|
b u8
|
|
|
|
a u8 = 255
|
2020-05-28 14:21:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// hex takes in a 32 bit integer and splits it into 4 byte values
|
|
|
|
pub fn hex(color int) Color {
|
2020-10-18 09:48:13 +03:00
|
|
|
return Color{
|
2022-04-15 14:58:56 +03:00
|
|
|
r: u8((color >> 24) & 0xFF)
|
|
|
|
g: u8((color >> 16) & 0xFF)
|
|
|
|
b: u8((color >> 8) & 0xFF)
|
|
|
|
a: u8(color & 0xFF)
|
2020-05-28 14:21:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 02:47:55 +03:00
|
|
|
// rgb builds a Color instance from given r, g, b values
|
2022-04-15 18:25:45 +03:00
|
|
|
pub fn rgb(r u8, g u8, b u8) Color {
|
2020-05-28 14:21:20 +03:00
|
|
|
return Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: r
|
|
|
|
g: g
|
2020-05-28 14:21:20 +03:00
|
|
|
b: b
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 02:47:55 +03:00
|
|
|
// rgba builds a Color instance from given r, g, b, a values
|
2022-04-15 18:25:45 +03:00
|
|
|
pub fn rgba(r u8, g u8, b u8, a u8) Color {
|
2020-05-28 14:21:20 +03:00
|
|
|
return Color{
|
2020-10-18 09:48:13 +03:00
|
|
|
r: r
|
|
|
|
g: g
|
|
|
|
b: b
|
2020-05-28 14:21:20 +03:00
|
|
|
a: a
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-29 22:40:02 +03:00
|
|
|
// + adds `b` to `a`, with a maximum value of 255 for each channel
|
|
|
|
pub fn (a Color) + (b Color) Color {
|
|
|
|
mut na := int(a.a) + b.a
|
|
|
|
mut nr := int(a.r) + b.r
|
|
|
|
mut ng := int(a.g) + b.g
|
|
|
|
mut nb := int(a.b) + b.b
|
|
|
|
if na > 255 {
|
|
|
|
na = 255
|
|
|
|
}
|
|
|
|
if nr > 255 {
|
|
|
|
nr = 255
|
|
|
|
}
|
|
|
|
if ng > 255 {
|
|
|
|
ng = 255
|
|
|
|
}
|
|
|
|
if nb > 255 {
|
|
|
|
nb = 255
|
|
|
|
}
|
2020-10-18 09:48:13 +03:00
|
|
|
return Color{
|
2022-04-15 14:58:56 +03:00
|
|
|
r: u8(nr)
|
|
|
|
g: u8(ng)
|
|
|
|
b: u8(nb)
|
|
|
|
a: u8(na)
|
2020-05-28 14:21:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-29 22:40:02 +03:00
|
|
|
// - subtracts `b` from `a`, with a minimum value of 0 for each channel
|
|
|
|
pub fn (a Color) - (b Color) Color {
|
|
|
|
mut na := if a.a > b.a { a.a } else { b.a }
|
|
|
|
mut nr := int(a.r) - b.r
|
|
|
|
mut ng := int(a.g) - b.g
|
|
|
|
mut nb := int(a.b) - b.b
|
|
|
|
if na < 0 {
|
|
|
|
na = 0
|
|
|
|
}
|
|
|
|
if nr < 0 {
|
|
|
|
nr = 0
|
|
|
|
}
|
|
|
|
if ng < 0 {
|
|
|
|
ng = 0
|
|
|
|
}
|
|
|
|
if nb < 0 {
|
|
|
|
nb = 0
|
|
|
|
}
|
2020-10-18 09:48:13 +03:00
|
|
|
return Color{
|
2022-04-15 14:58:56 +03:00
|
|
|
r: u8(nr)
|
|
|
|
g: u8(ng)
|
|
|
|
b: u8(nb)
|
|
|
|
a: u8(na)
|
2020-05-28 14:21:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 02:47:55 +03:00
|
|
|
// * multiplies Color `c` and `c2` keeping channel values in [0, 255] range
|
2021-01-08 14:40:03 +03:00
|
|
|
pub fn (c Color) * (c2 Color) Color {
|
2020-10-18 09:48:13 +03:00
|
|
|
return Color{
|
|
|
|
r: c.r * c2.r
|
|
|
|
g: c.g * c2.g
|
|
|
|
b: c.b * c2.b
|
2022-01-28 23:53:14 +03:00
|
|
|
a: c.a * c2.a
|
2020-05-28 14:21:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 02:47:55 +03:00
|
|
|
// / divides `c` by `c2` and converts each channel's value to u8(int)
|
2021-01-08 14:40:03 +03:00
|
|
|
pub fn (c Color) / (c2 Color) Color {
|
2020-10-18 09:48:13 +03:00
|
|
|
return Color{
|
|
|
|
r: c.r / c2.r
|
|
|
|
g: c.g / c2.g
|
|
|
|
b: c.b / c2.b
|
2022-01-28 23:53:14 +03:00
|
|
|
a: c.a / c2.a
|
2020-05-28 14:21:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-24 03:02:07 +03:00
|
|
|
// over implements an `a` over `b` operation.
|
2022-01-29 22:40:02 +03:00
|
|
|
// see https://keithp.com/~keithp/porterduff/p253-porter.pdf
|
|
|
|
pub fn (a Color) over(b Color) Color {
|
|
|
|
aa := f32(a.a) / 255
|
|
|
|
ab := f32(b.a) / 255
|
|
|
|
ar := aa + ab * (1 - aa)
|
|
|
|
//
|
|
|
|
rr := (f32(a.r) * aa + f32(b.r) * ab * (1 - aa)) / ar
|
|
|
|
gr := (f32(a.g) * aa + f32(b.g) * ab * (1 - aa)) / ar
|
|
|
|
br := (f32(a.b) * aa + f32(b.b) * ab * (1 - aa)) / ar
|
|
|
|
return Color{
|
2022-04-15 14:58:56 +03:00
|
|
|
r: u8(rr)
|
|
|
|
g: u8(gr)
|
|
|
|
b: u8(br)
|
|
|
|
a: u8(ar * 255)
|
2022-01-29 22:40:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 02:47:55 +03:00
|
|
|
// eq checks if color `c` and `c2` are equal in every channel
|
2020-05-28 14:21:20 +03:00
|
|
|
pub fn (c Color) eq(c2 Color) bool {
|
|
|
|
return c.r == c2.r && c.g == c2.g && c.b == c2.b && c.a == c2.a
|
|
|
|
}
|
|
|
|
|
2022-10-10 02:47:55 +03:00
|
|
|
// str returns a string representation of the Color `c`
|
2020-05-28 14:21:20 +03:00
|
|
|
pub fn (c Color) str() string {
|
2022-11-15 16:53:13 +03:00
|
|
|
return 'Color{${c.r}, ${c.g}, ${c.b}, ${c.a}}'
|
2020-05-28 14:21:20 +03:00
|
|
|
}
|
2020-08-09 04:57:54 +03:00
|
|
|
|
2023-01-24 03:02:07 +03:00
|
|
|
// rgba8 converts a color value to an int in the RGBA8 order.
|
2021-01-08 14:40:03 +03:00
|
|
|
// see https://developer.apple.com/documentation/coreimage/ciformat
|
|
|
|
[inline]
|
|
|
|
pub fn (c Color) rgba8() int {
|
2021-11-29 03:48:49 +03:00
|
|
|
return int(u32(c.r) << 24 | u32(c.g) << 16 | u32(c.b) << 8 | u32(c.a))
|
2021-01-08 14:40:03 +03:00
|
|
|
}
|
|
|
|
|
2023-01-24 03:02:07 +03:00
|
|
|
// bgra8 converts a color value to an int in the BGRA8 order.
|
2021-01-08 14:40:03 +03:00
|
|
|
// see https://developer.apple.com/documentation/coreimage/ciformat
|
|
|
|
[inline]
|
|
|
|
pub fn (c Color) bgra8() int {
|
2021-11-29 03:48:49 +03:00
|
|
|
return int(u32(c.b) << 24 | u32(c.g) << 16 | u32(c.r) << 8 | u32(c.a))
|
2021-01-08 14:40:03 +03:00
|
|
|
}
|
|
|
|
|
2023-01-24 03:02:07 +03:00
|
|
|
// abgr8 converts a color value to an int in the ABGR8 order.
|
2021-01-08 14:40:03 +03:00
|
|
|
// see https://developer.apple.com/documentation/coreimage/ciformat
|
|
|
|
[inline]
|
|
|
|
pub fn (c Color) abgr8() int {
|
2021-11-29 03:48:49 +03:00
|
|
|
return int(u32(c.a) << 24 | u32(c.b) << 16 | u32(c.g) << 8 | u32(c.r))
|
2021-01-08 14:40:03 +03:00
|
|
|
}
|
|
|
|
|
2020-08-09 04:57:54 +03:00
|
|
|
const (
|
2021-08-04 12:44:41 +03:00
|
|
|
string_colors = {
|
2021-07-03 10:09:11 +03:00
|
|
|
'blue': blue
|
|
|
|
'red': red
|
|
|
|
'green': green
|
|
|
|
'yellow': yellow
|
|
|
|
'orange': orange
|
|
|
|
'purple': purple
|
|
|
|
'black': black
|
|
|
|
'gray': gray
|
|
|
|
'indigo': indigo
|
|
|
|
'pink': pink
|
|
|
|
'violet': violet
|
|
|
|
'white': white
|
|
|
|
'dark_blue': dark_blue
|
|
|
|
'dark_gray': dark_gray
|
|
|
|
'dark_green': dark_green
|
|
|
|
'dark_red': dark_red
|
|
|
|
'light_blue': light_blue
|
|
|
|
'light_gray': light_gray
|
|
|
|
'light_green': light_green
|
|
|
|
'light_red': light_red
|
2020-10-18 09:48:13 +03:00
|
|
|
}
|
2020-08-09 04:57:54 +03:00
|
|
|
)
|
|
|
|
|
2022-10-10 02:47:55 +03:00
|
|
|
// color_from_string returns a Color, corresponding to the given string
|
|
|
|
// or black Color if string is not found in lookup table
|
2020-08-09 04:57:54 +03:00
|
|
|
pub fn color_from_string(s string) Color {
|
2021-05-08 13:32:29 +03:00
|
|
|
return gx.string_colors[s]
|
2020-08-09 04:57:54 +03:00
|
|
|
}
|
2021-12-20 16:18:21 +03:00
|
|
|
|
2022-10-10 02:47:55 +03:00
|
|
|
// to_css_string returns a CSS compatible string e.g. `rgba(10,11,12,13)` of the color `c`.
|
2021-12-20 16:18:21 +03:00
|
|
|
pub fn (c Color) to_css_string() string {
|
2022-11-15 16:53:13 +03:00
|
|
|
return 'rgba(${c.r},${c.g},${c.b},${c.a})'
|
2021-12-20 16:18:21 +03:00
|
|
|
}
|