Icons are changed
[gnuplot] / src / getcolor.c
1 #ifndef lint
2 static char *RCSid() { return RCSid("$Id: getcolor.c,v 1.24 2006/02/21 09:14:49 mikulik Exp $"); }
3 #endif
4
5 /* GNUPLOT - getcolor.c */
6
7 /*[
8  *
9  * Petr Mikulik, December 1998 -- June 1999
10  * Copyright: open source as much as possible
11  *
12 ]*/
13
14 #include "syscfg.h"
15
16 #include "stdfn.h"
17
18 #include "util.h"
19 #include "getcolor.h"
20
21 /*
22  * This file implements all the gray to color transforms except one:
23  * calculate_color_from_formulae() which can be found in color.c.
24  * calculate_color_from_formulae() belongs logicaly into this (getcolor.c)
25  * file, but it can't be here due to linkage problems:  gnuplot_x11
26  * needs a lot of code from getcolor.c but does not contain any function
27  * evaluation code [and does not call calculate_color_from_formulae()].
28  * This file is compiled twice:  Once as part of gnuplot and the second
29  * time with -DGPLT_X11_MODE resulting in getcolor_x11.o which is linked
30  * into gnuplot_x11.  With GPLT_X11_MODE defined this file does not
31  * contain code for calculating colors from gray by user defined functions.
32  */
33 #ifndef GPLT_X11_MODE
34 static int calculate_color_from_formulae __PROTO((double, rgb_color *));
35 #endif
36
37 static char *dbl_to_str __PROTO((double val, char *dest));
38 static double str_to_dbl __PROTO((char *s));
39 static void color_components_from_gray __PROTO((double gray, rgb_color *color));
40 static char *color_to_str __PROTO((rgb_color col, char *buf));
41 static void str_to_color __PROTO((char *buf, rgb_color *col));
42 static int interpolate_color_from_gray __PROTO((double, rgb_color *));
43 static double get_max_dev __PROTO((rgb_color *colors, int j, double limit));
44 static int is_extremum __PROTO((rgb_color left,rgb_color mid,rgb_color right));
45 static void CMY_2_RGB __PROTO((rgb_color *color));
46 static void CIEXYZ_2_RGB __PROTO((rgb_color *color));
47 static void YIQ_2_RGB __PROTO((rgb_color *color));
48 static void HSV_2_RGB __PROTO((rgb_color *color));
49
50
51 /* check if two palettes p1 and p2 differ significantly */
52 int
53 palettes_differ(t_sm_palette *p1, t_sm_palette *p2)
54 {
55     if (p1->colorMode != p2->colorMode)
56         return 1;
57     if (p1->positive != p2->positive)
58         return 1;
59     if (p1->cmodel != p2->cmodel)
60         return 1;
61     if (p1->use_maxcolors != p2->use_maxcolors)
62         return 1;
63
64     switch(p1->colorMode) {
65     case SMPAL_COLOR_MODE_NONE:
66         return 0;  /* ?? */
67     case SMPAL_COLOR_MODE_GRAY:
68         if (fabs(p1->gamma - p2->gamma) > 1e-3)
69             return 1;
70         break;
71     case SMPAL_COLOR_MODE_RGB:
72         if (p1->colorFormulae != p2->colorFormulae)
73             return 1;
74         if (p1->formulaR != p2->formulaR)
75             return 1;
76         if (p1->formulaG != p2->formulaG)
77             return 1;
78         if (p1->formulaB != p2->formulaB)
79             return 1;
80         /* if (p1->ps_allcF != p2->ps_allcF)
81            return 1; */
82         break;
83     case SMPAL_COLOR_MODE_FUNCTIONS:
84         /* coarse check based on typed fnct definitions */
85         if (strcmp(p1->Afunc.definition, p2->Afunc.definition))
86             return 1;
87         if (strcmp(p1->Bfunc.definition, p2->Bfunc.definition))
88             return 1;
89         if (strcmp(p1->Cfunc.definition, p2->Cfunc.definition))
90             return 1;
91         break;
92     case SMPAL_COLOR_MODE_GRADIENT: {
93         int i=0;
94
95         if (p1->gradient_num != p2->gradient_num)
96             return 1;
97         for(i=0; i<p1->gradient_num; ++i) {
98             if (p1->gradient[i].pos != p2->gradient[i].pos)
99                 return 1;
100             if (p1->gradient[i].col.r != p2->gradient[i].col.r)
101                 return 1;
102             if (p1->gradient[i].col.g != p2->gradient[i].col.g)
103                 return 1;
104             if (p1->gradient[i].col.b != p2->gradient[i].col.b)
105                 return 1;
106         }
107         break;
108     } /* case GRADIENT */
109     } /* switch() */
110
111     return 0;  /* no real difference found */
112 }
113
114
115 /* Store double value from [0,1] in 2 characters. Resolution is 6.1e-5.
116  * No '\n' are generated. */
117 static char *dbl_to_str(double val, char *dest)
118 {
119     unsigned int ival = (unsigned int) (((1 << 14) - 1) * val);
120
121     dest[0] = (ival >> 7) + 33;
122     dest[1] = (ival & 127) + 33;
123     return dest;
124 }
125
126 /* Reverse of dbl_to_str(): map 2 characters to double in [0,1] */
127 static double
128 str_to_dbl(char *s)
129 {
130     unsigned int ival =
131         (((unsigned int) (s[0] - 33) & 127) << 7)
132         | (unsigned int) ((s[1] - 33) & 127);
133     double val = ((double) ival) / ((1 << 14) - 1);
134
135     return val;
136 }
137
138
139 /* Save rgb_color to 6 characters which are no '\n'. */
140 static char
141 *color_to_str(rgb_color col, char *buf)
142 {
143     dbl_to_str(col.r, buf + 0);
144     dbl_to_str(col.g, buf + 2);
145     dbl_to_str(col.b, buf + 4);
146     buf[6] = 0;
147     return buf;
148 }
149
150 /* Restore rgb_color from 6 characters  */
151 static void
152 str_to_color(char *buf, rgb_color *col)
153 {
154     col->r = str_to_dbl(buf + 0);
155     col->g = str_to_dbl(buf + 2);
156     col->b = str_to_dbl(buf + 4);
157 }
158
159
160 /* Store a gradient entry in 8 characters which do not contain '\n' */
161 char *
162 gradient_entry_to_str(gradient_struct *gs)
163 {
164     static char buf[20];
165     dbl_to_str(gs->pos, buf);
166     color_to_str(gs->col, buf + 2);
167     return buf;
168 }
169
170 /* Gestore gradient entry from string */
171 void
172 str_to_gradient_entry(char *s, gradient_struct *gs)
173 {
174     gs->pos = str_to_dbl(s);
175     str_to_color(s + 2, & (gs->col));
176 }
177
178
179 #define CONSTRAIN(x) ((x) < 0 ? 0 : ((x) > 1 ? 1 : (x)))
180
181
182 /*  This one takes the gradient defined in sm_palette.gradient and
183  *  returns an interpolated color for the given gray value.  It
184  *  does not matter wether RGB or HSV or whatever values are stored
185  *  in sm_palette.gradient[i].col, they will simply be interpolated.
186  *  Return 0 on sucess, 1 if gray outside the range covered by the
187  *  gradient.  No gamma correction is done.  The user can implement
188  *  gamma correction specifying more points.
189  *  sm_palette.gradient[] should be sorted acording to .pos.
190  *  Returns 1 on failure and fills color with "nearest" color.
191  */
192 static int
193 interpolate_color_from_gray(double gray, rgb_color *color)
194 {
195     int idx, maxidx;
196     rgb_color *col1;
197     rgb_color *col2;
198
199     if (gray < 0)  {
200         color->r = sm_palette.gradient[0].col.r;
201         color->g = sm_palette.gradient[0].col.g;
202         color->b = sm_palette.gradient[0].col.b;
203         return 1;
204     }
205
206     maxidx = sm_palette.gradient_num;
207     if (gray > 1) {
208         color->r = sm_palette.gradient[maxidx-1].col.r;
209         color->g = sm_palette.gradient[maxidx-1].col.g;
210         color->b = sm_palette.gradient[maxidx-1].col.b;
211         return 1;
212     }
213
214     /* find index by bisecting */
215     idx = 0;
216     if (maxidx > 1) {
217         int topidx = maxidx - 1;
218         /* treat idx as though it is bottom index */
219         while (idx != topidx) {
220             int tmpidx = (idx + topidx) / 2;
221             if (sm_palette.gradient[tmpidx].pos < gray)
222                 idx = tmpidx + 1;  /* round up */
223             else
224                 topidx = tmpidx;
225         }
226     }
227
228     col2 = & sm_palette.gradient[idx].col;
229     if (gray == sm_palette.gradient[idx].pos) {
230         /* exact hit */
231         color->r = col2->r;
232         color->g = col2->g;
233         color->b = col2->b;
234     } else {
235         /* linear interpolation of two colors */
236         double dx = sm_palette.gradient[idx].pos
237             - sm_palette.gradient[idx - 1].pos;
238         double f = (gray - sm_palette.gradient[idx-1].pos) / dx;
239         
240         col1 = & sm_palette.gradient[idx - 1].col;
241         color->r = (col1->r + f * (col2->r - col1->r));
242         color->g = (col1->g + f * (col2->g - col1->g));
243         color->b = (col1->b + f * (col2->b - col1->b));
244     }
245     return 0;
246 }
247
248
249 #ifndef GPLT_X11_MODE
250 /*  Fills color with the values calculated from sm_palette.[ABC]func
251  *  The color values are clipped to [0,1] without further notice.
252  *  Returns 0 or does an int_error() when function evaluatin failed.
253  *  The result is not in RGB color space jet.
254  */
255 static int
256 calculate_color_from_formulae(double gray, rgb_color *color)
257 {
258     struct value v;
259     double a, b, c;
260
261 #define NO_CARET (-1)
262
263     (void) Gcomplex(&sm_palette.Afunc.dummy_values[0], gray, 0.0);
264     evaluate_at(sm_palette.Afunc.at, &v);
265     if (undefined)
266         int_error(NO_CARET,
267                   "Undefined value first color during function evaluation");
268     a = real(&v);
269     a = CONSTRAIN(a);
270
271     (void) Gcomplex(&sm_palette.Bfunc.dummy_values[0], gray, 0.0);
272     evaluate_at(sm_palette.Bfunc.at, &v);
273     if (undefined)
274         int_error(NO_CARET,
275                   "Undefined value second color during function evaluation");
276     b = real(&v);
277     b = CONSTRAIN(b);
278
279     (void) Gcomplex(&sm_palette.Cfunc.dummy_values[0], gray, 0.0);
280     evaluate_at(sm_palette.Cfunc.at, &v);
281     if (undefined)
282         int_error(NO_CARET,
283                   "Undefined value third color during function evaluation");
284     c = real(&v);
285     c = CONSTRAIN(c);
286
287     color->r = a;
288     color->g = b;
289     color->b = c;
290 #undef NO_CARET
291     return 0;
292 }
293 #endif  /* !GPLT_X11_MODE */
294
295
296 /* Map gray in [0,1] to color components according to colorMode */
297 static void
298 color_components_from_gray(double gray, rgb_color *color)
299 {
300     if (gray < 0)
301         gray = 0;
302     else if (gray > 1.0)
303         gray = 1.0;
304
305     switch(sm_palette.colorMode) {
306     case SMPAL_COLOR_MODE_GRAY:
307         color->r = color->g = color->b = pow(gray, 1.0/sm_palette.gamma);
308         return;  /* all done, no color space transformation needed  */
309     case SMPAL_COLOR_MODE_RGB:
310         color->r = GetColorValueFromFormula(sm_palette.formulaR, gray);
311         color->g = GetColorValueFromFormula(sm_palette.formulaG, gray);
312         color->b = GetColorValueFromFormula(sm_palette.formulaB, gray);
313         break;
314     case SMPAL_COLOR_MODE_GRADIENT:
315         interpolate_color_from_gray(gray, color);
316         break;
317 #ifndef GPLT_X11_MODE
318     case SMPAL_COLOR_MODE_FUNCTIONS:
319         calculate_color_from_formulae(gray, color);
320         break;
321 #endif /* !GPLT_X11_MODE */
322     default:
323         fprintf(stderr, "%s:%d ooops: Unknown colorMode '%c'.\n",
324                 __FILE__, __LINE__, (char)(sm_palette.colorMode));
325     }
326 }
327
328 /*
329  *  Map a gray value in [0,1] to the corresponding RGB values in [0,1],
330  *  according to the current colorMode and color space.
331  *
332  *  Note -- November 2003: this routine has been renamed from color_from_gray()
333  *  to rgb1_from_gray() in order to more clearly distinguish structures
334  *  rgb_color and rgb255_color.
335  */
336 void
337 rgb1_from_gray(double gray, rgb_color *color)
338 {
339     /* get the color */
340     color_components_from_gray(gray, color);
341     if (sm_palette.colorMode == SMPAL_COLOR_MODE_GRAY)
342         return;
343
344     /* transform to RGB if necessary */
345     switch(sm_palette.cmodel) {
346     case C_MODEL_RGB:
347         break;
348     case C_MODEL_HSV:
349         HSV_2_RGB(color);
350         break;
351     case C_MODEL_CMY:
352         CMY_2_RGB(color);
353         break;
354     case C_MODEL_YIQ:
355         YIQ_2_RGB(color);
356         break;
357     case C_MODEL_XYZ:
358         CIEXYZ_2_RGB(color);
359         break;
360     default:
361         fprintf(stderr, "%s:%d ooops: Unknown color model '%c'\n",
362                 __FILE__, __LINE__, (char)(sm_palette.cmodel));
363     }
364 }
365
366
367 /*
368  *  Convenience function to map R, G and B float values [0,1] to uchars [0,255].
369  */
370 void
371 rgb255_from_rgb1(rgb_color rgb1, rgb255_color *rgb255)
372 {
373     rgb255->r = (unsigned char)(255 * rgb1.r + 0.5);
374     rgb255->g = (unsigned char)(255 * rgb1.g + 0.5);
375     rgb255->b = (unsigned char)(255 * rgb1.b + 0.5);
376 }
377
378
379 /*
380  *  Convenience function to map gray values to R, G and B values in [0,1],
381  *  taking care of palette maxcolors (i.e., discrete nb of colors).
382  */
383 void
384 rgb1maxcolors_from_gray(double gray, rgb_color *color)
385 {
386     if (sm_palette.use_maxcolors != 0)
387         gray = floor(gray * sm_palette.use_maxcolors)
388             / (sm_palette.use_maxcolors-1);
389     rgb1_from_gray(gray, color);
390 }
391
392
393 /*
394  *  Convenience function to map gray values to R, G and B values in [0,255],
395  *  taking care of palette maxcolors (i.e., discrete nb of colors).
396  */
397 void
398 rgb255maxcolors_from_gray(double gray, rgb255_color *rgb255)
399 {
400     rgb_color rgb1;
401     rgb1maxcolors_from_gray(gray, &rgb1);
402     rgb255_from_rgb1(rgb1, rgb255);
403 }
404
405
406 /*
407  *  Used by approximate_palette
408  */
409 static double
410 get_max_dev(rgb_color *colors, int j, double limit)
411 {
412     double max_dev = 0.0;
413     double rdev, gdev, bdev;
414     double r=colors[0].r, g=colors[0].g, b=colors[0].b;
415     int i;
416     double sr = (colors[j].r - r) / j;
417     double sg = (colors[j].g - g) / j;
418     double sb = (colors[j].b - b) / j;
419
420     for(i=1; i<j; ++i) {
421         double dx = i;
422
423         rdev = fabs(sr*dx + r - colors[i].r);
424         gdev = fabs(sg*dx + g - colors[i].g);
425         bdev = fabs(sb*dx + b - colors[i].b);
426         if(rdev > max_dev)
427             max_dev = rdev;
428         if(gdev > max_dev)
429             max_dev = gdev;
430         if(bdev > max_dev)
431             max_dev = bdev;
432         if(max_dev >= limit)
433             break;
434     }
435     return max_dev;
436 }
437
438
439 /*
440  *  Used by approximate_palette:  true if one color component in mid
441  *  is higher (or lower) than both left and right, flase other wise
442  */
443 static int
444 is_extremum(rgb_color left, rgb_color mid, rgb_color right)
445 {
446     /* mid is maximum */
447     if(left.r < mid.r && mid.r > right.r)
448         return 1;
449     if(left.g < mid.g && mid.g > right.g)
450         return 1;
451     if(left.b < mid.b && mid.b > right.b)
452         return 1;
453
454     /* mid is minimum */
455     if(left.r > mid.r && mid.r < right.r)
456         return 1;
457     if(left.g > mid.g && mid.g < right.g)
458         return 1;
459     if(left.b > mid.b && mid.b < right.b)
460         return 1;
461
462     return 0;
463 }
464
465
466 #define GROW_GRADIENT(n) do {                                           \
467     if(cnt == gradient_size) {                                          \
468         gradient_size += (n);                                           \
469         gradient = (gradient_struct*)                                   \
470             realloc(gradient, gradient_size * sizeof(gradient_struct)); \
471     }                                                                   \
472 } while(0)
473
474
475 /*
476  *  This function takes a palette and constructs a gradient which can
477  *  be used to approximate the palette by linear interpolation.
478  *  The palette is sampled at samples+1 points equally spaced in [0,1].
479  *  From this huge gradient a much smaler one is constructed by selecting
480  *  just those sampling points which still do approximate the full sampled
481  *  one well enough.  allowed_deviation determines the maximum deviation
482  *  of all color components which is still acceptable for the reduced
483  *  gradient.  Use a sufficiently large number of samples (500 to 5000).
484  *  Please free() the returned gradient after use.  samples, allowed_deviation
485  *  and max_skip may be <=0 and useful defaults will be used.
486  *  Most probably it's useless to approximate a gradient- or rgbformulae-
487  *  palette.  Use it to build gradients from function palettes.
488  */
489 gradient_struct *
490 approximate_palette(t_sm_palette *palette, int samples,
491                     double allowed_deviation,
492                     int *gradient_num)
493 {
494     int i=0, j=0;
495     double gray=0;
496     int gradient_size=50;
497     gradient_struct *gradient;
498     int colors_size=100;
499     rgb_color *colors;
500     int cnt=0;
501     rgb_color color;
502     double max_dev=0.0;
503     /* int maximum_j=0, extrema=0; */
504
505     /* useful defaults */
506     if (samples <= 0)
507         samples = 2000;
508     if (allowed_deviation <= 0)
509         allowed_deviation = 0.003;
510
511     gradient = (gradient_struct*)
512         malloc(gradient_size * sizeof(gradient_struct));
513     colors = (rgb_color*) malloc(colors_size * sizeof(rgb_color));
514     assert(gradient && colors);
515
516     /* start (gray=0.0) is needed */
517     cnt = 0;
518     color_components_from_gray(0.0, colors + 0);
519     gradient[0].pos = 0.0;
520     gradient[0].col = colors[0];
521     ++cnt;
522     color_components_from_gray(1.0 / samples, colors + 1);
523
524     for(i = 0; i < samples; ++i) {
525         for(j = 2; i + j <= samples; ++j) {
526             gray = ((double) (i + j)) / samples;
527             if (j == colors_size) {
528                 colors_size += 50;
529                 colors = (rgb_color *)
530                     realloc(colors, colors_size*sizeof(gradient_struct));
531             }
532             color_components_from_gray(gray, colors + j);
533
534             /* test for extremum */
535             if(is_extremum(colors[j - 2], colors[j - 1], colors[j])) {
536                 /* fprintf(stderr,"Extremum at %g\n", gray); */
537                 /* ++extrema; */
538                 break;
539             }
540
541             /* to big deviation */
542             max_dev = get_max_dev(colors, j, allowed_deviation);
543             if(max_dev > allowed_deviation) {
544                 /* fprintf(stderr,"Control Point at %.3g\n",gray); */
545                 break;
546             }
547         }
548         GROW_GRADIENT(25);
549
550         gradient[cnt].pos = gray;
551         gradient[cnt].col = colors[j - 1];
552         ++cnt;
553
554         /* if(j-1 > maximum_j) maximum_j = j-1; */
555
556         colors[0] = colors[j - 1];
557         colors[1] = colors[j];
558         i += j - 1;
559     }
560
561     color_components_from_gray(1.0, &color);
562     GROW_GRADIENT(1);
563     gradient[cnt].pos = 1.0;
564     gradient[cnt].col = color;
565     ++cnt;
566
567     /***********
568     fprintf(stderr,
569              "PS interpolation table: %d samples, allowed deviation %.2f%%:\n",
570              samples, 100*allowed_deviation);
571
572     fprintf(stderr, "  --> new size %d, %d extrema, max skip %d\n",
573              cnt, extrema, maximum_j);
574     ************/
575     free(colors);
576     *gradient_num = cnt;
577     return gradient;  /* don't forget to free() it once you'r done with it */
578 }
579
580 #undef GROW_GRADIENT
581
582
583 /*
584  *  Original fixed color transformations
585  */
586 double
587 GetColorValueFromFormula(int formula, double x)
588 {
589     /* the input gray x is supposed to be in interval [0,1] */
590     if (formula < 0) {          /* negate the value for negative formula */
591         x = 1 - x;
592         formula = -formula;
593     }
594     switch (formula) {
595     case 0:
596         return 0;
597     case 1:
598         return 0.5;
599     case 2:
600         return 1;
601     case 3:                     /* x = x */
602         break;
603     case 4:
604         x = x * x;
605         break;
606     case 5:
607         x = x * x * x;
608         break;
609     case 6:
610         x = x * x * x * x;
611         break;
612     case 7:
613         x = sqrt(x);
614         break;
615     case 8:
616         x = sqrt(sqrt(x));
617         break;
618     case 9:
619         x = sin(90 * x * DEG2RAD);
620         break;
621     case 10:
622         x = cos(90 * x * DEG2RAD);
623         break;
624     case 11:
625         x = fabs(x - 0.5);
626         break;
627     case 12:
628         x = (2 * x - 1) * (2.0 * x - 1);
629         break;
630     case 13:
631         x = sin(180 * x * DEG2RAD);
632         break;
633     case 14:
634         x = fabs(cos(180 * x * DEG2RAD));
635         break;
636     case 15:
637         x = sin(360 * x * DEG2RAD);
638         break;
639     case 16:
640         x = cos(360 * x * DEG2RAD);
641         break;
642     case 17:
643         x = fabs(sin(360 * x * DEG2RAD));
644         break;
645     case 18:
646         x = fabs(cos(360 * x * DEG2RAD));
647         break;
648     case 19:
649         x = fabs(sin(720 * x * DEG2RAD));
650         break;
651     case 20:
652         x = fabs(cos(720 * x * DEG2RAD));
653         break;
654     case 21:
655         x = 3 * x;
656         break;
657     case 22:
658         x = 3 * x - 1;
659         break;
660     case 23:
661         x = 3 * x - 2;
662         break;
663     case 24:
664         x = fabs(3 * x - 1);
665         break;
666     case 25:
667         x = fabs(3 * x - 2);
668         break;
669     case 26:
670         x = (1.5 * x - 0.5);
671         break;
672     case 27:
673         x = (1.5 * x - 1);
674         break;
675     case 28:
676         x = fabs(1.5 * x - 0.5);
677         break;
678     case 29:
679         x = fabs(1.5 * x - 1);
680         break;
681     case 30:
682         if (x <= 0.25)
683             return 0;
684         if (x >= 0.57)
685             return 1;
686         x = x / 0.32 - 0.78125;
687         break;
688     case 31:
689         if (x <= 0.42)
690             return 0;
691         if (x >= 0.92)
692             return 1;
693         x = 2 * x - 0.84;
694         break;
695     case 32:
696         if (x <= 0.42)
697             x *= 4;
698         else
699             x = (x <= 0.92) ? -2 * x + 1.84 : x / 0.08 - 11.5;
700         break;
701     case 33:
702         x = fabs(2 * x - 0.5);
703         break;
704     case 34:
705         x = 2 * x;
706         break;
707     case 35:
708         x = 2 * x - 0.5;
709         break;
710     case 36:
711         x = 2 * x - 1;
712         break;
713         /*
714            IMPORTANT: if any new formula is added here, then:
715            (1) its postscript counterpart must be added into term/post.trm,
716            search for "ps_math_color_formulae[]"
717            (2) number of colours must be incremented in color.c: variable
718            sm_palette, first item---search for "t_sm_palette sm_palette = "
719          */
720     default:
721         fprintf(stderr, "Fatal: undefined color formula (can be 0--%i)\n", sm_palette.colorFormulae - 1);
722         exit(1);
723     }
724     if (x <= 0)
725         return 0;
726     if (x >= 1)
727         return 1;
728     return x;
729 }
730
731
732 /* Implementation of pm3dGetColorValue() in the postscript way.
733    Notice that the description, i.e. the part after %, is important
734    since it is used in `show pm3d' for displaying the analytical formulae.
735    The postscript formulae will be expanded into lines like:
736         "/cF0 {pop 0} bind def\t% 0",
737         "/cF4 {dup mul} bind def\t% x^2",
738 */
739
740 const char *ps_math_color_formulae[] = {
741     /* /cF0  */ "pop 0", "0",
742     /* /cF1  */ "pop 0.5", "0.5",
743     /* /cF2  */ "pop 1", "1",
744     /* /cF3  */ " ", "x",
745     /* /cF4  */ "dup mul", "x^2",
746     /* /cF5  */ "dup dup mul mul", "x^3",
747     /* /cF6  */ "dup mul dup mul", "x^4",
748     /* /cF7  */ "sqrt", "sqrt(x)",
749     /* /cF8  */ "sqrt sqrt", "sqrt(sqrt(x))",
750     /* /cF9  */ "90 mul sin", "sin(90x)",
751     /* /cF10 */ "90 mul cos", "cos(90x)",
752     /* /cF11 */ "0.5 sub abs", "|x-0.5|",
753     /* /cF12 */ "2 mul 1 sub dup mul", "(2x-1)^2",
754     /* /cF13 */ "180 mul sin", "sin(180x)",
755     /* /cF14 */ "180 mul cos abs", "|cos(180x)|",
756     /* /cF15 */ "360 mul sin", "sin(360x)",
757     /* /cF16 */ "360 mul cos", "cos(360x)",
758     /* /cF17 */ "360 mul sin abs", "|sin(360x)|",
759     /* /cF18 */ "360 mul cos abs", "|cos(360x)|",
760     /* /cF19 */ "720 mul sin abs", "|sin(720x)|",
761     /* /cF20 */ "720 mul cos abs", "|cos(720x)|",
762     /* /cF21 */ "3 mul", "3x",
763     /* /cF22 */ "3 mul 1 sub", "3x-1",
764     /* /cF23 */ "3 mul 2 sub", "3x-2",
765     /* /cF24 */ "3 mul 1 sub abs", "|3x-1|",
766     /* /cF25 */ "3 mul 2 sub abs", "|3x-2|",
767     /* /cF26 */ "1.5 mul .5 sub", "(3x-1)/2",
768     /* /cF27 */ "1.5 mul 1 sub", "(3x-2)/2",
769     /* /cF28 */ "1.5 mul .5 sub abs", "|(3x-1)/2|",
770     /* /cF29 */ "1.5 mul 1 sub abs", "|(3x-2)/2|",
771     /* /cF30 */ "0.32 div 0.78125 sub", "x/0.32-0.78125",
772     /* /cF31 */ "2 mul 0.84 sub", "2*x-0.84",
773     /* /cF32 */ "dup 0.42 le {4 mul} {dup 0.92 le {-2 mul 1.84 add} {0.08 div 11.5 sub} ifelse} ifelse",
774     "4x;1;-2x+1.84;x/0.08-11.5",
775     /* /cF33 */ "2 mul 0.5 sub abs", "|2*x - 0.5|",
776     /* /cF34 */ "2 mul", "2*x",
777     /* /cF35 */ "2 mul 0.5 sub", "2*x - 0.5",
778     /* /cF36 */ "2 mul 1 sub", "2*x - 1",
779     "", ""};
780
781
782 /*
783  *  Color Conversion Algorithms
784  *  taken from http://www.cs.rit.edu/~ncs/color/t_convert.html
785  *  each color model should provide a conversion to RGB.
786  *  RGB values are clipped to [0,1] as some colors in some
787  *  models have no RGB value.
788  */
789 static void
790 CMY_2_RGB(rgb_color *col)
791 {
792     double c,m,y;
793     c = col->r;
794     m = col->g;
795     y = col->b;
796     col->r = CONSTRAIN(1.0 - c);
797     col->g = CONSTRAIN(1.0 - m);
798     col->b = CONSTRAIN(1.0 - y);
799 }
800
801 static void
802 CIEXYZ_2_RGB(rgb_color *col)
803 {
804     double x,y,z;
805     
806     x = col->r;
807     y = col->g;
808     z = col->b;
809     col->r = CONSTRAIN( 1.9100 * x - 0.5338 * y - 0.2891 * z);
810     col->g = CONSTRAIN(-0.9844 * x + 1.9990 * y - 0.0279 * z);
811     col->b = CONSTRAIN( 0.0585 * x - 0.1187 * y - 0.9017 * z);
812 }
813
814 static void
815 YIQ_2_RGB(rgb_color *col)
816 {
817     double y,i,q;
818     
819     y = col->r;
820     i = col->g;
821     q = col->b;
822     col->r = CONSTRAIN(y - 0.956 * i + 0.621 * q);
823     col->g = CONSTRAIN(y - 0.272 * i - 0.647 * q);
824     col->b = CONSTRAIN(y - 1.105 * i - 1.702 * q);
825 }
826
827 static void
828 HSV_2_RGB(rgb_color *col)
829 {
830     double h,s,v, f,p,q,t;
831     int i;
832
833     h = col->r;
834     s = col->g;
835     v = col->b;
836     if (s == 0) { /* achromatic (gray) */
837         col->r = col->g = col->b = v;
838         return;
839     }
840
841     h *= 6.;  /* h range in gnuplot is [0,1] and not the usual [0,360] */
842     i = floor(h);
843     f = h - i;
844     p = v * (1.0 - s);
845     q = v * (1.0 - s*f);
846     t = v * (1.0 - s*(1.0-f));
847     switch(i % 6) {
848     case 0:
849         col->r = v;
850         col->g = t;
851         col->b = p;
852         break;
853     case 1:
854         col->r = q;
855         col->g = v;
856         col->b = p;
857         break;
858     case 2:
859         col->r = p;
860         col->g = v;
861         col->b = t;
862         break;
863     case 3:
864         col->r = p;
865         col->g = q;
866         col->b = v;
867         break;
868     case 4:
869         col->r = t;
870         col->g = p;
871         col->b = v;
872         break;
873     default:
874         col->r = v;
875         col->g = p;
876         col->b = q;
877         break;
878     }
879 }
880 #undef CONSTRAIN
881
882
883 /* eof getcolor.c */