#include #include #include #include #include #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)/60.0f; const float chroma = (1 - fabs((2 * (src -> l)) - 1)) * (src -> s); float x = chroma * (1 - fabs(fmod(hue, 2) - 1)); float m = (src -> l) - (chroma/2); if (0 <= hue && hue < 1) { r = chroma; g = x; b = 0; } else if (1 <= hue && hue < 2) { r = x; g = chroma; b = 0; } else if (2 <= hue && hue < 3) { r = 0; g = chroma; b = x; } else if (3 <= hue && hue < 4) { r = 0; g = x; b = chroma; } else if (4 <= hue && hue < 5) { r = x; g = 0; b = chroma; } else if (5 <= hue && hue < 6) { 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); float chroma = max - min; dest -> l = (max + min)/2; //bi-hexcone model. if (chroma == 0) { // neutral color. dest -> h = 0; // undefined. dest -> s = 0.0f; } else { dest -> s = (dest -> l > 0.5) ? (chroma/(2 - max - min)) : (chroma/(max + min)); //piecewise function.. float hue; if (max == r) { hue = ((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 const char* decspan(const int d) { switch(d) { case 0: return ""; case 1: return ""; case 2: return ""; case 3: return ""; case 4: return ""; case 5: return ""; case 6: return ""; case 7: return ""; case 8: return ""; case 9: return ""; } } static void hexspan(char *buf, int bufsize, const char *str) { // length of ... // "" // where each %d ranges from 0 to 255 // char buf[40]; const char h1[2] = {str[0], '\0'}; const char h2[2] = {str[1], '\0'}; const char h3[2] = {str[2], '\0'}; struct Rgb nrgb; // max value for a color code in darkplaces = 0xF // 0xF * 0xF = 255, max value for rgb nrgb.r = strtol(h1, NULL, 16) * 0xF; nrgb.g = strtol(h2, NULL, 16) * 0xF; nrgb.b = strtol(h3, NULL, 16) * 0xF; struct Hls nhls; rgb2hsl(&nhls, &nrgb); if (nhls.l < MIN_CONTRAST) { nhls.l = MIN_CONTRAST; hsl2rgb(&nrgb, &nhls); } int wrote = snprintf( buf, bufsize, "", nrgb.r, nrgb.g, nrgb.b); // output = buf; } #define TAG_LEN 40 static void colorize_noalloc(char * const str) { char *token = strtok(str, "^"); char c; while (token) { c = token[0]; if (isdigit(c)) { printf( decspan(c - '0') ); if (strlen(token) > 1) { printf("%s", token + 1); } printf(""); } else if ((c == 'x' && strlen(token) > 3) && (isxdigit(token[1]) && isxdigit(token[2]) && isxdigit(token[3]))) { char tag[TAG_LEN]; hexspan(tag, TAG_LEN, token + 1); printf( tag ); //exclude x if (strlen(token) > 4){ printf("%s", token + 4); } printf(""); } else { printf("%s", token); } token = strtok(NULL, "^"); } } static void sanitize(char *user_name) { if (user_name == NULL) { return; } char *pos = user_name; while (pos = strstr(pos, "^^")) { strcpy(pos, (pos + 1)); } } 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); sanitize(copy); colorize_noalloc(copy); fflush(stdout); free(copy); } static char* append_to_str(char *dest, const char *src) { if (dest == NULL || src == NULL) { fprintf(stderr, "append_to_str(): warning - received null ptr" ); return NULL; } size_t new_len = strlen(dest) + strlen(src) + 1; char *new_str = realloc(dest, new_len); if (new_str != NULL) { strcat(new_str, src); } return new_str; } // the most colorful names are the longest // names with 8 colors can go to 400 chars char* colorize_name(char *buf, /*int bufsize,*/ char * const str) { char *token = strtok(str, "^"); char c; // unsigned int i = 0; while (token) { c = token[0]; if (isdigit(c)) { // printf("%i : %s\n", i, buf);; buf = append_to_str(buf, decspan(c - '0') ); if (strlen(token) > 1) { buf = append_to_str(buf, token + 1); } buf = append_to_str(buf, ""); } else if ((c == 'x' && strlen(token) > 3) && (isxdigit(token[1]) && isxdigit(token[2]) && isxdigit(token[3]))) { char tag[TAG_LEN]; hexspan(tag, TAG_LEN, token + 1); //exclude x buf = append_to_str(buf, tag ); if (strlen(token) > 4){ buf = append_to_str(buf, token + 4); } buf = append_to_str(buf, ""); } else { buf = append_to_str(buf, token); } token = strtok(NULL, "^"); // i++; } return buf; } /* test: ./colors ^9[^1S^9]^x469Kom^0ier^7 ./colors ^9[^1S^9]^^x469Kom^0ier^7 */ #ifdef COLORS4PYTHON int main(int argc, const char **argv) { if (argc < 1) { return -1; } char *colored = (char*)calloc(strlen(argv[1]) + 1, sizeof(char)); char *player_name = (char*)calloc(strlen(argv[1]) + 1, sizeof(char)); strcpy(player_name, argv[1]); sanitize(player_name); colored = colorize_name(colored, /*sizeof(colored),*/ player_name); fprintf(stdout, "%s\n", colored); // clean up fflush(stdout); free(colored); free(player_name); return 0; } #endif