diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-05 10:44:52 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-08-05 10:44:52 +0300 |
commit | ddb3dd5c4278f4ecfbd76351cb1651581dd9ec49 (patch) | |
tree | 316839d72f77e7e0e50b8ff2cb7ddfb3070a9c76 /src/ui | |
parent | 84909b4deba7ed90eed591cefe457be482628ecf (diff) |
Color: Added HSL conversions
Removed the extra 15/88 grays from the UI palette.
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/color.c | 135 | ||||
-rw-r--r-- | src/ui/color.h | 79 |
2 files changed, 171 insertions, 43 deletions
diff --git a/src/ui/color.c b/src/ui/color.c index 46d8a71f..0402d0fb 100644 --- a/src/ui/color.c +++ b/src/ui/color.c | |||
@@ -4,40 +4,125 @@ | |||
4 | 4 | ||
5 | static const iColor transparent_; | 5 | static const iColor transparent_; |
6 | 6 | ||
7 | static iColor palette_[max_ColorId] = { | ||
8 | { 0, 0, 0, 255 }, | ||
9 | { 40, 40, 40, 255 }, | ||
10 | { 80, 80, 80, 255 }, | ||
11 | { 160, 160, 160, 255 }, | ||
12 | { 255, 255, 255, 255 }, | ||
13 | { 106, 80, 0, 255 }, | ||
14 | { 255, 192, 0, 255 }, | ||
15 | { 0, 96, 128, 255 }, | ||
16 | { 0, 192, 255, 255 }, | ||
17 | { 255, 255, 32, 255 }, | ||
18 | { 255, 64, 64, 255 }, | ||
19 | { 255, 0, 255, 255 }, | ||
20 | { 132, 132, 255, 255 }, | ||
21 | { 0, 200, 0, 255 }, | ||
22 | /* theme colors left black until theme is seeded */ | ||
23 | }; | ||
24 | |||
7 | iColor get_Color(int color) { | 25 | iColor get_Color(int color) { |
8 | static const iColor palette[] = { | 26 | const iColor *rgba = &transparent_; |
9 | { 0, 0, 0, 255 }, | 27 | if (color >= 0 && color < max_ColorId) { |
10 | { 24, 24, 24, 255 }, | 28 | rgba = &palette_[color]; |
11 | { 40, 40, 40, 255 }, | 29 | } |
12 | { 80, 80, 80, 255 }, | 30 | return *rgba; |
13 | { 160, 160, 160, 255 }, | 31 | } |
14 | { 208, 208, 208, 255 }, | 32 | |
15 | { 255, 255, 255, 255 }, | 33 | void set_Color(int color, iColor rgba) { |
16 | { 106, 80, 0, 255 }, | 34 | if (color >= tmFirst_ColorId && color < max_ColorId) { |
17 | { 255, 192, 0, 255 }, | 35 | palette_[color] = rgba; |
18 | { 0, 96, 128, 255 }, | ||
19 | { 0, 192, 255, 255 }, | ||
20 | { 255, 255, 32, 255 }, | ||
21 | { 255, 64, 64, 255 }, | ||
22 | { 255, 0, 255, 255 }, | ||
23 | { 132, 132, 255, 255 }, | ||
24 | { 0, 200, 0, 255 }, | ||
25 | }; | ||
26 | const iColor *clr = &transparent_; | ||
27 | if (color >= 0 && color < (int) iElemCount(palette)) { | ||
28 | clr = &palette[color]; | ||
29 | } | 36 | } |
30 | return *clr; | 37 | } |
38 | |||
39 | iLocalDef iFloat4 normalize_(iColor d) { | ||
40 | return divf_F4(init_F4(d.r, d.g, d.b, d.a), 255.0f); | ||
41 | } | ||
42 | |||
43 | iLocalDef iColor toColor_(iFloat4 d) { | ||
44 | const iFloat4 i = addf_F4(mulf_F4(d, 255.0f), 0.5f); | ||
45 | return (iColor){ (uint8_t) x_F4(i), | ||
46 | (uint8_t) y_F4(i), | ||
47 | (uint8_t) z_F4(i), | ||
48 | (uint8_t) w_F4(i) }; | ||
49 | } | ||
50 | |||
51 | iHSLColor hsl_Color(iColor color) { | ||
52 | float rgb[4]; | ||
53 | store_F4(normalize_(color), rgb); | ||
54 | int compMax, compMin; | ||
55 | if (rgb[0] >= rgb[1] && rgb[0] >= rgb[2]) { | ||
56 | compMax = 0; | ||
57 | } | ||
58 | else if (rgb[1] >= rgb[0] && rgb[1] >= rgb[2]) { | ||
59 | compMax = 1; | ||
60 | } | ||
61 | else { | ||
62 | compMax = 2; | ||
63 | } | ||
64 | if (rgb[0] <= rgb[1] && rgb[0] <= rgb[2]) { | ||
65 | compMin = 0; | ||
66 | } | ||
67 | else if (rgb[1] <= rgb[0] && rgb[1] <= rgb[2]) { | ||
68 | compMin = 1; | ||
69 | } | ||
70 | else { | ||
71 | compMin = 2; | ||
72 | } | ||
73 | const float rgbMax = rgb[compMax]; | ||
74 | const float rgbMin = rgb[compMin]; | ||
75 | const float lum = (rgbMax + rgbMin) / 2.0f; | ||
76 | float hue = 0.0f; | ||
77 | float sat = 0.0f; | ||
78 | if (fabsf(rgbMax - rgbMin) > 0.00001f) { | ||
79 | float chr = rgbMax - rgbMin; | ||
80 | sat = chr / (1.0f - fabsf(2.0f * lum - 1.0f)); | ||
81 | if (compMax == 0) { | ||
82 | hue = (rgb[1] - rgb[2]) / chr + (rgb[1] < rgb[2] ? 6 : 0); | ||
83 | } | ||
84 | else if (compMax == 1) { | ||
85 | hue = (rgb[2] - rgb[0]) / chr + 2; | ||
86 | } | ||
87 | else { | ||
88 | hue = (rgb[0] - rgb[1]) / chr + 4; | ||
89 | } | ||
90 | } | ||
91 | return (iHSLColor){ hue * 60, sat, lum, rgb[3] }; /* hue in degrees */ | ||
92 | } | ||
93 | |||
94 | static float hueToRgb_(float p, float q, float t) { | ||
95 | if (t < 0.0f) t += 1.0f; | ||
96 | if (t > 1.0f) t -= 1.0f; | ||
97 | if (t < 1.0f / 6.0f) return p + (q - p) * 6.0f * t; | ||
98 | if (t < 1.0f / 2.0f) return q; | ||
99 | if (t < 2.0f / 3.0f) return p + (q - p) * (2.0f / 3.0f - t) * 6.0f; | ||
100 | return p; | ||
101 | } | ||
102 | |||
103 | iColor fromHsl_Color(iHSLColor hsl) { | ||
104 | float r, g, b; | ||
105 | hsl.hue /= 360.0f; | ||
106 | if (hsl.sat < 0.00001f) { | ||
107 | r = g = b = hsl.lum; | ||
108 | } | ||
109 | else { | ||
110 | const float q = hsl.lum < 0.5f ? hsl.lum * (1 + hsl.sat) | ||
111 | : (hsl.lum + hsl.sat - hsl.lum * hsl.sat); | ||
112 | const float p = 2 * hsl.lum - q; | ||
113 | r = hueToRgb_(p, q, hsl.hue + 1.0f / 3.0f); | ||
114 | g = hueToRgb_(p, q, hsl.hue); | ||
115 | b = hueToRgb_(p, q, hsl.hue - 1.0f / 3.0f); | ||
116 | } | ||
117 | return toColor_(init_F4(r, g, b, hsl.a)); | ||
31 | } | 118 | } |
32 | 119 | ||
33 | const char *escape_Color(int color) { | 120 | const char *escape_Color(int color) { |
34 | static const char *esc[] = { | 121 | static const char *esc[] = { |
35 | black_ColorEscape, | 122 | black_ColorEscape, |
36 | gray15_ColorEscape, | ||
37 | gray25_ColorEscape, | 123 | gray25_ColorEscape, |
38 | gray50_ColorEscape, | 124 | gray50_ColorEscape, |
39 | gray75_ColorEscape, | 125 | gray75_ColorEscape, |
40 | gray88_ColorEscape, | ||
41 | white_ColorEscape, | 126 | white_ColorEscape, |
42 | brown_ColorEscape, | 127 | brown_ColorEscape, |
43 | orange_ColorEscape, | 128 | orange_ColorEscape, |
@@ -49,7 +134,7 @@ const char *escape_Color(int color) { | |||
49 | blue_ColorEscape, | 134 | blue_ColorEscape, |
50 | green_ColorEscape, | 135 | green_ColorEscape, |
51 | }; | 136 | }; |
52 | if (color >= 0 && color < max_ColorId) { | 137 | if (color >= 0 && color < (int) iElemCount(esc)) { |
53 | return esc[color]; | 138 | return esc[color]; |
54 | } | 139 | } |
55 | return white_ColorEscape; | 140 | return white_ColorEscape; |
diff --git a/src/ui/color.h b/src/ui/color.h index 01e49c9c..11feb63e 100644 --- a/src/ui/color.h +++ b/src/ui/color.h | |||
@@ -1,15 +1,14 @@ | |||
1 | #pragma once | 1 | #pragma once |
2 | 2 | ||
3 | #include <the_Foundation/range.h> | 3 | #include <the_Foundation/range.h> |
4 | #include <the_Foundation/math.h> | ||
4 | 5 | ||
5 | enum iColorId { | 6 | enum iColorId { |
6 | none_ColorId = -1, | 7 | none_ColorId = -1, |
7 | black_ColorId, | 8 | black_ColorId, |
8 | gray15_ColorId, | ||
9 | gray25_ColorId, | 9 | gray25_ColorId, |
10 | gray50_ColorId, | 10 | gray50_ColorId, |
11 | gray75_ColorId, | 11 | gray75_ColorId, |
12 | gray88_ColorId, | ||
13 | white_ColorId, | 12 | white_ColorId, |
14 | brown_ColorId, | 13 | brown_ColorId, |
15 | orange_ColorId, | 14 | orange_ColorId, |
@@ -20,35 +19,79 @@ enum iColorId { | |||
20 | magenta_ColorId, | 19 | magenta_ColorId, |
21 | blue_ColorId, | 20 | blue_ColorId, |
22 | green_ColorId, | 21 | green_ColorId, |
22 | /* content theme colors */ | ||
23 | tmFirst_ColorId, | ||
24 | tmBackground_ColorId = tmFirst_ColorId, | ||
25 | tmParagraph_ColorId, | ||
26 | tmFirstParagraph_ColorId, | ||
27 | tmQuote_ColorId, | ||
28 | tmPreformatted_ColorId, | ||
29 | tmHeader1_ColorId, | ||
30 | tmHeader2_ColorId, | ||
31 | tmHeader3_ColorId, | ||
32 | |||
33 | tmLinkIcon_ColorId, | ||
34 | tmLinkIconVisited_ColorId, | ||
35 | tmLinkText_ColorId, | ||
36 | tmLinkTextHover_ColorId, | ||
37 | tmLinkDomain_ColorId, | ||
38 | tmLinkLastVisitDate_ColorId, | ||
39 | |||
40 | tmHypertextLinkIcon_ColorId, | ||
41 | tmHypertextLinkIconVisited_ColorId, | ||
42 | tmHypertextLinkText_ColorId, | ||
43 | tmHypertextLinkTextHover_ColorId, | ||
44 | tmHypertextLinkDomain_ColorId, | ||
45 | tmHypertextLinkLastVisitDate_ColorId, | ||
46 | |||
47 | tmGopherLinkIcon_ColorId, | ||
48 | tmGopherLinkIconVisited_ColorId, | ||
49 | tmGopherLinkText_ColorId, | ||
50 | tmGopherLinkTextHover_ColorId, | ||
51 | tmGopherLinkDomain_ColorId, | ||
52 | tmGopherLinkLastVisitDate_ColorId, | ||
53 | |||
54 | tmInlineContentMetadata_ColorId, | ||
55 | tmBannerBackground_ColorId, | ||
56 | tmBannerTitle_ColorId, | ||
57 | tmBannerIcon_ColorId, | ||
23 | max_ColorId | 58 | max_ColorId |
24 | }; | 59 | }; |
25 | 60 | ||
26 | #define mask_ColorId 0x0f | 61 | #define mask_ColorId 0x3f |
27 | #define permanent_ColorId 0x80 /* cannot be changed via escapes */ | 62 | #define permanent_ColorId 0x80 /* cannot be changed via escapes */ |
28 | 63 | ||
29 | #define black_ColorEscape "\r0" | 64 | #define black_ColorEscape "\r0" |
30 | #define gray15_ColorEscape "\r1" | 65 | #define gray25_ColorEscape "\r1" |
31 | #define gray25_ColorEscape "\r2" | 66 | #define gray50_ColorEscape "\r2" |
32 | #define gray50_ColorEscape "\r3" | 67 | #define gray75_ColorEscape "\r3" |
33 | #define gray75_ColorEscape "\r4" | 68 | #define white_ColorEscape "\r4" |
34 | #define gray88_ColorEscape "\r5" | 69 | #define brown_ColorEscape "\r5" |
35 | #define white_ColorEscape "\r6" | 70 | #define orange_ColorEscape "\r6" |
36 | #define brown_ColorEscape "\r7" | 71 | #define teal_ColorEscape "\r7" |
37 | #define orange_ColorEscape "\r8" | 72 | #define cyan_ColorEscape "\r8" |
38 | #define teal_ColorEscape "\r9" | 73 | #define yellow_ColorEscape "\r9" |
39 | #define cyan_ColorEscape "\r:" | 74 | #define red_ColorEscape "\r:" |
40 | #define yellow_ColorEscape "\r;" | 75 | #define magenta_ColorEscape "\r;" |
41 | #define red_ColorEscape "\r<" | 76 | #define blue_ColorEscape "\r<" |
42 | #define magenta_ColorEscape "\r=" | 77 | #define green_ColorEscape "\r=" |
43 | #define blue_ColorEscape "\r>" | ||
44 | #define green_ColorEscape "\r?" | ||
45 | 78 | ||
46 | iDeclareType(Color) | 79 | iDeclareType(Color) |
80 | iDeclareType(HSLColor) | ||
47 | 81 | ||
48 | struct Impl_Color { | 82 | struct Impl_Color { |
49 | uint8_t r, g, b, a; | 83 | uint8_t r, g, b, a; |
50 | }; | 84 | }; |
51 | 85 | ||
86 | struct Impl_HSLColor { | ||
87 | float hue, sat, lum, a; | ||
88 | }; | ||
89 | |||
52 | iColor get_Color (int color); | 90 | iColor get_Color (int color); |
91 | void set_Color (int color, iColor rgba); | ||
92 | |||
93 | iHSLColor hsl_Color (iColor rgba); | ||
94 | iColor fromHsl_Color (iHSLColor hsl); | ||
95 | |||
53 | iColor ansi_Color (iRangecc escapeSequence, int fallback); | 96 | iColor ansi_Color (iRangecc escapeSequence, int fallback); |
54 | const char * escape_Color (int color); | 97 | const char * escape_Color (int color); |