00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdio.h>
00018
00019
00020 #include <stdlib.h>
00021 #ifdef WIN32
00022 #include <string.h>
00023 #include <ctype.h>
00024 #include "compat.h"
00025 #endif
00026 #include <string.h>
00027 #include <ctype.h>
00028
00029 #include "arith.h"
00030 #include "color.h"
00031 #include "colorprocs.h"
00032 #include "colortbl.h"
00033 #include "memory.h"
00034
00035 static char* colorscheme;
00036
00037 #ifdef WIN32
00038 extern int strcasecmp(const char *s1, const char *s2);
00039 extern int strncasecmp(const char *s1, const char *s2, unsigned int n);
00040 #endif
00041
00042
00043 static void hsv2rgb(double h, double s, double v,
00044 double *r, double *g, double *b)
00045 {
00046 int i;
00047 double f, p, q, t;
00048
00049 if (s <= 0.0) {
00050 *r = v;
00051 *g = v;
00052 *b = v;
00053 } else {
00054 if (h >= 1.0)
00055 h = 0.0;
00056 h = 6.0 * h;
00057 i = (int) h;
00058 f = h - (double) i;
00059 p = v * (1 - s);
00060 q = v * (1 - (s * f));
00061 t = v * (1 - (s * (1 - f)));
00062 switch (i) {
00063 case 0:
00064 *r = v;
00065 *g = t;
00066 *b = p;
00067 break;
00068 case 1:
00069 *r = q;
00070 *g = v;
00071 *b = p;
00072 break;
00073 case 2:
00074 *r = p;
00075 *g = v;
00076 *b = t;
00077 break;
00078 case 3:
00079 *r = p;
00080 *g = q;
00081 *b = v;
00082 break;
00083 case 4:
00084 *r = t;
00085 *g = p;
00086 *b = v;
00087 break;
00088 case 5:
00089 *r = v;
00090 *g = p;
00091 *b = q;
00092 break;
00093 }
00094 }
00095 }
00096
00097 static void rgb2hsv(double r, double g, double b,
00098 double *h, double *s, double *v)
00099 {
00100
00101 double rgbmin, rgbmax;
00102 double rc, bc, gc;
00103 double ht = 0.0, st = 0.0;
00104
00105 rgbmin = MIN(r, MIN(g, b));
00106 rgbmax = MAX(r, MAX(g, b));
00107
00108 if (rgbmax > 0.0)
00109 st = (rgbmax - rgbmin) / rgbmax;
00110
00111 if (st > 0.0) {
00112 rc = (rgbmax - r) / (rgbmax - rgbmin);
00113 gc = (rgbmax - g) / (rgbmax - rgbmin);
00114 bc = (rgbmax - b) / (rgbmax - rgbmin);
00115 if (r == rgbmax)
00116 ht = bc - gc;
00117 else if (g == rgbmax)
00118 ht = 2 + rc - bc;
00119 else if (b == rgbmax)
00120 ht = 4 + gc - rc;
00121 ht = ht * 60.0;
00122 if (ht < 0.0)
00123 ht += 360.0;
00124 }
00125 *h = ht / 360.0;
00126 *v = rgbmax;
00127 *s = st;
00128 }
00129
00130 static void rgb2cmyk(double r, double g, double b, double *c, double *m,
00131 double *y, double *k)
00132 {
00133 *c = 1.0 - r;
00134 *m = 1.0 - g;
00135 *y = 1.0 - b;
00136 *k = *c < *m ? *c : *m;
00137 *k = *y < *k ? *y : *k;
00138 *c -= *k;
00139 *m -= *k;
00140 *y -= *k;
00141 }
00142
00143 static int colorcmpf(const void *p0, const void *p1)
00144 {
00145 return strcasecmp(((hsvrgbacolor_t *) p0)->name, ((hsvrgbacolor_t *) p1)->name);
00146 }
00147
00148 char *canontoken(char *str)
00149 {
00150 static unsigned char *canon;
00151 static int allocated;
00152 unsigned char c, *p, *q;
00153 int len;
00154
00155 p = (unsigned char *) str;
00156 len = strlen(str);
00157 if (len >= allocated) {
00158 allocated = len + 1 + 10;
00159 canon = grealloc(canon, allocated);
00160 if (!canon)
00161 return NULL;
00162 }
00163 q = (unsigned char *) canon;
00164 while ((c = *p++)) {
00165
00166
00167 if (isupper(c))
00168 c = tolower(c);
00169 *q++ = c;
00170 }
00171 *q = '\0';
00172 return (char*)canon;
00173 }
00174
00175
00176
00177
00178 static char* fullColor (char* prefix, char* str)
00179 {
00180 static char *fulls;
00181 static int allocated;
00182 int len = strlen (prefix) + strlen (str) + 3;
00183
00184 if (len >= allocated) {
00185 allocated = len + 10;
00186 fulls = grealloc(fulls, allocated);
00187 }
00188 sprintf (fulls, "/%s/%s", prefix, str);
00189 return fulls;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 #define DFLT_SCHEME "X11/"
00223 #define DFLT_SCHEME_LEN ((sizeof(DFLT_SCHEME)-1)/sizeof(char))
00224 #define ISNONDFLT(s) ((s) && *(s) && strncasecmp(DFLT_SCHEME, s, DFLT_SCHEME_LEN-1))
00225
00226 static char* resolveColor (char* str)
00227 {
00228 char* s;
00229 char* ss;
00230 char* c2;
00231
00232 if ((*str == 'b') || !strncmp(str+1,"lack",4)) return str;
00233 else if (*str == '/') {
00234 c2 = str+1;
00235 if ((ss = strchr(c2, '/'))) {
00236 if (*c2 == '/') {
00237
00238 if (ISNONDFLT(colorscheme))
00239 s = fullColor (colorscheme, c2+1);
00240 else
00241 s = c2+1;
00242 }
00243 else if (strncasecmp(DFLT_SCHEME, c2, DFLT_SCHEME_LEN)) s = str;
00244 else s = ss + 1;
00245 }
00246 else s = c2;
00247 }
00248 else if (ISNONDFLT(colorscheme)) s = fullColor (colorscheme, str);
00249 else s = str;
00250 return canontoken(s);
00251 }
00252
00253 int colorxlate(char *str, gvcolor_t * color, color_type_t target_type)
00254 {
00255 static hsvrgbacolor_t *last;
00256 static unsigned char *canon;
00257 static int allocated;
00258 unsigned char *p, *q;
00259 hsvrgbacolor_t fake;
00260 unsigned char c;
00261 double H, S, V, A, R, G, B;
00262 double C, M, Y, K;
00263 unsigned int r, g, b, a;
00264 int len, rc;
00265
00266 color->type = target_type;
00267
00268 rc = COLOR_OK;
00269 for (; *str == ' '; str++);
00270 p = (unsigned char *) str;
00271
00272
00273
00274 a = 255;
00275 if ((*p == '#')
00276 && (sscanf((char *) p, "#%2x%2x%2x%2x", &r, &g, &b, &a) >= 3)) {
00277 switch (target_type) {
00278 case HSVA_DOUBLE:
00279 R = (double) r / 255.0;
00280 G = (double) g / 255.0;
00281 B = (double) b / 255.0;
00282 A = (double) a / 255.0;
00283 rgb2hsv(R, G, B, &H, &S, &V);
00284 color->u.HSVA[0] = H;
00285 color->u.HSVA[1] = S;
00286 color->u.HSVA[2] = V;
00287 color->u.HSVA[3] = A;
00288 break;
00289 case RGBA_BYTE:
00290 color->u.rgba[0] = r;
00291 color->u.rgba[1] = g;
00292 color->u.rgba[2] = b;
00293 color->u.rgba[3] = a;
00294 break;
00295 case CMYK_BYTE:
00296 R = (double) r / 255.0;
00297 G = (double) g / 255.0;
00298 B = (double) b / 255.0;
00299 rgb2cmyk(R, G, B, &C, &M, &Y, &K);
00300 color->u.cmyk[0] = (int) C *255;
00301 color->u.cmyk[1] = (int) M *255;
00302 color->u.cmyk[2] = (int) Y *255;
00303 color->u.cmyk[3] = (int) K *255;
00304 break;
00305 case RGBA_WORD:
00306 color->u.rrggbbaa[0] = r * 65535 / 255;
00307 color->u.rrggbbaa[1] = g * 65535 / 255;
00308 color->u.rrggbbaa[2] = b * 65535 / 255;
00309 color->u.rrggbbaa[3] = a * 65535 / 255;
00310 break;
00311 case RGBA_DOUBLE:
00312 color->u.RGBA[0] = (double) r / 255.0;
00313 color->u.RGBA[1] = (double) g / 255.0;
00314 color->u.RGBA[2] = (double) b / 255.0;
00315 color->u.RGBA[3] = (double) a / 255.0;
00316 break;
00317 case COLOR_STRING:
00318 break;
00319 case COLOR_INDEX:
00320 break;
00321 }
00322 return rc;
00323 }
00324
00325
00326 if (((c = *p) == '.') || isdigit(c)) {
00327 len = strlen((char*)p);
00328 if (len >= allocated) {
00329 allocated = len + 1 + 10;
00330 canon = grealloc(canon, allocated);
00331 if (! canon) {
00332 rc = COLOR_MALLOC_FAIL;
00333 return rc;
00334 }
00335 }
00336 q = canon;
00337 while ((c = *p++)) {
00338 if (c == ',')
00339 c = ' ';
00340 *q++ = c;
00341 }
00342 *q = '\0';
00343
00344 if (sscanf((char *) canon, "%lf%lf%lf", &H, &S, &V) == 3) {
00345
00346 H = MAX(MIN(H, 1.0), 0.0);
00347 S = MAX(MIN(S, 1.0), 0.0);
00348 V = MAX(MIN(V, 1.0), 0.0);
00349 switch (target_type) {
00350 case HSVA_DOUBLE:
00351 color->u.HSVA[0] = H;
00352 color->u.HSVA[1] = S;
00353 color->u.HSVA[2] = V;
00354 color->u.HSVA[3] = 1.0;
00355 break;
00356 case RGBA_BYTE:
00357 hsv2rgb(H, S, V, &R, &G, &B);
00358 color->u.rgba[0] = (int) (R * 255);
00359 color->u.rgba[1] = (int) (G * 255);
00360 color->u.rgba[2] = (int) (B * 255);
00361 color->u.rgba[3] = 255;
00362 break;
00363 case CMYK_BYTE:
00364 hsv2rgb(H, S, V, &R, &G, &B);
00365 rgb2cmyk(R, G, B, &C, &M, &Y, &K);
00366 color->u.cmyk[0] = (int) C *255;
00367 color->u.cmyk[1] = (int) M *255;
00368 color->u.cmyk[2] = (int) Y *255;
00369 color->u.cmyk[3] = (int) K *255;
00370 break;
00371 case RGBA_WORD:
00372 hsv2rgb(H, S, V, &R, &G, &B);
00373 color->u.rrggbbaa[0] = (int) (R * 65535);
00374 color->u.rrggbbaa[1] = (int) (G * 65535);
00375 color->u.rrggbbaa[2] = (int) (B * 65535);
00376 color->u.rrggbbaa[3] = 65535;
00377 break;
00378 case RGBA_DOUBLE:
00379 hsv2rgb(H, S, V, &R, &G, &B);
00380 color->u.RGBA[0] = R;
00381 color->u.RGBA[1] = G;
00382 color->u.RGBA[2] = B;
00383 color->u.RGBA[3] = 1.0;
00384 break;
00385 case COLOR_STRING:
00386 break;
00387 case COLOR_INDEX:
00388 break;
00389 }
00390 return rc;
00391 }
00392 }
00393
00394
00395 fake.name = resolveColor(str);
00396 if (!fake.name)
00397 return COLOR_MALLOC_FAIL;
00398 if ((last == NULL)
00399 || (last->name[0] != fake.name[0])
00400 || (strcmp(last->name, fake.name))) {
00401 last = (hsvrgbacolor_t *) bsearch((void *) &fake,
00402 (void *) color_lib,
00403 sizeof(color_lib) /
00404 sizeof(hsvrgbacolor_t), sizeof(fake),
00405 colorcmpf);
00406 }
00407 if (last != NULL) {
00408 switch (target_type) {
00409 case HSVA_DOUBLE:
00410 color->u.HSVA[0] = ((double) last->h) / 255.0;
00411 color->u.HSVA[1] = ((double) last->s) / 255.0;
00412 color->u.HSVA[2] = ((double) last->v) / 255.0;
00413 color->u.HSVA[3] = ((double) last->a) / 255.0;
00414 break;
00415 case RGBA_BYTE:
00416 color->u.rgba[0] = last->r;
00417 color->u.rgba[1] = last->g;
00418 color->u.rgba[2] = last->b;
00419 color->u.rgba[3] = last->a;
00420 break;
00421 case CMYK_BYTE:
00422 R = (last->r) / 255.0;
00423 G = (last->g) / 255.0;
00424 B = (last->b) / 255.0;
00425 rgb2cmyk(R, G, B, &C, &M, &Y, &K);
00426 color->u.cmyk[0] = (int) C * 255;
00427 color->u.cmyk[1] = (int) M * 255;
00428 color->u.cmyk[2] = (int) Y * 255;
00429 color->u.cmyk[3] = (int) K * 255;
00430 break;
00431 case RGBA_WORD:
00432 color->u.rrggbbaa[0] = last->r * 65535 / 255;
00433 color->u.rrggbbaa[1] = last->g * 65535 / 255;
00434 color->u.rrggbbaa[2] = last->b * 65535 / 255;
00435 color->u.rrggbbaa[3] = last->a * 65535 / 255;
00436 break;
00437 case RGBA_DOUBLE:
00438 color->u.RGBA[0] = last->r / 255.0;
00439 color->u.RGBA[1] = last->g / 255.0;
00440 color->u.RGBA[2] = last->b / 255.0;
00441 color->u.RGBA[3] = last->a / 255.0;
00442 break;
00443 case COLOR_STRING:
00444 break;
00445 case COLOR_INDEX:
00446 break;
00447 }
00448 return rc;
00449 }
00450
00451
00452 rc = COLOR_UNKNOWN;
00453 switch (target_type) {
00454 case HSVA_DOUBLE:
00455 color->u.HSVA[0] = color->u.HSVA[1] = color->u.HSVA[2] = 0.0;
00456 color->u.HSVA[3] = 1.0;
00457 break;
00458 case RGBA_BYTE:
00459 color->u.rgba[0] = color->u.rgba[1] = color->u.rgba[2] = 0;
00460 color->u.rgba[3] = 255;
00461 break;
00462 case CMYK_BYTE:
00463 color->u.cmyk[0] =
00464 color->u.cmyk[1] = color->u.cmyk[2] = color->u.cmyk[3] = 0;
00465 break;
00466 case RGBA_WORD:
00467 color->u.rrggbbaa[0] = color->u.rrggbbaa[1] = color->u.rrggbbaa[2] = 0;
00468 color->u.rrggbbaa[3] = 65535;
00469 break;
00470 case RGBA_DOUBLE:
00471 color->u.RGBA[0] = color->u.RGBA[1] = color->u.RGBA[2] = 0.0;
00472 color->u.RGBA[3] = 1.0;
00473 break;
00474 case COLOR_STRING:
00475 break;
00476 case COLOR_INDEX:
00477 break;
00478 }
00479 return rc;
00480 }
00481
00482
00483
00484
00485 void setColorScheme (char* s)
00486 {
00487 colorscheme = s;
00488 }
00489
00490
00491