feat: added colour code preview infobox

This commit is contained in:
frosty
2026-04-14 18:13:55 -04:00
parent 3a99a37b0c
commit 6738ab0eac
3 changed files with 181 additions and 0 deletions

166
src/Infobox/ColourCode.c Normal file
View File

@@ -0,0 +1,166 @@
#include "ColourCode.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const unsigned char HEX_VALS[256] = {
['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5,
['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9, ['a'] = 10, ['b'] = 11,
['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15, ['A'] = 10, ['B'] = 11,
['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15,
};
static int is_hex_digit(char c) {
return HEX_VALS[(unsigned char)c] || c == '0';
}
static int is_valid_hex(const char *s, int len) {
if (len != 3 && len != 6)
return 0;
for (int i = 0; i < len; i++) {
if (!is_hex_digit(s[i]))
return 0;
}
return 1;
}
static void hex_to_rgb(const char *hex, int *r, int *g, int *b, int len) {
*r = *g = *b = 0;
if (len == 3) {
*r = HEX_VALS[(unsigned char)hex[0]] * 17;
*g = HEX_VALS[(unsigned char)hex[1]] * 17;
*b = HEX_VALS[(unsigned char)hex[2]] * 17;
} else if (len == 6) {
*r = HEX_VALS[(unsigned char)hex[0]] * 16 + HEX_VALS[(unsigned char)hex[1]];
*g = HEX_VALS[(unsigned char)hex[2]] * 16 + HEX_VALS[(unsigned char)hex[3]];
*b = HEX_VALS[(unsigned char)hex[4]] * 16 + HEX_VALS[(unsigned char)hex[5]];
}
}
static void rgb_to_hsl(int r, int g, int b, int *h, int *s, int *l) {
int max = r > g ? (r > b ? r : b) : (g > b ? g : b);
int min = r < g ? (r < b ? r : b) : (g < b ? g : b);
int delta = max - min;
*l = (max + min) / 2;
*s = 0;
*h = 0;
if (delta > 0) {
*s = (int)((double)delta / (1.0 - fabs(2.0 * *l / 255.0 - 1.0)) * 100.0);
if (max == r) {
*h = (int)(60.0 * fmod((double)(g - b) / delta, 6.0));
} else if (max == g) {
*h = (int)(60.0 * (((b - r) / delta) + 2.0));
} else {
*h = (int)(60.0 * (((r - g) / delta) + 4.0));
}
if (*h < 0)
*h += 360;
}
}
static void rgb_to_hsv(int r, int g, int b, int *h, int *s, int *v) {
int max = r > g ? (r > b ? r : b) : (g > b ? g : b);
int min = r < g ? (r < b ? r : b) : (g < b ? g : b);
int delta = max - min;
*v = max * 100 / 255;
*s = max > 0 ? delta * 100 / max : 0;
*h = 0;
if (delta > 0) {
if (max == r) {
*h = (int)(60.0 * fmod((double)(g - b) / delta, 6.0));
} else if (max == g) {
*h = (int)(60.0 * (((b - r) / delta) + 2.0));
} else {
*h = (int)(60.0 * (((r - g) / delta) + 4.0));
}
if (*h < 0)
*h += 360;
}
}
static void rgb_to_cmyk(int r, int g, int b, int *c, int *m, int *y, int *k) {
int max = r > g ? (r > b ? r : b) : (g > b ? g : b);
double kf = 1.0 - max / 255.0;
if (kf >= 0.99) {
*c = *m = *y = *k = 100;
} else {
*c = (int)((1.0 - r / 255.0 - kf) / (1.0 - kf) * 100);
*m = (int)((1.0 - g / 255.0 - kf) / (1.0 - kf) * 100);
*y = (int)((1.0 - b / 255.0 - kf) / (1.0 - kf) * 100);
*k = (int)(kf * 100);
}
}
int is_colour_code_query(const char *query) {
if (!query)
return 0;
const char *p = query;
if (p[0] == '#') {
p++;
while (*p == ' ')
p++;
const char *end = p;
while (is_hex_digit(*end))
end++;
int len = end - p;
return is_valid_hex(p, len);
}
return 0;
}
InfoBox fetch_colour_data(char *query) {
InfoBox info = {NULL, NULL, NULL, NULL};
if (!query)
return info;
const char *p = query;
if (p[0] != '#')
return info;
p++;
while (*p == ' ')
p++;
const char *end = p;
while (is_hex_digit(*end))
end++;
int len = end - p;
if (!is_valid_hex(p, len))
return info;
int r, g, b;
hex_to_rgb(p, &r, &g, &b, len);
int h, s, l;
rgb_to_hsl(r, g, b, &h, &s, &l);
int h2, s2, v;
rgb_to_hsv(r, g, b, &h2, &s2, &v);
int c, m, y, k;
rgb_to_cmyk(r, g, b, &c, &m, &y, &k);
char html[1024];
snprintf(html, sizeof(html),
"<div class='colour-container' style='line-height: 1.6;'>"
"<div style='display: flex; align-items: flex-start; gap: 16px;'>"
"<div style='width: 100px; height: 100px; border-radius: 12px; "
"border: 1px solid #ddd; background-color: #%.*s; flex-shrink: 0;'></div>"
"<div>"
"<div style='font-size: 1.3em; font-weight: bold; margin-bottom: 8px;'>"
"#%.*s</div>"
"<div style='color: #666; margin-bottom: 4px;'>RGB(%d, %d, %d)</div>"
"<div style='color: #666; margin-bottom: 4px;'>HSL(%d, %d%%, %d%%)</div>"
"<div style='color: #666; margin-bottom: 4px;'>HSV(%d, %d%%, %d%%)</div>"
"<div style='color: #666;'>CMYK(%d%%, %d%%, %d%%, %d%%)</div>"
"</div>"
"</div>"
"</div>",
len, p, len, p, r, g, b, h, s, l, h2, s2, v, c, m, y, k);
info.title = strdup("Colour");
info.extract = strdup(html);
info.thumbnail_url = NULL;
info.url = strdup("#");
return info;
}

9
src/Infobox/ColourCode.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef COLOURCODE_H
#define COLOURCODE_H
#include "Infobox.h"
int is_colour_code_query(const char *query);
InfoBox fetch_colour_data(char *query);
#endif

View File

@@ -1,6 +1,7 @@
#include "Search.h" #include "Search.h"
#include "../Cache/Cache.h" #include "../Cache/Cache.h"
#include "../Infobox/Calculator.h" #include "../Infobox/Calculator.h"
#include "../Infobox/ColourCode.h"
#include "../Infobox/CurrencyConversion.h" #include "../Infobox/CurrencyConversion.h"
#include "../Infobox/Dictionary.h" #include "../Infobox/Dictionary.h"
#include "../Infobox/UnitConversion.h" #include "../Infobox/UnitConversion.h"
@@ -216,11 +217,16 @@ static int is_calculator_query(const char *query) {
return 0; return 0;
} }
static InfoBox fetch_colour_wrapper(char *query) {
return fetch_colour_data(query);
}
static InfoBoxHandler handlers[] = { static InfoBoxHandler handlers[] = {
{is_dictionary_query, fetch_dict_wrapper, NULL}, {is_dictionary_query, fetch_dict_wrapper, NULL},
{is_calculator_query, fetch_calc_wrapper, NULL}, {is_calculator_query, fetch_calc_wrapper, NULL},
{is_unit_conv_query, fetch_unit_wrapper, NULL}, {is_unit_conv_query, fetch_unit_wrapper, NULL},
{is_currency_query, fetch_currency_wrapper, NULL}, {is_currency_query, fetch_currency_wrapper, NULL},
{is_colour_code_query, fetch_colour_wrapper, NULL},
{always_true, fetch_wiki_wrapper, construct_wiki_url}, {always_true, fetch_wiki_wrapper, construct_wiki_url},
}; };
enum { HANDLER_COUNT = sizeof(handlers) / sizeof(handlers[0]) }; enum { HANDLER_COUNT = sizeof(handlers) / sizeof(handlers[0]) };