/
Color.re
147 lines (128 loc) · 4.03 KB
/
Color.re
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
type t = Skia.Color.t;
let rgba = (r, g, b, a) => Skia.Color.Float.makeArgb(a, r, g, b);
let rgb = (r, g, b) => Skia.Color.Float.makeArgb(1.0, r, g, b);
let rgba_int = (r, g, b, a) =>
Skia.Color.makeArgb(
a |> Int32.of_int,
r |> Int32.of_int,
g |> Int32.of_int,
b |> Int32.of_int,
);
let rgb_int = (r, g, b) =>
Skia.Color.makeArgb(
255l,
r |> Int32.of_int,
g |> Int32.of_int,
b |> Int32.of_int,
);
let getAlpha = Skia.Color.Float.getA;
// Matches:
// #FFF
// #FFFA
// #FFF00
//let singleHex = Str.regexp("#\\([a-f\\|A-F\\|0-9]\\)\\([a-f\\|A-F\\|0-9]\\)\\([a-f\\|A-F\\|0-9]\\)\\([a-f\\|A-F\\|0-9]\\)");
let singleHex =
Re.Perl.re(
"#([a-f|A-F|0-9])([a-f|A-F|0-9])([a-f|A-F|0-9])([a-f|A-F|0-9]?[a-f|A-F|0-9]?)",
)
|> Re.Perl.compile;
// Matches:
// #FFFFFF
// #FFFFFF0
// #FFFFFF00
let doubleHex =
Re.Perl.re(
"#([a-f|A-F|0-9][a-f|A-F|0-9])([a-f|A-F|0-9][a-f|A-F|0-9])([a-f|A-F|0-9][a-f|A-F|0-9])([a-f|A-F|0-9]?[a-f|A-F|0-9]?)",
)
|> Re.Perl.compile;
exception ColorHexParseException(string);
let parseColor = c => {
let len = String.length(c);
let result =
switch (len) {
// Zero-length case only happens in the alpha channel, if no alpha has been specified
| 0 => Some(255)
| 1 =>
switch (int_of_string_opt("0x" ++ c)) {
| Some(v) => Some(v * 16 + v)
| None => None
}
| 2 => int_of_string_opt("0x" ++ c)
| _ => None
};
switch (result) {
| None =>
raise(ColorHexParseException("Unable to parse color component: " ++ c))
| Some(v) => float_of_int(v) /. 255.
};
};
let hex = str =>
// First, try and parse with the 'double hex' option
switch (Re.exec_opt(doubleHex, str)) {
| Some(matches) =>
let r = Re.Group.get(matches, 1) |> parseColor;
let g = Re.Group.get(matches, 2) |> parseColor;
let b = Re.Group.get(matches, 3) |> parseColor;
let a = Re.Group.get(matches, 4) |> parseColor;
rgba(r, g, b, a);
| None =>
// Now, try and parse with the 'single hex' option
switch (Re.exec_opt(singleHex, str)) {
| Some(matches) =>
let r = Re.Group.get(matches, 1) |> parseColor;
let g = Re.Group.get(matches, 2) |> parseColor;
let b = Re.Group.get(matches, 3) |> parseColor;
let a = Re.Group.get(matches, 4) |> parseColor;
rgba(r, g, b, a);
| None => raise(ColorHexParseException("Unable to parse color: " ++ str))
}
};
let multiplyAlpha = (opacity: float, color: t) => {
let a = Skia.Color.Float.getA(color);
let r = Skia.Color.Float.getR(color);
let g = Skia.Color.Float.getG(color);
let b = Skia.Color.Float.getB(color);
Skia.Color.Float.makeArgb(a *. opacity, r, g, b);
};
let mix = (~start, ~stop, ~amount) => {
let startA = Skia.Color.Float.getA(start);
let startR = Skia.Color.Float.getR(start);
let startG = Skia.Color.Float.getG(start);
let startB = Skia.Color.Float.getB(start);
let stopA = Skia.Color.Float.getA(stop);
let stopR = Skia.Color.Float.getR(stop);
let stopG = Skia.Color.Float.getG(stop);
let stopB = Skia.Color.Float.getB(stop);
let r = (stopR -. startR) *. amount +. startR;
let g = (stopG -. startG) *. amount +. startG;
let b = (stopB -. startB) *. amount +. startB;
let a = (stopA -. startA) *. amount +. startA;
Skia.Color.Float.makeArgb(a, r, g, b);
};
let opposite = color => {
let a = Skia.Color.Float.getA(color);
let r = Skia.Color.Float.getR(color);
let g = Skia.Color.Float.getG(color);
let b = Skia.Color.Float.getB(color);
Skia.Color.Float.makeArgb(a, 1. -. r, 1. -. g, 1. -. b);
};
let toRgba = (color: t) => {
let a = Skia.Color.Float.getA(color);
let r = Skia.Color.Float.getR(color);
let g = Skia.Color.Float.getG(color);
let b = Skia.Color.Float.getB(color);
(r, g, b, a);
};
let equals = (a: t, b: t) => {
a == b;
};
let toString = (color: t) => {
let a = Skia.Color.Float.getA(color);
let r = Skia.Color.Float.getR(color);
let g = Skia.Color.Float.getG(color);
let b = Skia.Color.Float.getB(color);
Printf.sprintf("(r: %f g: %f b: %f a: %f)", r, g, b, a);
};
let toSkia = (color: t) => {
color;
};