xdfcgi/includes/colors.c

177 lines
4.7 KiB
C

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include "colors.h"
#define MIN_CONTRAST 0.5
void hsl2rgb(struct Rgb *dest, const struct Hls const *src) {
if ((src -> h < 0 || 360 < src -> h) ||
(src -> s < 0 && 1 < src -> s) ||
(src -> l < 0 && 1 < src -> l)) {
return;
}
float r, g, b;
float hue = src -> h;
float chroma = (1 - fabs(2 * (src -> l) - 1)) * (src -> s);
float x = chroma * (1 - fabs((int)(hue/60) % 2 - 1));
float m = (src -> l) - (chroma/2);
if (0 <= hue && hue < 60) {
r = chroma;
g = x;
b = 0;
} else if (60 <= hue && hue < 120) {
r = x;
g = chroma;
b = 0;
} else if (120 <= hue && hue < 180) {
r = 0;
g = chroma;
b = x;
} else if (180 <= hue && hue < 240) {
r = 0;
g = x;
b = chroma;
} else if (240 <= hue && hue < 300) {
r = x;
g = 0;
b = chroma;
} else if (300 <= hue && hue < 360) {
r = chroma;
g = 0;
b = x;
} else {
r = 0;
g = 0;
b = 0;
}
dest -> r = ceil((r + m) * 255);
dest -> g = ceil((g + m) * 255);
dest -> b = ceil((b + m) * 255);
}
void rgb2hsl(struct Hls *dest, const struct Rgb const *src) {
if (src == NULL || dest == NULL) {
return;
}
float r = src -> r / 255.0f;
float g = src -> g / 255.0f;
float b = src -> b / 255.0f;
float min = fmin(fmin(r, g), b);
float max = fmax(fmax(r, g), b);
dest -> l = (max + min)/2; //bi-hexcone model.
if (max == min) { // neutral color.
dest -> h = 0; // undefined.
dest -> s = 0.0f;
} else {
float chroma = max - min;
dest -> s = (dest -> l > 0.5) ? (chroma/(2 - max - min)) : (chroma/(max + min));
//piecewise function..
float hue;
if (max == r) {
hue = (int)((g - b)/chroma) + (g < b ? 6 : 0); // % 6 will break magenta (255, 0, 255)
} else if (max == g) {
hue = ((b - r)/chroma) + 2.0f;
} else {
hue = ((r - g)/chroma) + 4.0f;
}
dest -> h = (int)(hue * 60);
}
}
static void decspan(const int d) {
switch(d) {
case 0:
printf("<span style='color:rgb(128,128,128)'>");
break;
case 1:
printf("<span style='color:rgb(255,0,0)'>");
break;
case 2:
printf("<span style='color:rgb(51,255,0)'>");
break;
case 3:
printf("<span style='color:rgb(255,255,0)'>");
break;
case 4:
printf("<span style='color:rgb(51,102,255)'>");
break;
case 5:
printf("<span style='color:rgb(51,255,255)'>");
break;
case 6:
printf("<span style='color:rgb(255,51,102)'>");
break;
case 7:
printf("<span style='color:rgb(255,255,255)'>");
break;
case 8:
printf("<span style='color:rgb(153,153,153)'>");
break;
case 9:
printf("<span style='color:rgb(128,128,128)'>");
break;
}
}
static void hexspan(const char *str) {
const char h1[2] = {str[0], '\0'};
const char h2[2] = {str[1], '\0'};
const char h3[2] = {str[2], '\0'};
struct Rgb nrgb;
nrgb.r = strtol(h1, NULL, 16);
nrgb.g = strtol(h2, NULL, 16);
nrgb.b = strtol(h3, NULL, 16);
struct Hls nhls;
rgb2hsl(&nhls, &nrgb);
if (nhls.l < MIN_CONTRAST) {
nhls.l = MIN_CONTRAST;
hsl2rgb(&nrgb, &nhls);
}
printf("<span style=\"color:rgb(%d,%d,%d)\">", nrgb.r, nrgb.g, nrgb.b);
}
static void b(char * const str) {
char *token = strtok(str, "^");
char c;
printf("<TD>");
while (token) {
c = token[0];
if (isdigit(c)) {
decspan(c - ASCII_ZERO);
if (strlen(token) > 1) {
printf("%s", token + 1);
}
} else if (c == 'x' && strlen(token) > 3) {
if (isxdigit(token[1]) && isxdigit(token[2]) && isxdigit(token[3])) {
hexspan(token + 1); //exclude x
if (strlen(token) > 4){
printf("%s", token + 4);
}
printf("</span>");
}
} else {
printf("%s", token);
}
token = strtok(NULL, "^");
}
printf("</TD>");
}
void print_plname(const char* str) {
//find instance of ^^
//replace with ^
//concatenate with rest of the string
char *copy;
copy = calloc(strlen(str) + 1, sizeof(char));
strcpy(copy, str);
char *pos = copy;
while (pos = strstr(pos, "^^")) {
strcpy(pos, (pos + 1));
}
b(copy);
free(copy);
}