6 Color rgba(float r, float g, float b, float a)
18 /* TODO: hue is in degrees in 2019 */
19 Color hsla(float h, float s, float l, float a)
23 const float c = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
24 const float x = c * (1 - fabsf(fmodf(h / 60.0f, 2.0f) - 1.0f));
25 const float m = l - c / 2.0f;
29 if (0.0f <= h && h < 60.0f) {
30 color = rgba(c, x, 0.0f, a);
31 } else if (60.0f <= h && h < 120.0f) {
32 color = rgba(x, c, 0.0f, a);
33 } else if (120.0f <= h && h < 180.0f) {
34 color = rgba(0.0f, c, x, a);
35 } else if (180.0f <= h && h < 240.0f) {
36 color = rgba(0.0f, x, c, a);
37 } else if (240.0f <= h && h < 300.0f) {
38 color = rgba(x, 0.0f, c, a);
39 } else if (300.0f <= h && h < 360.0f) {
40 color = rgba(c, 0.0f, x, a);
50 static Uint8 hex2dec_digit(char c)
52 if (c >= '0' && c <= '9') {
53 return (Uint8) (c - '0');
56 if (c >= 'A' && c <= 'F') {
57 return (Uint8) (10 + c - 'A');
60 if (c >= 'a' && c <= 'f') {
61 return (Uint8) (10 + c - 'a');
67 static Uint8 parse_color_component(const char *component)
69 return (Uint8) (hex2dec_digit(component[0]) * 16 + hex2dec_digit(component[1]));
72 Color hexstr(const char *hexstr)
74 if (strlen(hexstr) != 6) {
75 return rgba(0.0f, 0.0f, 0.0f, 1.0f);
79 parse_color_component(hexstr) / 255.0f,
80 parse_color_component(hexstr + 2) / 255.0f,
81 parse_color_component(hexstr + 4) / 255.0f,
85 SDL_Color color_for_sdl(Color color)
87 const SDL_Color result = {
88 .r = (Uint8)roundf(color.r * 255.0f),
89 .g = (Uint8)roundf(color.g * 255.0f),
90 .b = (Uint8)roundf(color.b * 255.0f),
91 .a = (Uint8)roundf(color.a * 255.0f)
97 Color color_desaturate(Color c)
99 const float k = (c.r + c.g + c.b) / 3.0f;
100 return rgba(k, k, k, c.a);
103 Color color_darker(Color c, float d)
105 return rgba(fmaxf(c.r - d, 0.0f),
106 fmaxf(c.g - d, 0.0f),
107 fmaxf(c.b - d, 0.0f),
111 Color color_invert(Color c)
113 return rgba(1.0f - c.r, 1.0f - c.g, 1.0f - c.b, c.a);
116 Color color_scale(Color c, Color fc)
119 fmaxf(fminf(c.r * fc.r, 1.0f), 0.0f),
120 fmaxf(fminf(c.g * fc.g, 1.0f), 0.0f),
121 fmaxf(fminf(c.b * fc.b, 1.0f), 0.0f),
122 fmaxf(fminf(c.a * fc.a, 1.0f), 0.0f));
125 int color_hex_to_stream(Color color, FILE *stream)
127 SDL_Color sdl = color_for_sdl(color);
128 return fprintf(stream, "%02x%02x%02x", sdl.r, sdl.g, sdl.b);
131 Color rgba_to_hsla(Color color)
133 const float max = fmaxf(color.r, fmaxf(color.g, color.b));
134 const float min = fminf(color.r, fminf(color.g, color.b));
135 const float c = max - min;
137 float saturation = 0.0f;
138 const float lightness = (max + min) * 0.5f;
140 if (fabsf(c) > 1e-6) {
141 if (fabs(max - color.r) <= 1e-6) {
142 hue = 60.0f * fmodf((color.g - color.b) / c, 6.0f);
143 } else if (fabs(max - color.g) <= 1e-6) {
144 hue = 60.0f * ((color.b - color.r) / c + 2.0f);
146 hue = 60.0f * ((color.r - color.g) / c + 4.0f);
149 saturation = c / (1.0f - fabsf(2.0f * lightness - 1.0f));
152 // TODO: Color struct is used not only for RGBA
153 // But also for HSLA. We should make another similar struct but for HSLA
154 return rgba(hue, saturation, lightness, color.a);