annotate vendor/github.com/alecthomas/chroma/v2/colour.go @ 66:787b5ee0289d draft

Use vendored modules Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Sun, 23 Jul 2023 13:18:53 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 package chroma
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4 "fmt"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 "math"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6 "strconv"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7 "strings"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10 // ANSI2RGB maps ANSI colour names, as supported by Chroma, to hex RGB values.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11 var ANSI2RGB = map[string]string{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 "#ansiblack": "000000",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13 "#ansidarkred": "7f0000",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 "#ansidarkgreen": "007f00",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15 "#ansibrown": "7f7fe0",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16 "#ansidarkblue": "00007f",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17 "#ansipurple": "7f007f",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 "#ansiteal": "007f7f",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19 "#ansilightgray": "e5e5e5",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20 // Normal
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21 "#ansidarkgray": "555555",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 "#ansired": "ff0000",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23 "#ansigreen": "00ff00",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24 "#ansiyellow": "ffff00",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25 "#ansiblue": "0000ff",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26 "#ansifuchsia": "ff00ff",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27 "#ansiturquoise": "00ffff",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 "#ansiwhite": "ffffff",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30 // Aliases without the "ansi" prefix, because...why?
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 "#black": "000000",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 "#darkred": "7f0000",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33 "#darkgreen": "007f00",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34 "#brown": "7f7fe0",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 "#darkblue": "00007f",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 "#purple": "7f007f",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37 "#teal": "007f7f",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38 "#lightgray": "e5e5e5",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 // Normal
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40 "#darkgray": "555555",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41 "#red": "ff0000",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42 "#green": "00ff00",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43 "#yellow": "ffff00",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 "#blue": "0000ff",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45 "#fuchsia": "ff00ff",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 "#turquoise": "00ffff",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47 "#white": "ffffff",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50 // Colour represents an RGB colour.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 type Colour int32
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53 // NewColour creates a Colour directly from RGB values.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54 func NewColour(r, g, b uint8) Colour {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 return ParseColour(fmt.Sprintf("%02x%02x%02x", r, g, b))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58 // Distance between this colour and another.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60 // This uses the approach described here (https://www.compuphase.com/cmetric.htm).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61 // This is not as accurate as LAB, et. al. but is *vastly* simpler and sufficient for our needs.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 func (c Colour) Distance(e2 Colour) float64 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 ar, ag, ab := int64(c.Red()), int64(c.Green()), int64(c.Blue())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 br, bg, bb := int64(e2.Red()), int64(e2.Green()), int64(e2.Blue())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65 rmean := (ar + br) / 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66 r := ar - br
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67 g := ag - bg
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68 b := ab - bb
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69 return math.Sqrt(float64((((512 + rmean) * r * r) >> 8) + 4*g*g + (((767 - rmean) * b * b) >> 8)))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 // Brighten returns a copy of this colour with its brightness adjusted.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74 // If factor is negative, the colour is darkened.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76 // Uses approach described here (http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77 func (c Colour) Brighten(factor float64) Colour {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 r := float64(c.Red())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79 g := float64(c.Green())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80 b := float64(c.Blue())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 if factor < 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 factor++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84 r *= factor
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 g *= factor
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86 b *= factor
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 r = (255-r)*factor + r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89 g = (255-g)*factor + g
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 b = (255-b)*factor + b
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92 return NewColour(uint8(r), uint8(g), uint8(b))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95 // BrightenOrDarken brightens a colour if it is < 0.5 brightness or darkens if > 0.5 brightness.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96 func (c Colour) BrightenOrDarken(factor float64) Colour {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97 if c.Brightness() < 0.5 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 return c.Brighten(factor)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100 return c.Brighten(-factor)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103 // ClampBrightness returns a copy of this colour with its brightness adjusted such that
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104 // it falls within the range [min, max] (or very close to it due to rounding errors).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 // The supplied values use the same [0.0, 1.0] range as Brightness.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106 func (c Colour) ClampBrightness(min, max float64) Colour {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107 if !c.IsSet() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 return c
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111 min = math.Max(min, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112 max = math.Min(max, 1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113 current := c.Brightness()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114 target := math.Min(math.Max(current, min), max)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115 if current == target {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116 return c
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119 r := float64(c.Red())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120 g := float64(c.Green())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121 b := float64(c.Blue())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 rgb := r + g + b
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123 if target > current {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124 // Solve for x: target == ((255-r)*x + r + (255-g)*x + g + (255-b)*x + b) / 255 / 3
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125 return c.Brighten((target*255*3 - rgb) / (255*3 - rgb))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127 // Solve for x: target == (r*(x+1) + g*(x+1) + b*(x+1)) / 255 / 3
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 return c.Brighten((target*255*3)/rgb - 1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131 // Brightness of the colour (roughly) in the range 0.0 to 1.0.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 func (c Colour) Brightness() float64 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133 return (float64(c.Red()) + float64(c.Green()) + float64(c.Blue())) / 255.0 / 3.0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136 // ParseColour in the forms #rgb, #rrggbb, #ansi<colour>, or #<colour>.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137 // Will return an "unset" colour if invalid.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 func ParseColour(colour string) Colour {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139 colour = normaliseColour(colour)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140 n, err := strconv.ParseUint(colour, 16, 32)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144 return Colour(n + 1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147 // MustParseColour is like ParseColour except it panics if the colour is invalid.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149 // Will panic if colour is in an invalid format.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150 func MustParseColour(colour string) Colour {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151 parsed := ParseColour(colour)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 if !parsed.IsSet() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153 panic(fmt.Errorf("invalid colour %q", colour))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155 return parsed
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 // IsSet returns true if the colour is set.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159 func (c Colour) IsSet() bool { return c != 0 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161 func (c Colour) String() string { return fmt.Sprintf("#%06x", int(c-1)) }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162 func (c Colour) GoString() string { return fmt.Sprintf("Colour(0x%06x)", int(c-1)) }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 // Red component of colour.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 func (c Colour) Red() uint8 { return uint8(((c - 1) >> 16) & 0xff) }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 // Green component of colour.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 func (c Colour) Green() uint8 { return uint8(((c - 1) >> 8) & 0xff) }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170 // Blue component of colour.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171 func (c Colour) Blue() uint8 { return uint8((c - 1) & 0xff) }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173 // Colours is an orderable set of colours.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174 type Colours []Colour
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176 func (c Colours) Len() int { return len(c) }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177 func (c Colours) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 func (c Colours) Less(i, j int) bool { return c[i] < c[j] }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
179
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
180 // Convert colours to #rrggbb.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
181 func normaliseColour(colour string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
182 if ansi, ok := ANSI2RGB[colour]; ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
183 return ansi
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
184 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
185 if strings.HasPrefix(colour, "#") {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
186 colour = colour[1:]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
187 if len(colour) == 3 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
188 return colour[0:1] + colour[0:1] + colour[1:2] + colour[1:2] + colour[2:3] + colour[2:3]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
189 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
190 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
191 return colour
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
192 }