From c7f323bf733160016247368883a58a9d467468b4 Mon Sep 17 00:00:00 2001 From: pommicket Date: Thu, 7 Sep 2023 19:30:51 -0400 Subject: move color-related functions from util.c to color.c --- buffer.c | 4 +-- colors.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++-- config.c | 2 +- gl.c | 2 +- ide-autocomplete.c | 6 ++-- main.c | 4 +-- ted.h | 4 +++ text.c | 2 +- util.c | 98 --------------------------------------------------- util.h | 4 --- 10 files changed, 113 insertions(+), 114 deletions(-) diff --git a/buffer.c b/buffer.c index 8d48c6d..39d28ac 100644 --- a/buffer.c +++ b/buffer.c @@ -3372,7 +3372,7 @@ void buffer_render(TextBuffer *buffer, Rect r) { } } // set color - rgba_u32_to_floats(line_number_color, text_state.color); + color_u32_to_floats(line_number_color, text_state.color); text_state.x = x; text_state.y = y; text_state_break_kerning(&text_state); text_utf8_with_state(font, &text_state, str); @@ -3532,7 +3532,7 @@ void buffer_render(TextBuffer *buffer, Rect r) { if (syntax_highlighting) { SyntaxCharType type = char_types[i]; ColorSetting color = syntax_char_type_to_color_setting(type); - rgba_u32_to_floats(settings_color(settings, color), text_state.color); + color_u32_to_floats(settings_color(settings, color), text_state.color); } buffer_render_char(buffer, font, &text_state, c); } diff --git a/colors.c b/colors.c index d9ef7aa..289d286 100644 --- a/colors.c +++ b/colors.c @@ -195,7 +195,104 @@ float color_contrast_ratio(const float rgb1[3], const float rgb2[3]) { float color_contrast_ratio_u32(u32 color1, u32 color2) { float rgb1[4], rgb2[4]; - rgba_u32_to_floats(color1, rgb1); - rgba_u32_to_floats(color2, rgb2); + color_u32_to_floats(color1, rgb1); + color_u32_to_floats(color2, rgb2); return color_contrast_ratio(rgb1, rgb2); } + +void color_u32_to_floats(u32 rgba, float floats[4]) { + floats[0] = (float)((rgba >> 24) & 0xff) / 255.f; + floats[1] = (float)((rgba >> 16) & 0xff) / 255.f; + floats[2] = (float)((rgba >> 8) & 0xff) / 255.f; + floats[3] = (float)((rgba >> 0) & 0xff) / 255.f; +} + +vec4 color_u32_to_vec4(u32 rgba) { + float c[4]; + color_u32_to_floats(rgba, c); + return (vec4){c[0], c[1], c[2], c[3]}; +} + +u32 color_vec4_to_u32(vec4 color) { + return (u32)(color.x * 255) << 24 + | (u32)(color.y * 255) << 16 + | (u32)(color.z * 255) << 8 + | (u32)(color.w * 255); +} + +static vec4 color_rgba_to_hsva(vec4 rgba) { + float R = rgba.x, G = rgba.y, B = rgba.z, A = rgba.w; + float M = maxf(R, maxf(G, B)); + float m = minf(R, minf(G, B)); + float C = M - m; + float H = 0; + if (C == 0) + H = 0; + else if (M == R) + H = fmodf((G - B) / C, 6); + else if (M == G) + H = (B - R) / C + 2; + else if (M == B) + H = (R - G) / C + 4; + H *= 60; + float V = M; + float S = V == 0 ? 0 : C / V; + return (vec4){H, S, V, A}; +} + +static vec4 color_hsva_to_rgba(vec4 hsva) { + float H = hsva.x, S = hsva.y, V = hsva.z, A = hsva.w; + H /= 60; + float C = S * V; + float X = C * (1 - fabsf(fmodf(H, 2) - 1)); + float R, G, B; + if (H <= 1) + R=C, G=X, B=0; + else if (H <= 2) + R=X, G=C, B=0; + else if (H <= 3) + R=0, G=C, B=X; + else if (H <= 4) + R=0, G=X, B=C; + else if (H <= 5) + R=X, G=0, B=C; + else + R=C, G=0, B=X; + + float m = V-C; + R += m; + G += m; + B += m; + return (vec4){R, G, B, A}; +} + +u32 color_interpolate(float x, u32 color1, u32 color2) { + x = x * x * (3 - 2*x); // hermite interpolation + + vec4 c1 = color_u32_to_vec4(color1), c2 = color_u32_to_vec4(color2); + // to make it interpolate more nicely, convert to hsv, interpolate in that space, then convert back + c1 = color_rgba_to_hsva(c1); + c2 = color_rgba_to_hsva(c2); + // v_1/2 named differently to avoid shadowing + float h1 = c1.x, s1 = c1.y, v_1 = c1.z, a1 = c1.w; + float h2 = c2.x, s2 = c2.y, v_2 = c2.z, a2 = c2.w; + + float s_out = lerpf(x, s1, s2); + float v_out = lerpf(x, v_1, v_2); + float a_out = lerpf(x, a1, a2); + + float h_out; + // because hue is on a circle, we need to make sure we take the shorter route around the circle + if (fabsf(h1 - h2) < 180) { + h_out = lerpf(x, h1, h2); + } else if (h1 > h2) { + h_out = lerpf(x, h1, h2 + 360); + } else { + h_out = lerpf(x, h1 + 360, h2); + } + h_out = fmodf(h_out, 360); + + vec4 c_out = (vec4){h_out, s_out, v_out, a_out}; + c_out = color_hsva_to_rgba(c_out); + return color_vec4_to_u32(c_out); +} diff --git a/config.c b/config.c index 6dce3bc..e575803 100644 --- a/config.c +++ b/config.c @@ -1310,7 +1310,7 @@ u32 settings_color(const Settings *settings, ColorSetting color) { } void settings_color_floats(const Settings *settings, ColorSetting color, float f[4]) { - rgba_u32_to_floats(settings_color(settings, color), f); + color_u32_to_floats(settings_color(settings, color), f); } diff --git a/gl.c b/gl.c index bf03250..52902e6 100644 --- a/gl.c +++ b/gl.c @@ -232,7 +232,7 @@ void gl_geometry_init(void) { void gl_geometry_rect(Rect r, u32 color_rgba) { if (r.size.x <= 0 || r.size.y <= 0) return; - vec4 color = rgba_u32_to_vec4(color_rgba); + vec4 color = color_u32_to_vec4(color_rgba); vec2 p1 = {rect_x1(r), rect_y1(r)}; vec2 p2 = {rect_x1(r), rect_y2(r)}; diff --git a/ide-autocomplete.c b/ide-autocomplete.c index 295dcda..0ad78ed 100644 --- a/ide-autocomplete.c +++ b/ide-autocomplete.c @@ -668,7 +668,7 @@ void autocomplete_frame(Ted *ted) { text_state.x = doc_x + padding; text_state.y = doc_y + padding; text_state.wrap = true; - rgba_u32_to_floats(colors[COLOR_TEXT], text_state.color); + color_u32_to_floats(colors[COLOR_TEXT], text_state.color); text_utf8_with_state(font, &text_state, document->documentation); } } @@ -688,7 +688,7 @@ void autocomplete_frame(Ted *ted) { float y = start_y; TextRenderState state = text_render_state_default; state.min_x = x + padding; state.min_y = y; state.max_x = x + menu_width - padding; state.max_y = y + menu_height; - rgba_u32_to_floats(colors[COLOR_TEXT], state.color); + color_u32_to_floats(colors[COLOR_TEXT], state.color); if (waiting_for_lsp && ncompletions == 0) { state.x = x + padding; state.y = y; @@ -708,7 +708,7 @@ void autocomplete_frame(Ted *ted) { if (!settings->syntax_highlighting) label_color = COLOR_TEXT; - rgba_u32_to_floats(colors[label_color], state.color); + color_u32_to_floats(colors[label_color], state.color); // draw icon char icon_text[2] = {symbol_kind_icon(completion->kind), 0}; diff --git a/main.c b/main.c index dbfb6a1..5791ad2 100644 --- a/main.c +++ b/main.c @@ -922,7 +922,7 @@ int main(int argc, char **argv) { glViewport(0, 0, (GLsizei)window_width, (GLsizei)window_height); { // clear (background) float bg_color[4]; - rgba_u32_to_floats(ted_active_color(ted, COLOR_BG), bg_color); + color_u32_to_floats(ted_active_color(ted, COLOR_BG), bg_color); glClearColor(bg_color[0], bg_color[1], bg_color[2], bg_color[3]); } glClear(GL_COLOR_BUFFER_BIT); @@ -1090,7 +1090,7 @@ int main(int argc, char **argv) { text_state.x = text_x1; text_state.y = text_y1; text_state.wrap = true; - rgba_u32_to_floats(ted_active_color(ted, COLOR_TEXT), text_state.color); + color_u32_to_floats(ted_active_color(ted, COLOR_TEXT), text_state.color); text_utf8_with_state(font, &text_state, ted->message_shown); gl_geometry_draw(); text_render(font); diff --git a/ted.h b/ted.h index 8de7fc4..2cc7d3a 100644 --- a/ted.h +++ b/ted.h @@ -807,6 +807,10 @@ float color_contrast_ratio(const float rgb1[3], const float rgb2[3]); /// /// the "alpha" components (i.e. lowest 8 bits) of `color1`, `color2` are ignored float color_contrast_ratio_u32(u32 color1, u32 color2); +void color_u32_to_floats(u32 rgba, float floats[4]); +vec4 color_u32_to_vec4(u32 rgba); +u32 color_vec4_to_u32(vec4 color); +u32 color_interpolate(float x, u32 color1, u32 color2); // === command.c === /// parse command diff --git a/text.c b/text.c index 4e21143..8b4e38f 100644 --- a/text.c +++ b/text.c @@ -493,7 +493,7 @@ static vec2 text_render_utf8_internal(Font *font, const char *text, double x, do render_state.render = render; render_state.x = x; render_state.y = y; - rgba_u32_to_floats(color, render_state.color); + color_u32_to_floats(color, render_state.color); text_utf8_with_state(font, &render_state, text); return (vec2){ maxf(0.0f, (float)(render_state.x_largest - x)), diff --git a/util.c b/util.c index 1b9b9f3..bdeb687 100644 --- a/util.c +++ b/util.c @@ -720,26 +720,6 @@ vec2 vec2_polar(float r, float theta) { return (vec2){r * cosf(theta), r * sinf(theta)}; } -void rgba_u32_to_floats(u32 rgba, float floats[4]) { - floats[0] = (float)((rgba >> 24) & 0xFF) / 255.f; - floats[1] = (float)((rgba >> 16) & 0xFF) / 255.f; - floats[2] = (float)((rgba >> 8) & 0xFF) / 255.f; - floats[3] = (float)((rgba >> 0) & 0xFF) / 255.f; -} - -vec4 rgba_u32_to_vec4(u32 rgba) { - float c[4]; - rgba_u32_to_floats(rgba, c); - return (vec4){c[0], c[1], c[2], c[3]}; -} - -u32 rgba_vec4_to_u32(vec4 color) { - return (u32)(color.x * 255) << 24 - | (u32)(color.y * 255) << 16 - | (u32)(color.z * 255) << 8 - | (u32)(color.w * 255); -} - bool rect_contains_point_v2(vec2 pos, vec2 size, vec2 point) { float x1 = pos.x, y1 = pos.y, x2 = pos.x + size.x, y2 = pos.y + size.y, x = point.x, y = point.y; @@ -868,84 +848,6 @@ void rect_grow(Rect *r, float amount) { r->size.y += 2 * amount; } -static vec4 color_rgba_to_hsva(vec4 rgba) { - float R = rgba.x, G = rgba.y, B = rgba.z, A = rgba.w; - float M = maxf(R, maxf(G, B)); - float m = minf(R, minf(G, B)); - float C = M - m; - float H = 0; - if (C == 0) - H = 0; - else if (M == R) - H = fmodf((G - B) / C, 6); - else if (M == G) - H = (B - R) / C + 2; - else if (M == B) - H = (R - G) / C + 4; - H *= 60; - float V = M; - float S = V == 0 ? 0 : C / V; - return (vec4){H, S, V, A}; -} - -static vec4 color_hsva_to_rgba(vec4 hsva) { - float H = hsva.x, S = hsva.y, V = hsva.z, A = hsva.w; - H /= 60; - float C = S * V; - float X = C * (1 - fabsf(fmodf(H, 2) - 1)); - float R, G, B; - if (H <= 1) - R=C, G=X, B=0; - else if (H <= 2) - R=X, G=C, B=0; - else if (H <= 3) - R=0, G=C, B=X; - else if (H <= 4) - R=0, G=X, B=C; - else if (H <= 5) - R=X, G=0, B=C; - else - R=C, G=0, B=X; - - float m = V-C; - R += m; - G += m; - B += m; - return (vec4){R, G, B, A}; -} - -u32 color_interpolate(float x, u32 color1, u32 color2) { - x = x * x * (3 - 2*x); // hermite interpolation - - vec4 c1 = rgba_u32_to_vec4(color1), c2 = rgba_u32_to_vec4(color2); - // to make it interpolate more nicely, convert to hsv, interpolate in that space, then convert back - c1 = color_rgba_to_hsva(c1); - c2 = color_rgba_to_hsva(c2); - // v_1/2 named differently to avoid shadowing - float h1 = c1.x, s1 = c1.y, v_1 = c1.z, a1 = c1.w; - float h2 = c2.x, s2 = c2.y, v_2 = c2.z, a2 = c2.w; - - float s_out = lerpf(x, s1, s2); - float v_out = lerpf(x, v_1, v_2); - float a_out = lerpf(x, a1, a2); - - float h_out; - // because hue is on a circle, we need to make sure we take the shorter route around the circle - if (fabsf(h1 - h2) < 180) { - h_out = lerpf(x, h1, h2); - } else if (h1 > h2) { - h_out = lerpf(x, h1, h2 + 360); - } else { - h_out = lerpf(x, h1 + 360, h2); - } - h_out = fmodf(h_out, 360); - - vec4 c_out = (vec4){h_out, s_out, v_out, a_out}; - c_out = color_hsva_to_rgba(c_out); - return rgba_vec4_to_u32(c_out); -} - - int timespec_cmp(struct timespec a, struct timespec b) { if (a.tv_sec > b.tv_sec) return 1; if (a.tv_sec < b.tv_sec) return -1; diff --git a/util.h b/util.h index 25ff72b..97db6fd 100644 --- a/util.h +++ b/util.h @@ -216,9 +216,6 @@ vec2 vec2_normalize(vec2 v); float vec2_distance(vec2 a, vec2 b); void vec2_print(vec2 v); vec2 vec2_polar(float r, float theta); -void rgba_u32_to_floats(u32 rgba, float floats[4]); -vec4 rgba_u32_to_vec4(u32 rgba); -u32 rgba_vec4_to_u32(vec4 color); bool rect_contains_point_v2(vec2 pos, vec2 size, vec2 point); bool centered_rect_contains_point(vec2 center, vec2 size, vec2 point); Rect rect(vec2 pos, vec2 size); @@ -250,7 +247,6 @@ void rect_shrink_right(Rect *r, float amount); void rect_shrink_bottom(Rect *r, float amount); /// adds `amount` to all sides of r void rect_grow(Rect *r, float amount); -u32 color_interpolate(float x, u32 color1, u32 color2); int timespec_cmp(struct timespec a, struct timespec b); bool timespec_eq(struct timespec a, struct timespec b); struct timespec timespec_max(struct timespec a, struct timespec b); -- cgit v1.2.3