forked from gonutz/framebuffer
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcolor.go
71 lines (60 loc) · 1.66 KB
/
color.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package framebuffer
import (
"image/color"
)
// colorModel is an RGBA color model.
type colorModel struct {
r, g, b, a colorChannel
}
// colorChannel is one color of a [colorModel].
type colorChannel struct {
length, offset uint32
}
// colorValue is [colorModel]'s implementation of [color.Color].
type colorValue struct {
value uint32
model colorModel
}
// Convert converts a color to this model.
func (cm *colorModel) Convert(c color.Color) color.Color {
return &colorValue{cm.convert(c), *cm}
}
// RGBA returns each color channel as a separate value.
func (c *colorValue) RGBA() (r, g, b, a uint32) {
return c.model.r.unshift(c.value),
c.model.g.unshift(c.value),
c.model.b.unshift(c.value),
c.model.a.unshift(c.value)
}
// convert converts a color this model.
func (cm colorModel) convert(c color.Color) uint32 {
r, g, b, a := c.RGBA()
return cm.r.shift(r) |
cm.g.shift(g) |
cm.b.shift(b) |
cm.a.shift(a)
}
// shift shifts and masks the value to the offset and length of this channel.
func (ch colorChannel) shift(val uint32) uint32 {
// Skip the math if this channel is not used
if ch.length == 0 {
return 0
}
// Shift and mask
var mask uint32 = 1<<ch.length - 1
val >>= 16 - ch.length
return (val & mask) << uint32(ch.offset)
}
// unshift extracts the value of this channel.
func (ch colorChannel) unshift(val uint32) uint32 {
// The alpha channel is the only one that should have zero length. If the
// alpha channel doesn't exist, pretend like it's value is the max (full
// opacity).
if ch.length == 0 {
return 0xFFFF
}
// Mask and shift
var mask uint32 = 1<<ch.length - 1
val = (val >> ch.offset) & mask
return val << (16 - ch.length)
}