feat: added colour code preview infobox
This commit is contained in:
166
src/Infobox/ColourCode.c
Normal file
166
src/Infobox/ColourCode.c
Normal 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
9
src/Infobox/ColourCode.h
Normal 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
|
||||||
@@ -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]) };
|
||||||
|
|||||||
Reference in New Issue
Block a user