-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
linear.go
79 lines (66 loc) · 1.32 KB
/
linear.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
72
73
74
75
76
77
78
79
package colorgrad
import (
"math"
)
type linearGradient struct {
colors [][4]float64
positions []float64
min float64
max float64
mode BlendMode
first Color
last Color
}
func (lg linearGradient) At(t float64) Color {
if t <= lg.min {
return lg.first
}
if t >= lg.max {
return lg.last
}
if math.IsNaN(t) {
return Color{A: 1}
}
low := 0
high := len(lg.positions)
for low < high {
mid := (low + high) / 2
if lg.positions[mid] < t {
low = mid + 1
} else {
high = mid
}
}
if low == 0 {
low = 1
}
p1 := lg.positions[low-1]
p2 := lg.positions[low]
t = (t - p1) / (p2 - p1)
a, b, c, d := linearInterpolate(lg.colors[low-1], lg.colors[low], t)
switch lg.mode {
case BlendRgb:
return Color{R: a, G: b, B: c, A: d}
case BlendLinearRgb:
return LinearRgb(a, b, c, d)
case BlendOklab:
return Oklab(a, b, c, d).Clamp()
}
return Color{}
}
func newLinearGradient(colors []Color, positions []float64, mode BlendMode) Gradient {
gradbase := linearGradient{
colors: convertColors(colors, mode),
positions: positions,
min: positions[0],
max: positions[len(positions)-1],
mode: mode,
first: colors[0],
last: colors[len(colors)-1],
}
return Gradient{
grad: gradbase,
dmin: positions[0],
dmax: positions[len(positions)-1],
}
}