1 
2 /*
3 A* -------------------------------------------------------------------
4 B* This file contains source code for the PyMOL computer program
5 C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
6 D* -------------------------------------------------------------------
7 E* It is unlawful to modify or remove this copyright notice.
8 F* -------------------------------------------------------------------
9 G* Please see the accompanying LICENSE file for further information.
10 H* -------------------------------------------------------------------
11 I* Additional authors of this source file include:
12 -*
13 -*
14 -*
15 Z* -------------------------------------------------------------------
16 */
17 #include"os_python.h"
18 #include"os_predef.h"
19 #include"os_std.h"
20 
21 #include"Base.h"
22 #include"OOMac.h"
23 #include"MemoryDebug.h"
24 #include"Ortho.h"
25 #include"Word.h"
26 
27 #include"Color.h"
28 #include"PConv.h"
29 #include"ObjectGadgetRamp.h"
30 #include"Util.h"
31 #include"Executive.h"
32 #include"MyPNG.h"
33 #include"Scene.h"
34 #include"OVContext.h"
35 #include"OVreturns.h"
36 
37 static int AutoColor[] = {
38   26,                           /* carbon */
39   5,                            /* cyan */
40   154,                          /* lightmagenta */
41   6,                            /* yellow */
42   9,                            /* salmon */
43   29,                           /* hydrogen */
44   11,                           /* slate */
45   13,                           /* orange */
46   10,                           /* lime */
47   5262,                         /* deepteal */
48   12,                           /* hotpink */
49   36,                           /* yelloworange */
50   5271,                         /* violetpurple */
51   124,                          /* grey70 */
52   17,                           /* marine */
53   18,                           /* olive */
54   5270,                         /* smudge */
55   20,                           /* teal */
56   5272,                         /* dirtyviolet */
57   52,                           /* wheat */
58   5258,                         /* deepsalmon */
59   5274,                         /* lightpink */
60   5257,                         /* aquamarine */
61   5256,                         /* paleyellow */
62   15,                           /* limegreen */
63   5277,                         /* skyblue */
64   5279,                         /* warmpink */
65   5276,                         /* limon */
66   53,                           /* violet */
67   5278,                         /* bluewhite */
68   5275,                         /* greencyan */
69   5269,                         /* sand */
70   22,                           /* forest */
71   5266,                         /* lightteal */
72   5280,                         /* darksalmon */
73   5267,                         /* splitpea */
74   5268,                         /* raspberry */
75   104,                          /* grey50 */
76   23,                           /* deepblue */
77   51,                           /* brown */
78 };
79 
80 static int nAutoColor = 40;
81 static void lookup_color(CColor * I, const float *in, float *out, int big_endian);
82 
ColorGetBkrdContColor(PyMOLGlobals * G,float * rgb,int invert_flag)83 void ColorGetBkrdContColor(PyMOLGlobals * G, float *rgb, int invert_flag)
84 {
85   const float *bkrd = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting_bg_rgb));
86 
87   if(!invert_flag) {
88     if((bkrd[0] + bkrd[1] + bkrd[2]) > 0.5F) {
89       rgb[0] = 1.0F;
90       rgb[1] = 1.0F;
91       rgb[2] = 1.0F;
92     } else {
93       rgb[0] = 0.0F;
94       rgb[1] = 0.0F;
95       rgb[2] = 0.0F;
96     }
97   }
98 
99   {
100     int a;
101     for(a = 0; a < 3; a++)
102       if(fabs(bkrd[a] - rgb[a]) < 0.5F) {
103         rgb[a] = 1.0F - rgb[a];
104         if(fabs(bkrd[a] - rgb[a]) < 0.5F) {
105           if(bkrd[a] > 0.5F)
106             rgb[a] = 0.0F;
107           else
108             rgb[a] = 1.0F;
109         }
110       }
111   }
112 }
113 
ColorGet32BitWord(PyMOLGlobals * G,const float * rgba)114 unsigned int ColorGet32BitWord(PyMOLGlobals * G, const float *rgba)
115 {
116   CColor *I = G->Color;
117   unsigned int rc, gc, bc, ac;
118   unsigned int result;
119 
120   rc = (int) (255 * rgba[0] + 0.49999F);
121   gc = (int) (255 * rgba[1] + 0.49999F);
122   bc = (int) (255 * rgba[2] + 0.49999F);
123   ac = (int) (255 * rgba[3] + 0.49999F);
124 
125   if(rc > 255)
126     rc = 255;
127   if(bc > 255)
128     bc = 255;
129   if(gc > 255)
130     gc = 255;
131   if(ac > 255)
132     ac = 255;
133 
134   if(I->BigEndian) {
135     result = (rc << 24) | (gc << 16) | (bc << 8) | ac;
136   } else {
137     result = (ac << 24) | (bc << 16) | (gc << 8) | rc;
138   }
139   return result;
140 }
141 
ColorGetNext(PyMOLGlobals * G)142 int ColorGetNext(PyMOLGlobals * G)
143 {
144   int result;
145   int next;
146   next = SettingGetGlobal_i(G, cSetting_auto_color_next);
147 
148   if(next >= nAutoColor)
149     next = 0;
150   result = AutoColor[next];
151   next++;
152   if(next >= nAutoColor)
153     next = 0;
154   SettingSetGlobal_i(G, cSetting_auto_color_next, next);
155   return (result);
156 }
157 
ColorGetCurrent(PyMOLGlobals * G)158 int ColorGetCurrent(PyMOLGlobals * G)
159 {
160   int result;
161   int next;
162   next = SettingGetGlobal_i(G, cSetting_auto_color_next);
163   next--;
164   if(next < 0)
165     next = (nAutoColor - 1);
166   result = AutoColor[next];
167   return (result);
168 }
169 
ColorCheckRamped(PyMOLGlobals * G,int index)170 int ColorCheckRamped(PyMOLGlobals * G, int index)
171 {
172   return (index <= (cColorExtCutoff));
173 }
174 
ColorGetRamp(PyMOLGlobals * G,int index)175 ObjectGadgetRamp *ColorGetRamp(PyMOLGlobals * G, int index)
176 {
177   CColor *I = G->Color;
178   ObjectGadgetRamp *result = NULL;
179   if(index <= cColorExtCutoff) {
180     index = cColorExtCutoff - index;
181     if(index < I->NExt) {
182       if(!I->Ext[index].Ptr) {
183         if(I->Ext[index].Name) {
184           const char *name = I->Ext[index].Name;
185           I->Ext[index].Ptr = (void *) ExecutiveFindObjectByName(G, name);
186         }
187       }
188       if(I->Ext[index].Ptr)
189         result = (ObjectGadgetRamp *) I->Ext[index].Ptr;
190     }
191   }
192   return result;
193 }
194 
ColorGetRamped(PyMOLGlobals * G,int index,const float * vertex,float * color,int state)195 int ColorGetRamped(PyMOLGlobals * G, int index, const float *vertex, float *color, int state)
196 {
197   CColor *I = G->Color;
198   int ok = false;
199   if(index <= cColorExtCutoff) {
200     index = cColorExtCutoff - index;
201     if(index < I->NExt) {
202       if(!I->Ext[index].Ptr) {
203         if(I->Ext[index].Name) {
204           const char *name = I->Ext[index].Name;
205           I->Ext[index].Ptr = (void *) ExecutiveFindObjectByName(G, name);
206         }
207       }
208       if(I->Ext[index].Ptr)
209         ok = ObjectGadgetRampInterVertex((ObjectGadgetRamp *) I->Ext[index].Ptr,
210                                          vertex, color, state);
211     }
212 
213   }
214   if(!ok) {
215     color[0] = 1.0;
216     color[1] = 1.0;
217     color[2] = 1.0;
218   } else if(I->LUTActive) {
219     lookup_color(I, color, color, I->BigEndian);
220   }
221   return (ok);
222 }
223 
224 /* Color::ColorGetCheckRamped -- This function gets a color as 3 floats from an index and writes it into
225  * the color argument.  If the index is a ramp, then it uses the vertex and state arguments to lookup the
226  * color value in the ramp.
227  * NOTES: does not support index values cColorObject(-5) or cColorAtomic(-4) color since the object
228  *        or atom color is not passed in.
229  *
230  * PARAMS
231  *
232  * index - color index value
233  * vertex - x/y/z used for ramp lookup (if color index is a ramp)
234  * color - output color array of 3 floats
235  * state - state lookup if ramp
236  *
237  * RETURN VALUE: returns whether the color index is dependent on a ramp.
238  *
239  */
ColorGetCheckRamped(PyMOLGlobals * G,int index,const float * vertex,float * color,int state)240 bool ColorGetCheckRamped(PyMOLGlobals * G, int index, const float *vertex, float *color, int state)
241 {
242   bool isRamped = false;
243   if(ColorCheckRamped(G, index)) {
244     ColorGetRamped(G, index, vertex, color, state);
245     isRamped = true;
246   } else {
247     copy3f(ColorGet(G, index), color);
248   }
249   return isRamped;
250 }
251 
ColorFindExtByName(PyMOLGlobals * G,const char * name,int null_okay,int * best)252 static int ColorFindExtByName(PyMOLGlobals * G, const char *name, int null_okay, int *best)
253 {
254   CColor *I = G->Color;
255   int result = -1;
256   int wm;
257   int a;
258   int mybest;
259   if(!best)
260     best = &mybest;
261   *best = 0;
262   for(a = 0; a < I->NExt; a++) {
263     const char *color_name = I->Ext[a].Name;
264     if(color_name) {
265       wm = WordMatch(G, name, color_name, true);
266       if(wm < 0) {
267         if(null_okay || (I->Ext[a].Ptr)) {
268           result = a;
269           *best = 0;
270           break;
271         }
272       } else if((wm > 0) && ((*best) < wm)) {
273         if(null_okay || (I->Ext[a].Ptr)) {
274           result = a;
275           *best = wm;
276         }
277       }
278     }
279   }
280   return (result);
281 }
282 
283 /**
284  * Map name to index (idx[name] = index)
285  *
286  * @return pointer to stored name string
287  */
reg_name(std::unordered_map<std::string,CColor::ColorIdx> & idx,int index,const char * name)288 static const char* reg_name(
289     std::unordered_map<std::string, CColor::ColorIdx>& idx, int index,
290     const char* name)
291 {
292   auto handle = idx.emplace(name, index);
293 
294   if (!handle.second) {
295     handle.first->second = index;
296   }
297 
298   return handle.first->first.c_str();
299 }
300 
ColorRegisterExt(PyMOLGlobals * G,const char * name,void * ptr,int type)301 void ColorRegisterExt(PyMOLGlobals * G, const char *name, void *ptr, int type)
302 {
303   CColor *I = G->Color;
304   int a;
305 
306   a = ColorFindExtByName(G, name, true, NULL);
307   if(a < 0) {
308     VLACheck(I->Ext, ExtRec, I->NExt);
309     a = I->NExt;
310     I->NExt++;
311     I->Ext[a].Name = reg_name(I->Idx, cColorExtCutoff - a, name);
312   }
313   if(a >= 0) {
314     I->Ext[a].Ptr = ptr;
315     I->Ext[a].Type = type;
316   }
317 }
318 
ColorForgetExt(PyMOLGlobals * G,const char * name)319 void ColorForgetExt(PyMOLGlobals * G, const char *name)
320 {
321   CColor *I = G->Color;
322   int a;
323   a = ColorFindExtByName(G, name, true, NULL);
324 
325   if(a >= 0) {                  /* currently leaks memory in I->Ext array -- TODO fix */
326     if(I->Ext[a].Name) {
327       I->Idx.erase(I->Ext[a].Name);
328     }
329     I->Ext[a].Name = 0;
330     I->Ext[a].Ptr = NULL;
331   }
332 }
333 
ColorExtAsPyList(PyMOLGlobals * G)334 PyObject *ColorExtAsPyList(PyMOLGlobals * G)
335 {
336   CColor *I = G->Color;
337   PyObject *result, *list;
338   ExtRec *ext;
339   int a;
340 
341   result = PyList_New(I->NExt);
342   ext = I->Ext;
343   for(a = 0; a < I->NExt; a++) {
344     list = PyList_New(2);
345     {
346       const char *name = ext->Name ? ext->Name : "";
347       PyList_SetItem(list, 0, PyString_FromString(name));
348     }
349     PyList_SetItem(list, 1, PyInt_FromLong(ext->Type));
350     PyList_SetItem(result, a, list);
351     ext++;
352   }
353   return (result);
354 }
355 
356 
357 /*========================================================================*/
ColorAsPyList(PyMOLGlobals * G)358 PyObject *ColorAsPyList(PyMOLGlobals * G)
359 {
360   CColor *I = G->Color;
361   PyObject *result, *list;
362   ColorRec *color;
363   int n_custom = 0;
364   int a, c;
365   color = I->Color;
366   for(a = 0; a < I->NColor; a++) {
367     if(color->Custom || color->LutColorFlag)
368       n_custom++;
369     color++;
370   }
371   result = PyList_New(n_custom);
372   c = 0;
373   color = I->Color;
374   for(a = 0; a < I->NColor; a++) {
375     if(color->Custom || color->LutColorFlag) {
376       list = PyList_New(7);
377       {
378         const char *name = color->Name;
379         PyList_SetItem(list, 0, PyString_FromString(name));
380       }
381       PyList_SetItem(list, 1, PyInt_FromLong(a));
382       PyList_SetItem(list, 2, PConvFloatArrayToPyList(color->Color, 3));
383       PyList_SetItem(list, 3, PyInt_FromLong((int) color->Custom));
384       PyList_SetItem(list, 4, PyInt_FromLong((int) color->LutColorFlag));
385       PyList_SetItem(list, 5, PConvFloatArrayToPyList(color->LutColor, 3));
386       PyList_SetItem(list, 6, PyInt_FromLong((int) color->Fixed));
387       PyList_SetItem(result, c, list);
388       c++;
389     }
390     color++;
391   }
392   return (result);
393 }
394 
395 /*========================================================================*/
ColorConvertOldSessionIndex(PyMOLGlobals * G,int index)396 int ColorConvertOldSessionIndex(PyMOLGlobals * G, int index)
397 {
398   CColor *I = G->Color;
399   if(index > cColorExtCutoff) {
400     if(I->HaveOldSessionColors) {
401       ColorRec *col = I->Color + (I->NColor - 1);
402       int a;
403       for(a = I->NColor - 1; a >= 0; a--) {
404         if(index == col->old_session_index) {
405           index = a;
406           break;
407         }
408         col--;
409       }
410     }
411   } else if(I->HaveOldSessionExtColors) {
412     ExtRec *ext = I->Ext + (I->NExt - 1);
413     int a;
414     for(a = I->NExt - 1; a >= 0; a--) {
415       if(index == ext->old_session_index) {
416         index = cColorExtCutoff - a;
417         break;
418       }
419       ext--;
420     }
421   }
422   return index;                 /* failsafe */
423 }
424 
ColorExtFromPyList(PyMOLGlobals * G,PyObject * list,int partial_restore)425 int ColorExtFromPyList(PyMOLGlobals * G, PyObject * list, int partial_restore)
426 {
427   int n_ext = 0;
428   int a;
429   int ok = true;
430   CColor *I = G->Color;
431   PyObject *rec;
432   ExtRec *ext;
433 
434   if(partial_restore) {
435     ext = I->Ext;
436     for(a = 0; a < I->NExt; a++) {
437       ext->old_session_index = 0;
438       ext++;
439     }
440     I->HaveOldSessionExtColors = true;
441   } else {
442     I->HaveOldSessionExtColors = false;
443   }
444 
445   if(ok)
446     ok = (list != NULL);
447   if(ok)
448     ok = PyList_Check(list);
449 
450   /* TO SUPPORT BACKWARDS COMPATIBILITY...
451      Always check ll when adding new PyList_GetItem's */
452 
453   if(ok) {
454     n_ext = PyList_Size(list);
455     if(partial_restore) {
456       VLACheck(I->Ext, ExtRec, n_ext + I->NExt);
457       ext = I->Ext + I->NExt;
458     } else {
459       VLACheck(I->Ext, ExtRec, n_ext);
460       ext = I->Ext;
461     }
462     for(a = 0; a < n_ext; a++) {
463       rec = PyList_GetItem(list, a);
464       if(ok)
465         ok = (rec != NULL);
466       if(ok)
467         ok = PyList_Check(rec);
468       if(ok) {
469         WordType name;
470         ok = PConvPyStrToStr(PyList_GetItem(rec, 0), name, sizeof(WordType));
471         ext->Name = reg_name(I->Idx, cColorExtCutoff - a, name);
472       }
473       if(ok)
474         ok = PConvPyIntToInt(PyList_GetItem(rec, 1), &ext->Type);
475       ext->old_session_index = cColorExtCutoff - a;
476       ext++;
477     }
478     if(ok)
479       I->NExt = (ext - I->Ext);
480 
481   }
482   return (ok);
483 }
484 
485 
486 /*========================================================================*/
ColorFromPyList(PyMOLGlobals * G,PyObject * list,int partial_restore)487 int ColorFromPyList(PyMOLGlobals * G, PyObject * list, int partial_restore)
488 {
489   int n_custom = 0;
490   int a;
491   int index = 0, old_session_index = 0;
492   int ok = true;
493   int ll = 0;
494   CColor *I = G->Color;
495   PyObject *rec;
496   ColorRec *color = NULL;
497 
498   if(partial_restore) {
499     color = I->Color;
500     for(a = 0; a < I->NColor; a++) {
501       color->old_session_index = 0;
502       color++;
503     }
504   }
505   I->HaveOldSessionColors = false;
506 
507   if(ok)
508     ok = (list != NULL);
509   if(ok)
510     ok = PyList_Check(list);
511   if(ok) {
512     n_custom = PyList_Size(list);
513     for(a = 0; a < n_custom; a++) {
514       rec = PyList_GetItem(list, a);
515       if(ok)
516         ok = (rec != NULL);
517       if(ok)
518         ok = PyList_Check(rec);
519       if(ok)
520         ll = PyList_Size(rec);
521       /* TO SUPPORT BACKWARDS COMPATIBILITY...
522          Always check ll when adding new PyList_GetItem's */
523       if(ok)
524         ok = PConvPyIntToInt(PyList_GetItem(rec, 1), &index);
525       if(ok) {
526         old_session_index = index;
527         if(partial_restore) {
528           if(I->NColor > index) {       /* conflicts with an existing color... */
529             I->HaveOldSessionColors = true;
530             index = I->NColor;
531           }
532         }
533         if(index >= I->NColor) {
534           VLACheck(I->Color, ColorRec, index);  /* auto-zeros */
535           I->NColor = index + 1;
536         }
537         color = I->Color + index;
538         color->old_session_index = old_session_index;
539         if(ok) {
540           WordType name;
541           ok = PConvPyStrToStr(PyList_GetItem(rec, 0), name, sizeof(WordType));
542           color->Name = reg_name(I->Idx, index, name);
543         }
544         if(ok)
545           ok = PConvPyListToFloatArrayInPlace(PyList_GetItem(rec, 2), color->Color, 3);
546         if(PyList_Size(rec) >= 6) {
547           if(ok)
548             ok = PConvPyIntToChar(PyList_GetItem(rec, 3), &color->Custom);
549           if(ok)
550             ok = PConvPyIntToChar(PyList_GetItem(rec, 4), &color->LutColorFlag);
551           if(ok)
552             ok =
553               PConvPyListToFloatArrayInPlace(PyList_GetItem(rec, 5), color->LutColor, 3);
554         } else {
555           if(ok) {
556             color->Custom = true;
557           }
558         }
559       }
560       if(ok && (ll > 6)) {
561         if(ok)
562           ok = PConvPyIntToChar(PyList_GetItem(rec, 6), &color->Fixed);
563       } else if(ok && color) {
564         color->Fixed = false;
565       }
566       if(!ok)
567         break;
568     }
569   }
570   return (ok);
571 }
572 
573 /*========================================================================*/
ColorDef(PyMOLGlobals * G,const char * name,const float * v,int mode,int quiet)574 void ColorDef(PyMOLGlobals * G, const char *name, const float *v, int mode, int quiet)
575 {
576   CColor *I = G->Color;
577   int color = -1;
578   int a;
579   int wm;
580 
581   {
582       auto it = I->Idx.find(name);
583       if(it != I->Idx.end()){
584         color = it->second;
585       }
586   }
587 
588   if(color < 0) {
589     for(a = 0; a < I->NColor; a++) {
590       auto* color_name = I->Color[a].Name;
591       if(color_name) {
592         wm = WordMatch(G, name, color_name, true);
593         if(wm < 0) {
594           color = a;
595           break;
596         }
597       }
598     }
599   }
600 
601   if(color < 0) {
602     color = I->NColor;
603     VLACheck(I->Color, ColorRec, I->NColor);
604     I->NColor++;
605     I->Color[color].Name = reg_name(I->Idx, color, name);
606   }
607 
608   I->Color[color].Color[0] = v[0];
609   I->Color[color].Color[1] = v[1];
610   I->Color[color].Color[2] = v[2];
611 
612   switch (mode) {
613   case 1:
614     I->Color[color].Fixed = true;
615     break;
616   default:
617     I->Color[color].Fixed = false;
618     break;
619   }
620 
621   I->Color[color].Custom = true;
622   ColorUpdateFromLut(G, color);
623 
624   if(!quiet) {
625     PRINTFB(G, FB_Executive, FB_Actions)
626       " Color: \"%s\" defined as [ %3.3f, %3.3f, %3.3f ].\n", name, v[0], v[1], v[2]
627       ENDFB(G);
628 
629   }
630 
631   PRINTFD(G, FB_Color)
632     " Color: and assigned number %d.\n", color ENDFD;
633 }
634 
635 
636 /*========================================================================*/
ColorGetIndex(PyMOLGlobals * G,const char * name)637 int ColorGetIndex(PyMOLGlobals * G, const char *name)
638 {
639   CColor *I = G->Color;
640   int color = -1;               /* default for unknown is white */
641   int ext_color;
642   int a;
643   int i;
644   int wm, best = 0;
645   int ext_best = 0;
646   int is_numeric = true;
647   int found = false;
648 
649   {
650     const char *c;
651     c = name;
652     while(*c) {
653       if((((*c) < '0') || ((*c) > '9')) && ((*c) != '-')) {
654         is_numeric = false;
655         break;
656       }
657       c++;
658     }
659   }
660 
661   if(is_numeric) {
662     if(sscanf(name, "%d", &i)) {
663       if((i < I->NColor) && (i >= 0))
664         return (i);
665       else if(i == cColorNewAuto)
666         return (ColorGetNext(G));
667       else if(i == cColorCurAuto)
668         return (ColorGetCurrent(G));
669       else if(i == cColorAtomic)
670         return cColorAtomic;
671       else if(i == cColorObject)
672         return cColorObject;
673       else if(i == cColorFront)
674         return cColorFront;
675       else if(i == cColorBack)
676         return cColorBack;
677       else if(i == -1)
678         return -1;
679       if (i & cColor_TRGB_Bits)
680         return i;
681     }
682   }
683   if((name[0] == '0') && (name[1] == 'x')) {    /* explicit hex RGB 0x000000 */
684     int tmp_color;
685     if(sscanf(name + 2, "%x", (unsigned int *) &tmp_color) == 1) {
686       tmp_color = (cColor_TRGB_Bits |
687                    (tmp_color & 0x00FFFFFF) | ((tmp_color >> 2) & 0x3F000000));
688       return tmp_color;
689     }
690   }
691   if(WordMatch(G, name, "default", true))
692     return (-1);
693   if(WordMatch(G, name, "auto", true))
694     return (ColorGetNext(G));
695   if(WordMatch(G, name, "current", true))
696     return (ColorGetCurrent(G));
697   if(WordMatch(G, name, "atomic", true))
698     return (cColorAtomic);
699   if(WordMatch(G, name, "object", true))
700     return (cColorObject);
701   if(WordMatch(G, name, "front", true))
702     return (cColorFront);
703   if(WordMatch(G, name, "back", true))
704     return (cColorBack);
705 
706   {                  /* search for a perfect match (fast!) */
707       auto it = I->Idx.find(name);
708       if(it != I->Idx.end()){
709         found = true;
710         color = it->second;
711       }
712   }
713   if(!found) {                  /* search for an imperfect match */
714     for(a = 0; a < I->NColor; a++) {
715       auto* color_name = I->Color[a].Name;
716       if(color_name) {
717         wm = WordMatch(G, name, color_name, true);
718         if(wm < 0) {
719           color = a;
720           best = 0;
721           break;
722         } else if((wm > 0) && (best < wm)) {
723           color = a;
724           best = wm;
725         }
726       }
727     }
728     if(best || (color < 0)) {
729       ext_color = ColorFindExtByName(G, name, true, &ext_best);
730       if(ext_color >= 0) {
731         ext_color = cColorExtCutoff - ext_color;    /* indicates external */
732         if((!ext_best) || (ext_best > best))    /* perfect or better match? */
733           color = ext_color;
734       }
735     }
736   }
737   return (color);
738 }
739 
740 
741 /*========================================================================*/
ColorGetNamed(PyMOLGlobals * G,const char * name)742 const float *ColorGetNamed(PyMOLGlobals * G, const char *name)
743 {
744   return (ColorGet(G, ColorGetIndex(G, name)));
745 }
746 
747 
748 /*========================================================================*/
ColorGetName(PyMOLGlobals * G,int index)749 const char *ColorGetName(PyMOLGlobals * G, int index)
750 {
751   CColor *I = G->Color;
752   if((index >= 0) && (index < I->NColor)) {
753     return I->Color[index].Name;
754   } else if((index & cColor_TRGB_Mask) == cColor_TRGB_Bits) {
755     index = (((index & 0xFFFFFF) | ((index << 2) & 0xFC000000) |        /* convert 6 bits of trans into 8 */
756               ((index >> 4) & 0x03000000)));
757     if(index & 0xFF000000)      /* if transparent */
758       sprintf(I->RGBName, "0x%08x", index);
759     else                        /* else */
760       sprintf(I->RGBName, "0x%06x", index);
761     return I->RGBName;
762   } else if(index <= cColorExtCutoff) {
763     int a = cColorExtCutoff - index;
764     if(a < I->NExt) {
765       return I->Ext[a].Name;
766     } else
767       return NULL;
768   }
769   return (NULL);
770 }
771 
772 
773 /*========================================================================*/
ColorGetStatus(PyMOLGlobals * G,int index)774 int ColorGetStatus(PyMOLGlobals * G, int index)
775 {
776   CColor *I = G->Color;
777   /* return 0 if color is invalid, -1 if hidden;
778      1 otherwise */
779   int result = 0;
780   if((index >= 0) && (index < I->NColor)) {
781     auto* color_name = I->Color[index].Name;
782     if(color_name) {
783       const char* c = color_name;
784       result = 1;
785       while(*c) {
786         if(((*c) >= '0') && ((*c) <= '9')) {
787           result = -1;
788           break;
789         }
790         c++;
791       }
792     }
793   }
794   return (result);
795 }
796 
797 
798 /*========================================================================*/
ColorGetNColor(PyMOLGlobals * G)799 int ColorGetNColor(PyMOLGlobals * G)
800 {
801   CColor *I = G->Color;
802   return (I->NColor);
803 }
804 
805 
806 /*========================================================================*/
ColorFree(PyMOLGlobals * G)807 void ColorFree(PyMOLGlobals * G)
808 {
809   CColor *I = G->Color;
810   VLAFreeP(I->Color);
811   VLAFreeP(I->Ext);
812   DeleteP(I);
813 }
814 
815 
816 /*========================================================================*/
817 
ColorReset(PyMOLGlobals * G)818 void ColorReset(PyMOLGlobals * G)
819 {
820 
821 /* PyMOL core color names
822 
823   1   1   1   white
824  .5  .5  .5   grey/gray
825   0   0   0   black
826 
827   1   0   0   red
828   0   1   0   green
829   0   0   1   blue
830 
831   1   1   0   yellow
832   1   0   1   magenta
833   0   1   1   cyan
834 
835   1   1  .5   paleyellow  .
836   1  .5   1   violet      .
837  .5   1   1   aquamarine  .
838 
839   1  .5  .5   deepsalmon  .
840  .5   1  .5   palegreen   .
841  .5  .5   1   slate       .
842 
843  .75 .75  0   olive       .
844  .75  0  .75  purple      .
845   0  .75 .75  teal        .
846 
847  .6  .6  .1   deepolive   .
848  .6  .1  .6   deeppurple  .
849  .1  .6  .6   deepteal    .
850 
851   1  .5   0   orange      .
852   1   0  .5   hotpink     .
853  .5   1   0   chartreuse  .
854   0   1  .5   limegreen   .
855   0  .5   1   marine      .
856  .5   0   1   purpleblue  .
857 
858 */
859 
860   CColor *I = G->Color;
861   ColorRec *color = I->Color;
862   int n_color = 0;
863 
864   char name[10];
865   int a;
866   int set1;
867   float f;
868   float spectrumS[13][3] = {
869     {1.0, 0.0, 1.0},            /* magenta - 0 */
870     {0.5, 0.0, 1.0},
871     {0.0, 0.0, 1.0},            /* blue - 166.66  */
872     {0.0, 0.5, 1.0},
873     {0.0, 1.0, 1.0},            /* cyan - 333.33 */
874 
875     {0.0, 1.0, 0.5},
876     {0.0, 1.0, 0.0},            /* green - 500 */
877     {0.5, 1.0, 0.0},
878     {1.0, 1.0, 0.0},            /* yellow - 666.66 */
879     {1.0, 0.5, 0.0},
880 
881     {1.0, 0.0, 0.0},            /* red - 833.33 */
882     {1.0, 0.0, 0.5},
883     {1.0, 0.0, 1.0},            /* magenta - 999 */
884   };
885 
886   float spectrumR[13][3] = {
887     {1.0, 1.0, 0.0},            /* yellow - 0 */
888     {0.5, 1.0, 0.0},            /* chartreuse */
889     {0.0, 1.0, 0.0},            /* green - 166.66 */
890     {0.0, 1.0, 0.5},            /* limegreen */
891     {0.0, 1.0, 1.0},            /* cyan - 333.33 */
892 
893     {0.0, 0.5, 1.0},            /* marine */
894     {0.0, 0.0, 1.0},            /* blue - 500 */
895     {0.5, 0.0, 1.0},            /* purpleblue */
896     {1.0, 0.0, 1.0},            /* magenta - 666.66 */
897     {1.0, 0.0, 0.5},            /* hotpink */
898 
899     {1.0, 0.0, 0.0},            /* red - 833.33 */
900     {1.0, 0.5, 0.0},            /* orange */
901     {1.0, 1.0, 0.0},            /* yellow - 999 */
902   };
903 
904   float spectrumC[][3] = {
905     {1.0, 1.0, 0.0},            /* yellow - 0 */
906     {0.0, 0.0, 1.0},            /* blue - 83.333 */
907     {1.0, 0.0, 0.0},            /* red - 167.67 */
908     {0.0, 1.0, 0.0},            /* green - 250.00 */
909     {1.0, 0.0, 1.0},            /* magenta - 333.33 */
910 
911     {0.0, 1.0, 1.0},            /* cyan - 416.67 */
912     {1.0, 1.0, 0.0},            /* yellow - 500.00 */
913     {0.0, 1.0, 0.0},            /* green - 583.33 */
914     {0.0, 0.0, 1.0},            /* blue - 666.67 */
915     {1.0, 0.0, 1.0},            /* magenta - 750.00 */
916 
917     {1.0, 1.0, 0.0},            /* yellow - 833.33 */
918     {1.0, 0.0, 0.0},            /* red - 916.67 */
919     {0.0, 1.0, 1.0},            /* cyan - 999 */
920   };
921 
922   float spectrumW[][3] = {
923     {1.0, 1.0, 0.0},            /* yellow - 0 */
924     {1.0, 1.0, 1.0},            /* white */
925     {0.0, 0.0, 1.0},            /* blue  - 83.333 */
926     {1.0, 1.0, 1.0},            /* white */
927     {1.0, 0.0, 0.0},            /* red - 166.67 */
928 
929     {1.0, 1.0, 1.0},            /* white */
930     {0.0, 1.0, 0.0},            /* green - 250.00 */
931     {1.0, 1.0, 1.0},            /* white */
932     {1.0, 0.0, 1.0},            /* magenta - 333.33 */
933     {1.0, 1.0, 1.0},            /* white */
934 
935     {0.0, 1.0, 1.0},            /* cyan - 416.67 */
936     {1.0, 1.0, 1.0},            /* white */
937     {1.0, 1.0, 0.0},            /* yellow - 500.00 */
938     {1.0, 1.0, 1.0},            /* white */
939     {0.0, 1.0, 0.0},            /* green - 583.33 */
940 
941     {1.0, 1.0, 1.0},            /* white */
942     {0.0, 0.0, 1.0},            /* blue - 666.67 */
943     {1.0, 1.0, 1.0},            /* white */
944     {1.0, 0.0, 1.0},            /* magenta - 750.00 */
945     {1.0, 1.0, 1.0},            /* white */
946 
947     {1.0, 1.0, 0.0},            /* yellow - 833.33 */
948     {1.0, 1.0, 1.0},            /* white */
949     {1.0, 0.0, 0.0},            /* red - 916.67 */
950     {1.0, 1.0, 1.0},            /* white */
951     {0.0, 1.0, 1.0},            /* cyan - 999 */
952   };
953 
954   float spectrumO[29][3] = {
955     /* a rainbow with perceptive color balancing and extra blue/red at the ends */
956     {1.0, 0.0, 1.0},            /* violet */
957     {0.8F, 0.0, 1.0},
958 
959     {0.5F, 0.0, 1.0},           /* blend */
960 
961     {0.0, 0.0, 1.0},            /* blue */
962     {0.0, 0.0, 1.0},            /* blue */
963     {0.0, 0.2F, 1.0},
964 
965     {0.0, 0.5F, 1.0},           /* blend */
966 
967     {0.0, 0.8F, 1.0},
968     {0.0, 1.0, 1.0},            /* cyan */
969     {0.0, 1.0, 0.8F},
970 
971     {0.0, 1.0, 0.5F},           /* blend */
972 
973     {0.0, 1.0, 0.2F},
974     {0.0, 1.0, 0.0},            /* green */
975     {0.2F, 1.0, 0.0},
976 
977     {0.5F, 1.0, 0.0},           /* blend */
978 
979     {0.8F, 1.0, 0.0},
980     {1.0, 1.0, 0.0},            /* yellow */
981     {1.0, 0.9F, 0.0},
982 
983     {1.0, 0.75F, 0.0},          /* blend */
984 
985     {1.0, 0.6F, 0.0},
986     {1.0, 0.5F, 0.0},           /* orange */
987     {1.0, 0.4F, 0.0},
988 
989     {1.0, 0.3F, 0.0},           /* blend */
990 
991     {1.0, 0.2F, 0.0},
992     {1.0, 0.0, 0.0},            /* red */
993     {1.0, 0.0, 0.0},            /* red */
994 
995     {1.0, 0.0, 0.5F},           /* blend */
996 
997     {1.0, 0.0, 0.8F},           /* violet */
998     {1.0, 0.0, 1.0},            /* violet */
999   };
1000 
1001   I->Idx.clear();
1002 
1003   /* BLUE->VIOLET->RED r546 to r909 */
1004   /* BLUE->CYAN->GREEN->YELLOW->RED s182 to s909 */
1005   /* BLUE->WHITE->RED w00 to */
1006 
1007   color->Name = reg_name(I->Idx, n_color, "white");
1008   color->Color[0] = 1.0F;
1009   color->Color[1] = 1.0F;
1010   color->Color[2] = 1.0F;
1011   n_color++;
1012   color++;
1013 
1014   color->Name = reg_name(I->Idx, n_color, "black");
1015   color->Color[0] = 0.0F;
1016   color->Color[1] = 0.0F;
1017   color->Color[2] = 0.0F;
1018   n_color++;
1019   color++;
1020 
1021   color->Name = reg_name(I->Idx, n_color, "blue");
1022   color->Color[0] = 0.0F;
1023   color->Color[1] = 0.0F;
1024   color->Color[2] = 1.0F;
1025   n_color++;
1026   color++;
1027 
1028   color->Name = reg_name(I->Idx, n_color, "green");
1029   color->Color[0] = 0.0F;
1030   color->Color[1] = 1.0F;
1031   color->Color[2] = 0.0F;
1032   n_color++;
1033   color++;
1034 
1035   color->Name = reg_name(I->Idx, n_color, "red");
1036   color->Color[0] = 1.0F;
1037   color->Color[1] = 0.0F;
1038   color->Color[2] = 0.0F;
1039   n_color++;
1040   color++;
1041 
1042   color->Name = reg_name(I->Idx, n_color, "cyan");
1043   color->Color[0] = 0.0F;
1044   color->Color[1] = 1.0F;
1045   color->Color[2] = 1.0F;
1046   n_color++;
1047   color++;
1048 
1049   color->Name = reg_name(I->Idx, n_color, "yellow");
1050   color->Color[0] = 1.0F;
1051   color->Color[1] = 1.0F;
1052   color->Color[2] = 0.0F;
1053   n_color++;
1054   color++;
1055 
1056   color->Name = reg_name(I->Idx, n_color, "dash");
1057   color->Color[0] = 1.0F;
1058   color->Color[1] = 1.0F;
1059   color->Color[2] = 0.0F;
1060   n_color++;
1061   color++;
1062 
1063   color->Name = reg_name(I->Idx, n_color, "magenta");
1064   color->Color[0] = 1.0F;
1065   color->Color[1] = 0.0F;
1066   color->Color[2] = 1.0F;
1067   n_color++;
1068   color++;
1069 
1070   color->Name = reg_name(I->Idx, n_color, "salmon");
1071   color->Color[0] = 1.0F;
1072   color->Color[1] = 0.6F;       /* was 0.5 */
1073   color->Color[2] = 0.6F;       /* wat 0.5 */
1074   n_color++;
1075   color++;
1076 
1077   color->Name = reg_name(I->Idx, n_color, "lime");
1078   color->Color[0] = 0.5F;
1079   color->Color[1] = 1.0F;
1080   color->Color[2] = 0.5F;
1081   n_color++;
1082   color++;
1083 
1084   color->Name = reg_name(I->Idx, n_color, "slate");
1085   color->Color[0] = 0.5F;
1086   color->Color[1] = 0.5F;
1087   color->Color[2] = 1.0F;
1088   n_color++;
1089   color++;
1090 
1091   color->Name = reg_name(I->Idx, n_color, "hotpink");
1092   color->Color[0] = 1.0F;
1093   color->Color[1] = 0.0F;
1094   color->Color[2] = 0.5F;
1095   n_color++;
1096   color++;
1097 
1098   color->Name = reg_name(I->Idx, n_color, "orange");
1099   color->Color[0] = 1.0F;
1100   color->Color[1] = 0.5F;
1101   color->Color[2] = 0.0F;
1102   n_color++;
1103   color++;
1104 
1105   color->Name = reg_name(I->Idx, n_color, "chartreuse");        /* AKA puke green */
1106   color->Color[0] = 0.5F;
1107   color->Color[1] = 1.0F;
1108   color->Color[2] = 0.0F;
1109   n_color++;
1110   color++;
1111 
1112   color->Name = reg_name(I->Idx, n_color, "limegreen");
1113   color->Color[0] = 0.0F;
1114   color->Color[1] = 1.0F;
1115   color->Color[2] = 0.5F;
1116   n_color++;
1117   color++;
1118 
1119   color->Name = reg_name(I->Idx, n_color, "purpleblue");        /* legacy name */
1120   color->Color[0] = 0.5F;
1121   color->Color[1] = 0.0F;
1122   color->Color[2] = 1.0F;
1123   n_color++;
1124   color++;
1125 
1126   color->Name = reg_name(I->Idx, n_color, "marine");
1127   color->Color[0] = 0.0F;
1128   color->Color[1] = 0.5F;
1129   color->Color[2] = 1.0F;
1130   n_color++;
1131   color++;
1132 
1133   color->Name = reg_name(I->Idx, n_color, "olive");
1134   color->Color[0] = 0.77F;
1135   color->Color[1] = 0.70F;
1136   color->Color[2] = 0.00F;
1137   n_color++;
1138   color++;
1139 
1140   color->Name = reg_name(I->Idx, n_color, "purple");
1141   color->Color[0] = 0.75F;
1142   color->Color[1] = 0.00F;
1143   color->Color[2] = 0.75F;
1144   n_color++;
1145   color++;
1146 
1147   color->Name = reg_name(I->Idx, n_color, "teal");
1148   color->Color[0] = 0.00F;
1149   color->Color[1] = 0.75F;
1150   color->Color[2] = 0.75F;
1151   n_color++;
1152   color++;
1153 
1154   color->Name = reg_name(I->Idx, n_color, "ruby");
1155   color->Color[0] = 0.6F;
1156   color->Color[1] = 0.2F;
1157   color->Color[2] = 0.2F;
1158   n_color++;
1159   color++;
1160 
1161   color->Name = reg_name(I->Idx, n_color, "forest");
1162   color->Color[0] = 0.2F;
1163   color->Color[1] = 0.6F;
1164   color->Color[2] = 0.2F;
1165   n_color++;
1166   color++;
1167 
1168   color->Name = reg_name(I->Idx, n_color, "deepblue");  /* was "deep" */
1169   color->Color[0] = 0.25F;
1170   color->Color[1] = 0.25F;
1171   color->Color[2] = 0.65F;
1172   n_color++;
1173   color++;
1174 
1175   color->Name = reg_name(I->Idx, n_color, "grey");      /* english spelling */
1176   color->Color[0] = 0.5F;
1177   color->Color[1] = 0.5F;
1178   color->Color[2] = 0.5F;
1179   n_color++;
1180   color++;
1181 
1182   color->Name = reg_name(I->Idx, n_color, "gray");      /* american spelling */
1183   color->Color[0] = 0.5F;
1184   color->Color[1] = 0.5F;
1185   color->Color[2] = 0.5F;
1186   n_color++;
1187   color++;
1188 
1189   color->Name = reg_name(I->Idx, n_color, "carbon");
1190   color->Color[0] = 0.2F;
1191   color->Color[1] = 1.0F;
1192   color->Color[2] = 0.2F;
1193   n_color++;
1194   color++;
1195 
1196   color->Name = reg_name(I->Idx, n_color, "nitrogen");
1197   color->Color[0] = 0.2F;
1198   color->Color[1] = 0.2F;
1199   color->Color[2] = 1.0F;
1200   n_color++;
1201   color++;
1202 
1203   color->Name = reg_name(I->Idx, n_color, "oxygen");
1204   color->Color[0] = 1.0F;
1205   color->Color[1] = 0.3F;
1206   color->Color[2] = 0.3F;
1207   n_color++;
1208   color++;
1209 
1210   color->Name = reg_name(I->Idx, n_color, "hydrogen");
1211   color->Color[0] = 0.9F;
1212   color->Color[1] = 0.9F;
1213   color->Color[2] = 0.9F;
1214   n_color++;
1215   color++;
1216 
1217   color->Name = reg_name(I->Idx, n_color, "brightorange");
1218   color->Color[0] = 1.0F;
1219   color->Color[1] = 0.7F;
1220   color->Color[2] = 0.2F;
1221   n_color++;
1222   color++;
1223 
1224   color->Name = reg_name(I->Idx, n_color, "sulfur");
1225   color->Color[0] = 0.9F;       /* needs to be far enough from "yellow" */
1226   color->Color[1] = 0.775F;     /* to be resolved, while still slightly on */
1227   color->Color[2] = 0.25F;      /* the yellow side of yelloworange */
1228   n_color++;
1229   color++;
1230 
1231   color->Name = reg_name(I->Idx, n_color, "tv_red");
1232   color->Color[0] = 1.0F;
1233   color->Color[1] = 0.2F;
1234   color->Color[2] = 0.2F;
1235   n_color++;
1236   color++;
1237 
1238   color->Name = reg_name(I->Idx, n_color, "tv_green");
1239   color->Color[0] = 0.2F;
1240   color->Color[1] = 1.0F;
1241   color->Color[2] = 0.2F;
1242   n_color++;
1243   color++;
1244 
1245   color->Name = reg_name(I->Idx, n_color, "tv_blue");
1246   color->Color[0] = 0.3F;
1247   color->Color[1] = 0.3F;
1248   color->Color[2] = 1.0F;
1249   n_color++;
1250   color++;
1251 
1252   color->Name = reg_name(I->Idx, n_color, "tv_yellow");
1253   color->Color[0] = 1.0F;
1254   color->Color[1] = 1.0F;
1255   color->Color[2] = 0.2F;
1256   n_color++;
1257   color++;
1258 
1259   color->Name = reg_name(I->Idx, n_color, "yelloworange");
1260   color->Color[0] = 1.0F;
1261   color->Color[1] = 0.87F;
1262   color->Color[2] = 0.37F;
1263   n_color++;
1264   color++;
1265 
1266   color->Name = reg_name(I->Idx, n_color, "tv_orange");
1267   color->Color[0] = 1.0F;
1268   color->Color[1] = 0.55F;
1269   color->Color[2] = 0.15F;
1270   n_color++;
1271   color++;
1272 
1273   color->Name = reg_name(I->Idx, n_color, "br0");
1274   color->Color[0] = 0.1F;
1275   color->Color[1] = 0.1F;
1276   color->Color[2] = 1.0F;
1277   n_color++;
1278   color++;
1279 
1280   color->Name = reg_name(I->Idx, n_color, "br1");
1281   color->Color[0] = 0.2F;
1282   color->Color[1] = 0.1F;
1283   color->Color[2] = 0.9F;
1284   n_color++;
1285   color++;
1286 
1287   color->Name = reg_name(I->Idx, n_color, "br2");
1288   color->Color[0] = 0.3F;
1289   color->Color[1] = 0.1F;
1290   color->Color[2] = 0.8F;
1291   n_color++;
1292   color++;
1293 
1294   color->Name = reg_name(I->Idx, n_color, "br3");
1295   color->Color[0] = 0.4F;
1296   color->Color[1] = 0.1F;
1297   color->Color[2] = 0.7F;
1298   n_color++;
1299   color++;
1300 
1301   color->Name = reg_name(I->Idx, n_color, "br4");
1302   color->Color[0] = 0.5F;
1303   color->Color[1] = 0.1F;
1304   color->Color[2] = 0.6F;
1305   n_color++;
1306   color++;
1307 
1308   color->Name = reg_name(I->Idx, n_color, "br5");
1309   color->Color[0] = 0.6F;
1310   color->Color[1] = 0.1F;
1311   color->Color[2] = 0.5F;
1312   n_color++;
1313   color++;
1314 
1315   color->Name = reg_name(I->Idx, n_color, "br6");
1316   color->Color[0] = 0.7F;
1317   color->Color[1] = 0.1F;
1318   color->Color[2] = 0.4F;
1319   n_color++;
1320   color++;
1321 
1322   color->Name = reg_name(I->Idx, n_color, "br7");
1323   color->Color[0] = 0.8F;
1324   color->Color[1] = 0.1F;
1325   color->Color[2] = 0.3F;
1326   n_color++;
1327   color++;
1328 
1329   color->Name = reg_name(I->Idx, n_color, "br8");
1330   color->Color[0] = 0.9F;
1331   color->Color[1] = 0.1F;
1332   color->Color[2] = 0.2F;
1333   n_color++;
1334   color++;
1335 
1336   color->Name = reg_name(I->Idx, n_color, "br9");
1337   color->Color[0] = 1.0F;
1338   color->Color[1] = 0.1F;
1339   color->Color[2] = 0.1F;
1340   n_color++;
1341   color++;
1342 
1343   color->Name = reg_name(I->Idx, n_color, "pink");
1344   color->Color[0] = 1.0F;
1345   color->Color[1] = 0.65F;
1346   color->Color[2] = 0.85F;
1347   n_color++;
1348   color++;
1349 
1350   color->Name = reg_name(I->Idx, n_color, "firebrick");
1351   color->Color[0] = 0.698F;
1352   color->Color[1] = 0.13F;
1353   color->Color[2] = 0.13F;
1354   n_color++;
1355   color++;
1356 
1357   color->Name = reg_name(I->Idx, n_color, "chocolate");
1358   color->Color[0] = 0.555F;
1359   color->Color[1] = 0.222F;
1360   color->Color[2] = 0.111F;
1361   n_color++;
1362   color++;
1363 
1364   color->Name = reg_name(I->Idx, n_color, "brown");
1365   color->Color[0] = 0.65F;
1366   color->Color[1] = 0.32F;
1367   color->Color[2] = 0.17F;
1368   n_color++;
1369   color++;
1370 
1371   color->Name = reg_name(I->Idx, n_color, "wheat");
1372   color->Color[0] = 0.99F;
1373   color->Color[1] = 0.82F;
1374   color->Color[2] = 0.65F;
1375   n_color++;
1376   color++;
1377 
1378   color->Name = reg_name(I->Idx, n_color, "violet");
1379   color->Color[0] = 1.0F;
1380   color->Color[1] = 0.5F;
1381   color->Color[2] = 1.0F;
1382   n_color++;
1383   color++;
1384 
1385   /* greybow */
1386 
1387   strcpy(name, "grey00");       /* english spelling */
1388   for(a = 0; a < 100; a = a + 1) {
1389     name[5] = (a % 10) + '0';
1390     name[4] = ((a % 100) / 10) + '0';
1391     /* sprintf(color->Name,"grey%02d",a); */
1392     color->Name = reg_name(I->Idx, n_color, name);
1393     color->Color[0] = a / 99.0F;
1394     color->Color[1] = a / 99.0F;
1395     color->Color[2] = a / 99.0F;
1396     n_color++;
1397     color++;
1398   }
1399 
1400   color->Name = reg_name(I->Idx, n_color, "lightmagenta");
1401   color->Color[0] = 1.0F;
1402   color->Color[1] = 0.2F;
1403   color->Color[2] = 0.8F;
1404   n_color++;
1405   color++;
1406 
1407 #define A_DIV 83.333333333F
1408 
1409   /* full spectrum (s000-s999) */
1410 
1411   strcpy(name, "s000");
1412   for(a = 0; a < 1000; a = a + 1) {
1413     set1 = (int) (a / A_DIV);
1414     name[3] = (a % 10) + '0';
1415     name[2] = ((a % 100) / 10) + '0';
1416     name[1] = ((a % 1000) / 100) + '0';
1417     /* sprintf(color->Name,"s%03d",a); */
1418     f = 1.0F - (a - (set1 * A_DIV)) / A_DIV;
1419     color->Name = reg_name(I->Idx, n_color, name);
1420     color->Color[0] = f * spectrumS[set1][0] + (1.0F - f) * spectrumS[set1 + 1][0];
1421     color->Color[1] = f * spectrumS[set1][1] + (1.0F - f) * spectrumS[set1 + 1][1];
1422     color->Color[2] = f * spectrumS[set1][2] + (1.0F - f) * spectrumS[set1 + 1][2];
1423     n_color++;
1424     color++;
1425   }
1426 
1427   /* offset & reversed full spectrum (r000-r999) */
1428 
1429   strcpy(name, "r000");
1430   for(a = 0; a < 1000; a = a + 1) {
1431     set1 = (int) (a / A_DIV);
1432     /* sprintf(color->Name,"r%03d",a); */
1433     name[3] = (a % 10) + '0';
1434     name[2] = ((a % 100) / 10) + '0';
1435     name[1] = ((a % 1000) / 100) + '0';
1436     f = 1.0F - (a - (set1 * A_DIV)) / A_DIV;
1437     color->Name = reg_name(I->Idx, n_color, name);
1438     color->Color[0] = f * spectrumR[set1][0] + (1.0F - f) * spectrumR[set1 + 1][0];
1439     color->Color[1] = f * spectrumR[set1][1] + (1.0F - f) * spectrumR[set1 + 1][1];
1440     color->Color[2] = f * spectrumR[set1][2] + (1.0F - f) * spectrumR[set1 + 1][2];
1441     n_color++;
1442     color++;
1443   }
1444 
1445   /* complementary spectra (c000-c999) */
1446 
1447   strcpy(name, "c000");
1448   for(a = 0; a < 1000; a = a + 1) {
1449     set1 = (int) (a / A_DIV);
1450     /*     sprintf(color->Name,"c%03d",a); */
1451     name[3] = (a % 10) + '0';
1452     name[2] = ((a % 100) / 10) + '0';
1453     name[1] = ((a % 1000) / 100) + '0';
1454     f = 1.0F - (a - (set1 * A_DIV)) / A_DIV;
1455     color->Name = reg_name(I->Idx, n_color, name);
1456     color->Color[0] = f * spectrumC[set1][0] + (1.0F - f) * spectrumC[set1 + 1][0];
1457     color->Color[1] = f * spectrumC[set1][1] + (1.0F - f) * spectrumC[set1 + 1][1];
1458     color->Color[2] = f * spectrumC[set1][2] + (1.0F - f) * spectrumC[set1 + 1][2];
1459     n_color++;
1460     color++;
1461   }
1462 
1463 #define W_DIV 41.666666667F
1464 
1465   /* complementary spectra separated by white (w000-w999) */
1466 
1467   strcpy(name, "w000");
1468   for(a = 0; a < 1000; a = a + 1) {
1469     set1 = (int) (a / W_DIV);
1470     /* sprintf(color->Name,"w%03d",a); */
1471     name[3] = (a % 10) + '0';
1472     name[2] = ((a % 100) / 10) + '0';
1473     name[1] = ((a % 1000) / 100) + '0';
1474     f = 1.0F - (a - (set1 * W_DIV)) / W_DIV;
1475     color->Name = reg_name(I->Idx, n_color, name);
1476     color->Color[0] = f * spectrumW[set1][0] + (1.0F - f) * spectrumW[set1 + 1][0];
1477     color->Color[1] = f * spectrumW[set1][1] + (1.0F - f) * spectrumW[set1 + 1][1];
1478     color->Color[2] = f * spectrumW[set1][2] + (1.0F - f) * spectrumW[set1 + 1][2];
1479     n_color++;
1480     color++;
1481   }
1482 
1483   color->Name = reg_name(I->Idx, n_color, "density");
1484   color->Color[0] = 0.1F;
1485   color->Color[1] = 0.1F;
1486   color->Color[2] = 0.6F;
1487   n_color++;
1488   color++;
1489 
1490   strcpy(name, "gray00");       /* american */
1491   for(a = 0; a < 100; a = a + 1) {
1492     name[5] = (a % 10) + '0';
1493     name[4] = ((a % 100) / 10) + '0';
1494     /* sprintf(color->Name,"gray%02d",a); */
1495     color->Name = reg_name(I->Idx, n_color, name);
1496     color->Color[0] = a / 99.0F;
1497     color->Color[1] = a / 99.0F;
1498     color->Color[2] = a / 99.0F;
1499     n_color++;
1500     color++;
1501   }
1502 
1503   /* original full spectrum, with extra blue and red at the ends (o000-o999) */
1504 
1505 #define B_DIV 35.7143F
1506 
1507   strcpy(name, "o000");
1508   for(a = 0; a < 1000; a = a + 1) {
1509     set1 = (int) (a / B_DIV);
1510     name[3] = (a % 10) + '0';
1511     name[2] = ((a % 100) / 10) + '0';
1512     name[1] = ((a % 1000) / 100) + '0';
1513     /* sprintf(color->Name,"o%03d",a); */
1514     f = 1.0F - (a - (set1 * B_DIV)) / B_DIV;
1515     color->Name = reg_name(I->Idx, n_color, name);
1516     color->Color[0] = f * spectrumO[set1][0] + (1.0F - f) * spectrumO[set1 + 1][0];
1517     color->Color[1] = f * spectrumO[set1][1] + (1.0F - f) * spectrumO[set1 + 1][1];
1518     color->Color[2] = f * spectrumO[set1][2] + (1.0F - f) * spectrumO[set1 + 1][2];
1519     n_color++;
1520     color++;
1521   }
1522 
1523   color->Name = reg_name(I->Idx, n_color, "paleyellow");
1524   color->Color[0] = 1.0F;
1525   color->Color[1] = 1.0F;
1526   color->Color[2] = 0.5F;
1527   n_color++;
1528   color++;
1529 
1530   color->Name = reg_name(I->Idx, n_color, "aquamarine");
1531   color->Color[0] = 0.5F;
1532   color->Color[1] = 1.0F;
1533   color->Color[2] = 1.0F;
1534   n_color++;
1535   color++;
1536 
1537   color->Name = reg_name(I->Idx, n_color, "deepsalmon");
1538   color->Color[0] = 1.0F;
1539   color->Color[1] = 0.5F;
1540   color->Color[2] = 0.5F;
1541   n_color++;
1542   color++;
1543 
1544   color->Name = reg_name(I->Idx, n_color, "palegreen");
1545   color->Color[0] = 0.65F;
1546   color->Color[1] = 0.9F;
1547   color->Color[2] = 0.65F;
1548   n_color++;
1549   color++;
1550 
1551   color->Name = reg_name(I->Idx, n_color, "deepolive");
1552   color->Color[0] = 0.6F;
1553   color->Color[1] = 0.6F;
1554   color->Color[2] = 0.1F;
1555   n_color++;
1556   color++;
1557 
1558   color->Name = reg_name(I->Idx, n_color, "deeppurple");
1559   color->Color[0] = 0.6F;
1560   color->Color[1] = 0.1F;
1561   color->Color[2] = 0.6F;
1562   n_color++;
1563   color++;
1564 
1565   color->Name = reg_name(I->Idx, n_color, "deepteal");
1566   color->Color[0] = 0.1F;
1567   color->Color[1] = 0.6F;
1568   color->Color[2] = 0.6F;
1569   n_color++;
1570   color++;
1571 
1572   color->Name = reg_name(I->Idx, n_color, "lightblue");
1573   color->Color[0] = 0.75F;
1574   color->Color[1] = 0.75;
1575   color->Color[2] = 1.0F;
1576   n_color++;
1577   color++;
1578 
1579   color->Name = reg_name(I->Idx, n_color, "lightorange");
1580   color->Color[0] = 1.0F;
1581   color->Color[1] = 0.8F;
1582   color->Color[2] = 0.5F;
1583   n_color++;
1584   color++;
1585 
1586   color->Name = reg_name(I->Idx, n_color, "palecyan");
1587   color->Color[0] = 0.8F;
1588   color->Color[1] = 1.0F;
1589   color->Color[2] = 1.0F;
1590   n_color++;
1591   color++;
1592 
1593   color->Name = reg_name(I->Idx, n_color, "lightteal");
1594   color->Color[0] = 0.4F;
1595   color->Color[1] = 0.7F;
1596   color->Color[2] = 0.7F;
1597   n_color++;
1598   color++;
1599 
1600   color->Name = reg_name(I->Idx, n_color, "splitpea");
1601   color->Color[0] = 0.52F;
1602   color->Color[1] = 0.75F;
1603   color->Color[2] = 0.00F;
1604   n_color++;
1605   color++;
1606 
1607   color->Name = reg_name(I->Idx, n_color, "raspberry");
1608   color->Color[0] = 0.70F;
1609   color->Color[1] = 0.30F;
1610   color->Color[2] = 0.40F;
1611   n_color++;
1612   color++;
1613 
1614   color->Name = reg_name(I->Idx, n_color, "sand");
1615   color->Color[0] = 0.72F;
1616   color->Color[1] = 0.55F;
1617   color->Color[2] = 0.30F;
1618   n_color++;
1619   color++;
1620 
1621   color->Name = reg_name(I->Idx, n_color, "smudge");
1622   color->Color[0] = 0.55F;
1623   color->Color[1] = 0.70F;
1624   color->Color[2] = 0.40F;
1625   n_color++;
1626   color++;
1627 
1628   color->Name = reg_name(I->Idx, n_color, "violetpurple");
1629   color->Color[0] = 0.55F;
1630   color->Color[1] = 0.25F;
1631   color->Color[2] = 0.60F;
1632   n_color++;
1633   color++;
1634 
1635   color->Name = reg_name(I->Idx, n_color, "dirtyviolet");
1636   color->Color[0] = 0.70F;
1637   color->Color[1] = 0.50F;
1638   color->Color[2] = 0.50F;
1639   n_color++;
1640   color++;
1641 
1642   color->Name = reg_name(I->Idx, n_color, "deepsalmon");
1643   color->Color[0] = 1.00F;
1644   color->Color[1] = 0.42F;
1645   color->Color[2] = 0.42F;
1646   n_color++;
1647   color++;
1648 
1649   color->Name = reg_name(I->Idx, n_color, "lightpink");
1650   color->Color[0] = 1.00F;
1651   color->Color[1] = 0.75F;
1652   color->Color[2] = 0.87F;
1653   n_color++;
1654   color++;
1655 
1656   color->Name = reg_name(I->Idx, n_color, "greencyan");
1657   color->Color[0] = 0.25F;
1658   color->Color[1] = 1.00F;
1659   color->Color[2] = 0.75F;
1660   n_color++;
1661   color++;
1662 
1663   color->Name = reg_name(I->Idx, n_color, "limon");
1664   color->Color[0] = 0.75F;
1665   color->Color[1] = 1.00F;
1666   color->Color[2] = 0.25F;
1667   n_color++;
1668   color++;
1669 
1670   color->Name = reg_name(I->Idx, n_color, "skyblue");
1671   color->Color[0] = 0.20F;
1672   color->Color[1] = 0.50F;
1673   color->Color[2] = 0.80F;
1674   n_color++;
1675   color++;
1676 
1677   color->Name = reg_name(I->Idx, n_color, "bluewhite");
1678   color->Color[0] = 0.85F;
1679   color->Color[1] = 0.85F;
1680   color->Color[2] = 1.00F;
1681   n_color++;
1682   color++;
1683 
1684   color->Name = reg_name(I->Idx, n_color, "warmpink");
1685   color->Color[0] = 0.85F;
1686   color->Color[1] = 0.20F;
1687   color->Color[2] = 0.50F;
1688   n_color++;
1689   color++;
1690 
1691   color->Name = reg_name(I->Idx, n_color, "darksalmon");
1692   color->Color[0] = 0.73F;
1693   color->Color[1] = 0.55F;
1694   color->Color[2] = 0.52F;
1695   n_color++;
1696   color++;
1697 
1698   color->Name = reg_name(I->Idx, n_color, "helium");
1699   color->Color[0] = 0.850980392F;
1700   color->Color[1] = 1.000000000F;
1701   color->Color[2] = 1.000000000F;
1702   n_color++;
1703   color++;
1704 
1705   color->Name = reg_name(I->Idx, n_color, "lithium");
1706   color->Color[0] = 0.800000000F;
1707   color->Color[1] = 0.501960784F;
1708   color->Color[2] = 1.000000000F;
1709   n_color++;
1710   color++;
1711 
1712   color->Name = reg_name(I->Idx, n_color, "beryllium");
1713   color->Color[0] = 0.760784314F;
1714   color->Color[1] = 1.000000000F;
1715   color->Color[2] = 0.000000000F;
1716   n_color++;
1717   color++;
1718 
1719   color->Name = reg_name(I->Idx, n_color, "boron");
1720   color->Color[0] = 1.000000000F;
1721   color->Color[1] = 0.709803922F;
1722   color->Color[2] = 0.709803922F;
1723   n_color++;
1724   color++;
1725 
1726   color->Name = reg_name(I->Idx, n_color, "fluorine");
1727   color->Color[0] = 0.701960784F;
1728   color->Color[1] = 1.000000000F;
1729   color->Color[2] = 1.000000000F;
1730   n_color++;
1731   color++;
1732 
1733   color->Name = reg_name(I->Idx, n_color, "neon");
1734   color->Color[0] = 0.701960784F;
1735   color->Color[1] = 0.890196078F;
1736   color->Color[2] = 0.960784314F;
1737   n_color++;
1738   color++;
1739 
1740   color->Name = reg_name(I->Idx, n_color, "sodium");
1741   color->Color[0] = 0.670588235F;
1742   color->Color[1] = 0.360784314F;
1743   color->Color[2] = 0.949019608F;
1744   n_color++;
1745   color++;
1746 
1747   color->Name = reg_name(I->Idx, n_color, "magnesium");
1748   color->Color[0] = 0.541176471F;
1749   color->Color[1] = 1.000000000F;
1750   color->Color[2] = 0.000000000F;
1751   n_color++;
1752   color++;
1753 
1754   color->Name = reg_name(I->Idx, n_color, "aluminum");
1755   color->Color[0] = 0.749019608F;
1756   color->Color[1] = 0.650980392F;
1757   color->Color[2] = 0.650980392F;
1758   n_color++;
1759   color++;
1760 
1761   color->Name = reg_name(I->Idx, n_color, "silicon");
1762   color->Color[0] = 0.941176471F;
1763   color->Color[1] = 0.784313725F;
1764   color->Color[2] = 0.627450980F;
1765   n_color++;
1766   color++;
1767 
1768   color->Name = reg_name(I->Idx, n_color, "phosphorus");
1769   color->Color[0] = 1.000000000F;
1770   color->Color[1] = 0.501960784F;
1771   color->Color[2] = 0.000000000F;
1772   n_color++;
1773   color++;
1774 
1775   color->Name = reg_name(I->Idx, n_color, "chlorine");
1776   color->Color[0] = 0.121568627F;
1777   color->Color[1] = 0.941176471F;
1778   color->Color[2] = 0.121568627F;
1779   n_color++;
1780   color++;
1781 
1782   color->Name = reg_name(I->Idx, n_color, "argon");
1783   color->Color[0] = 0.501960784F;
1784   color->Color[1] = 0.819607843F;
1785   color->Color[2] = 0.890196078F;
1786   n_color++;
1787   color++;
1788 
1789   color->Name = reg_name(I->Idx, n_color, "potassium");
1790   color->Color[0] = 0.560784314F;
1791   color->Color[1] = 0.250980392F;
1792   color->Color[2] = 0.831372549F;
1793   n_color++;
1794   color++;
1795 
1796   color->Name = reg_name(I->Idx, n_color, "calcium");
1797   color->Color[0] = 0.239215686F;
1798   color->Color[1] = 1.000000000F;
1799   color->Color[2] = 0.000000000F;
1800   n_color++;
1801   color++;
1802 
1803   color->Name = reg_name(I->Idx, n_color, "scandium");
1804   color->Color[0] = 0.901960784F;
1805   color->Color[1] = 0.901960784F;
1806   color->Color[2] = 0.901960784F;
1807   n_color++;
1808   color++;
1809 
1810   color->Name = reg_name(I->Idx, n_color, "titanium");
1811   color->Color[0] = 0.749019608F;
1812   color->Color[1] = 0.760784314F;
1813   color->Color[2] = 0.780392157F;
1814   n_color++;
1815   color++;
1816 
1817   color->Name = reg_name(I->Idx, n_color, "vanadium");
1818   color->Color[0] = 0.650980392F;
1819   color->Color[1] = 0.650980392F;
1820   color->Color[2] = 0.670588235F;
1821   n_color++;
1822   color++;
1823 
1824   color->Name = reg_name(I->Idx, n_color, "chromium");
1825   color->Color[0] = 0.541176471F;
1826   color->Color[1] = 0.600000000F;
1827   color->Color[2] = 0.780392157F;
1828   n_color++;
1829   color++;
1830 
1831   color->Name = reg_name(I->Idx, n_color, "manganese");
1832   color->Color[0] = 0.611764706F;
1833   color->Color[1] = 0.478431373F;
1834   color->Color[2] = 0.780392157F;
1835   n_color++;
1836   color++;
1837 
1838   color->Name = reg_name(I->Idx, n_color, "iron");
1839   color->Color[0] = 0.878431373F;
1840   color->Color[1] = 0.400000000F;
1841   color->Color[2] = 0.200000000F;
1842   n_color++;
1843   color++;
1844 
1845   color->Name = reg_name(I->Idx, n_color, "cobalt");
1846   color->Color[0] = 0.941176471F;
1847   color->Color[1] = 0.564705882F;
1848   color->Color[2] = 0.627450980F;
1849   n_color++;
1850   color++;
1851 
1852   color->Name = reg_name(I->Idx, n_color, "nickel");
1853   color->Color[0] = 0.313725490F;
1854   color->Color[1] = 0.815686275F;
1855   color->Color[2] = 0.313725490F;
1856   n_color++;
1857   color++;
1858 
1859   color->Name = reg_name(I->Idx, n_color, "copper");
1860   color->Color[0] = 0.784313725F;
1861   color->Color[1] = 0.501960784F;
1862   color->Color[2] = 0.200000000F;
1863   n_color++;
1864   color++;
1865 
1866   color->Name = reg_name(I->Idx, n_color, "zinc");
1867   color->Color[0] = 0.490196078F;
1868   color->Color[1] = 0.501960784F;
1869   color->Color[2] = 0.690196078F;
1870   n_color++;
1871   color++;
1872 
1873   color->Name = reg_name(I->Idx, n_color, "gallium");
1874   color->Color[0] = 0.760784314F;
1875   color->Color[1] = 0.560784314F;
1876   color->Color[2] = 0.560784314F;
1877   n_color++;
1878   color++;
1879 
1880   color->Name = reg_name(I->Idx, n_color, "germanium");
1881   color->Color[0] = 0.400000000F;
1882   color->Color[1] = 0.560784314F;
1883   color->Color[2] = 0.560784314F;
1884   n_color++;
1885   color++;
1886 
1887   color->Name = reg_name(I->Idx, n_color, "arsenic");
1888   color->Color[0] = 0.741176471F;
1889   color->Color[1] = 0.501960784F;
1890   color->Color[2] = 0.890196078F;
1891   n_color++;
1892   color++;
1893 
1894   color->Name = reg_name(I->Idx, n_color, "selenium");
1895   color->Color[0] = 1.000000000F;
1896   color->Color[1] = 0.631372549F;
1897   color->Color[2] = 0.000000000F;
1898   n_color++;
1899   color++;
1900 
1901   color->Name = reg_name(I->Idx, n_color, "bromine");
1902   color->Color[0] = 0.650980392F;
1903   color->Color[1] = 0.160784314F;
1904   color->Color[2] = 0.160784314F;
1905   n_color++;
1906   color++;
1907 
1908   color->Name = reg_name(I->Idx, n_color, "krypton");
1909   color->Color[0] = 0.360784314F;
1910   color->Color[1] = 0.721568627F;
1911   color->Color[2] = 0.819607843F;
1912   n_color++;
1913   color++;
1914 
1915   color->Name = reg_name(I->Idx, n_color, "rubidium");
1916   color->Color[0] = 0.439215686F;
1917   color->Color[1] = 0.180392157F;
1918   color->Color[2] = 0.690196078F;
1919   n_color++;
1920   color++;
1921 
1922   color->Name = reg_name(I->Idx, n_color, "strontium");
1923   color->Color[0] = 0.000000000F;
1924   color->Color[1] = 1.000000000F;
1925   color->Color[2] = 0.000000000F;
1926   n_color++;
1927   color++;
1928 
1929   color->Name = reg_name(I->Idx, n_color, "yttrium");
1930   color->Color[0] = 0.580392157F;
1931   color->Color[1] = 1.000000000F;
1932   color->Color[2] = 1.000000000F;
1933   n_color++;
1934   color++;
1935 
1936   color->Name = reg_name(I->Idx, n_color, "zirconium");
1937   color->Color[0] = 0.580392157F;
1938   color->Color[1] = 0.878431373F;
1939   color->Color[2] = 0.878431373F;
1940   n_color++;
1941   color++;
1942 
1943   color->Name = reg_name(I->Idx, n_color, "niobium");
1944   color->Color[0] = 0.450980392F;
1945   color->Color[1] = 0.760784314F;
1946   color->Color[2] = 0.788235294F;
1947   n_color++;
1948   color++;
1949 
1950   color->Name = reg_name(I->Idx, n_color, "molybdenum");
1951   color->Color[0] = 0.329411765F;
1952   color->Color[1] = 0.709803922F;
1953   color->Color[2] = 0.709803922F;
1954   n_color++;
1955   color++;
1956 
1957   color->Name = reg_name(I->Idx, n_color, "technetium");
1958   color->Color[0] = 0.231372549F;
1959   color->Color[1] = 0.619607843F;
1960   color->Color[2] = 0.619607843F;
1961   n_color++;
1962   color++;
1963 
1964   color->Name = reg_name(I->Idx, n_color, "ruthenium");
1965   color->Color[0] = 0.141176471F;
1966   color->Color[1] = 0.560784314F;
1967   color->Color[2] = 0.560784314F;
1968   n_color++;
1969   color++;
1970 
1971   color->Name = reg_name(I->Idx, n_color, "rhodium");
1972   color->Color[0] = 0.039215686F;
1973   color->Color[1] = 0.490196078F;
1974   color->Color[2] = 0.549019608F;
1975   n_color++;
1976   color++;
1977 
1978   color->Name = reg_name(I->Idx, n_color, "palladium");
1979   color->Color[0] = 0.000000000F;
1980   color->Color[1] = 0.411764706F;
1981   color->Color[2] = 0.521568627F;
1982   n_color++;
1983   color++;
1984 
1985   color->Name = reg_name(I->Idx, n_color, "silver");
1986   color->Color[0] = 0.752941176F;
1987   color->Color[1] = 0.752941176F;
1988   color->Color[2] = 0.752941176F;
1989   n_color++;
1990   color++;
1991 
1992   color->Name = reg_name(I->Idx, n_color, "cadmium");
1993   color->Color[0] = 1.000000000F;
1994   color->Color[1] = 0.850980392F;
1995   color->Color[2] = 0.560784314F;
1996   n_color++;
1997   color++;
1998 
1999   color->Name = reg_name(I->Idx, n_color, "indium");
2000   color->Color[0] = 0.650980392F;
2001   color->Color[1] = 0.458823529F;
2002   color->Color[2] = 0.450980392F;
2003   n_color++;
2004   color++;
2005 
2006   color->Name = reg_name(I->Idx, n_color, "tin");
2007   color->Color[0] = 0.400000000F;
2008   color->Color[1] = 0.501960784F;
2009   color->Color[2] = 0.501960784F;
2010   n_color++;
2011   color++;
2012 
2013   color->Name = reg_name(I->Idx, n_color, "antimony");
2014   color->Color[0] = 0.619607843F;
2015   color->Color[1] = 0.388235294F;
2016   color->Color[2] = 0.709803922F;
2017   n_color++;
2018   color++;
2019 
2020   color->Name = reg_name(I->Idx, n_color, "tellurium");
2021   color->Color[0] = 0.831372549F;
2022   color->Color[1] = 0.478431373F;
2023   color->Color[2] = 0.000000000F;
2024   n_color++;
2025   color++;
2026 
2027   color->Name = reg_name(I->Idx, n_color, "iodine");
2028   color->Color[0] = 0.580392157F;
2029   color->Color[1] = 0.000000000F;
2030   color->Color[2] = 0.580392157F;
2031   n_color++;
2032   color++;
2033 
2034   color->Name = reg_name(I->Idx, n_color, "xenon");
2035   color->Color[0] = 0.258823529F;
2036   color->Color[1] = 0.619607843F;
2037   color->Color[2] = 0.690196078F;
2038   n_color++;
2039   color++;
2040 
2041   color->Name = reg_name(I->Idx, n_color, "cesium");
2042   color->Color[0] = 0.341176471F;
2043   color->Color[1] = 0.090196078F;
2044   color->Color[2] = 0.560784314F;
2045   n_color++;
2046   color++;
2047 
2048   color->Name = reg_name(I->Idx, n_color, "barium");
2049   color->Color[0] = 0.000000000F;
2050   color->Color[1] = 0.788235294F;
2051   color->Color[2] = 0.000000000F;
2052   n_color++;
2053   color++;
2054 
2055   color->Name = reg_name(I->Idx, n_color, "lanthanum");
2056   color->Color[0] = 0.439215686F;
2057   color->Color[1] = 0.831372549F;
2058   color->Color[2] = 1.000000000F;
2059   n_color++;
2060   color++;
2061 
2062   color->Name = reg_name(I->Idx, n_color, "cerium");
2063   color->Color[0] = 1.000000000F;
2064   color->Color[1] = 1.000000000F;
2065   color->Color[2] = 0.780392157F;
2066   n_color++;
2067   color++;
2068 
2069   color->Name = reg_name(I->Idx, n_color, "praseodymium");
2070   color->Color[0] = 0.850980392F;
2071   color->Color[1] = 1.000000000F;
2072   color->Color[2] = 0.780392157F;
2073   n_color++;
2074   color++;
2075 
2076   color->Name = reg_name(I->Idx, n_color, "neodymium");
2077   color->Color[0] = 0.780392157F;
2078   color->Color[1] = 1.000000000F;
2079   color->Color[2] = 0.780392157F;
2080   n_color++;
2081   color++;
2082 
2083   color->Name = reg_name(I->Idx, n_color, "promethium");
2084   color->Color[0] = 0.639215686F;
2085   color->Color[1] = 1.000000000F;
2086   color->Color[2] = 0.780392157F;
2087   n_color++;
2088   color++;
2089 
2090   color->Name = reg_name(I->Idx, n_color, "samarium");
2091   color->Color[0] = 0.560784314F;
2092   color->Color[1] = 1.000000000F;
2093   color->Color[2] = 0.780392157F;
2094   n_color++;
2095   color++;
2096 
2097   color->Name = reg_name(I->Idx, n_color, "europium");
2098   color->Color[0] = 0.380392157F;
2099   color->Color[1] = 1.000000000F;
2100   color->Color[2] = 0.780392157F;
2101   n_color++;
2102   color++;
2103 
2104   color->Name = reg_name(I->Idx, n_color, "gadolinium");
2105   color->Color[0] = 0.270588235F;
2106   color->Color[1] = 1.000000000F;
2107   color->Color[2] = 0.780392157F;
2108   n_color++;
2109   color++;
2110 
2111   color->Name = reg_name(I->Idx, n_color, "terbium");
2112   color->Color[0] = 0.188235294F;
2113   color->Color[1] = 1.000000000F;
2114   color->Color[2] = 0.780392157F;
2115   n_color++;
2116   color++;
2117 
2118   color->Name = reg_name(I->Idx, n_color, "dysprosium");
2119   color->Color[0] = 0.121568627F;
2120   color->Color[1] = 1.000000000F;
2121   color->Color[2] = 0.780392157F;
2122   n_color++;
2123   color++;
2124 
2125   color->Name = reg_name(I->Idx, n_color, "holmium");
2126   color->Color[0] = 0.000000000F;
2127   color->Color[1] = 1.000000000F;
2128   color->Color[2] = 0.611764706F;
2129   n_color++;
2130   color++;
2131 
2132   color->Name = reg_name(I->Idx, n_color, "erbium");
2133   color->Color[0] = 0.000000000F;
2134   color->Color[1] = 0.901960784F;
2135   color->Color[2] = 0.458823529F;
2136   n_color++;
2137   color++;
2138 
2139   color->Name = reg_name(I->Idx, n_color, "thulium");
2140   color->Color[0] = 0.000000000F;
2141   color->Color[1] = 0.831372549F;
2142   color->Color[2] = 0.321568627F;
2143   n_color++;
2144   color++;
2145 
2146   color->Name = reg_name(I->Idx, n_color, "ytterbium");
2147   color->Color[0] = 0.000000000F;
2148   color->Color[1] = 0.749019608F;
2149   color->Color[2] = 0.219607843F;
2150   n_color++;
2151   color++;
2152 
2153   color->Name = reg_name(I->Idx, n_color, "lutetium");
2154   color->Color[0] = 0.000000000F;
2155   color->Color[1] = 0.670588235F;
2156   color->Color[2] = 0.141176471F;
2157   n_color++;
2158   color++;
2159 
2160   color->Name = reg_name(I->Idx, n_color, "hafnium");
2161   color->Color[0] = 0.301960784F;
2162   color->Color[1] = 0.760784314F;
2163   color->Color[2] = 1.000000000F;
2164   n_color++;
2165   color++;
2166 
2167   color->Name = reg_name(I->Idx, n_color, "tantalum");
2168   color->Color[0] = 0.301960784F;
2169   color->Color[1] = 0.650980392F;
2170   color->Color[2] = 1.000000000F;
2171   n_color++;
2172   color++;
2173 
2174   color->Name = reg_name(I->Idx, n_color, "tungsten");
2175   color->Color[0] = 0.129411765F;
2176   color->Color[1] = 0.580392157F;
2177   color->Color[2] = 0.839215686F;
2178   n_color++;
2179   color++;
2180 
2181   color->Name = reg_name(I->Idx, n_color, "rhenium");
2182   color->Color[0] = 0.149019608F;
2183   color->Color[1] = 0.490196078F;
2184   color->Color[2] = 0.670588235F;
2185   n_color++;
2186   color++;
2187 
2188   color->Name = reg_name(I->Idx, n_color, "osmium");
2189   color->Color[0] = 0.149019608F;
2190   color->Color[1] = 0.400000000F;
2191   color->Color[2] = 0.588235294F;
2192   n_color++;
2193   color++;
2194 
2195   color->Name = reg_name(I->Idx, n_color, "iridium");
2196   color->Color[0] = 0.090196078F;
2197   color->Color[1] = 0.329411765F;
2198   color->Color[2] = 0.529411765F;
2199   n_color++;
2200   color++;
2201 
2202   color->Name = reg_name(I->Idx, n_color, "platinum");
2203   color->Color[0] = 0.815686275F;
2204   color->Color[1] = 0.815686275F;
2205   color->Color[2] = 0.878431373F;
2206   n_color++;
2207   color++;
2208 
2209   color->Name = reg_name(I->Idx, n_color, "gold");
2210   color->Color[0] = 1.000000000F;
2211   color->Color[1] = 0.819607843F;
2212   color->Color[2] = 0.137254902F;
2213   n_color++;
2214   color++;
2215 
2216   color->Name = reg_name(I->Idx, n_color, "mercury");
2217   color->Color[0] = 0.721568627F;
2218   color->Color[1] = 0.721568627F;
2219   color->Color[2] = 0.815686275F;
2220   n_color++;
2221   color++;
2222 
2223   color->Name = reg_name(I->Idx, n_color, "thallium");
2224   color->Color[0] = 0.650980392F;
2225   color->Color[1] = 0.329411765F;
2226   color->Color[2] = 0.301960784F;
2227   n_color++;
2228   color++;
2229 
2230   color->Name = reg_name(I->Idx, n_color, "lead");
2231   color->Color[0] = 0.341176471F;
2232   color->Color[1] = 0.349019608F;
2233   color->Color[2] = 0.380392157F;
2234   n_color++;
2235   color++;
2236 
2237   color->Name = reg_name(I->Idx, n_color, "bismuth");
2238   color->Color[0] = 0.619607843F;
2239   color->Color[1] = 0.309803922F;
2240   color->Color[2] = 0.709803922F;
2241   n_color++;
2242   color++;
2243 
2244   color->Name = reg_name(I->Idx, n_color, "polonium");
2245   color->Color[0] = 0.670588235F;
2246   color->Color[1] = 0.360784314F;
2247   color->Color[2] = 0.000000000F;
2248   n_color++;
2249   color++;
2250 
2251   color->Name = reg_name(I->Idx, n_color, "astatine");
2252   color->Color[0] = 0.458823529F;
2253   color->Color[1] = 0.309803922F;
2254   color->Color[2] = 0.270588235F;
2255   n_color++;
2256   color++;
2257 
2258   color->Name = reg_name(I->Idx, n_color, "radon");
2259   color->Color[0] = 0.258823529F;
2260   color->Color[1] = 0.509803922F;
2261   color->Color[2] = 0.588235294F;
2262   n_color++;
2263   color++;
2264 
2265   color->Name = reg_name(I->Idx, n_color, "francium");
2266   color->Color[0] = 0.258823529F;
2267   color->Color[1] = 0.000000000F;
2268   color->Color[2] = 0.400000000F;
2269   n_color++;
2270   color++;
2271 
2272   color->Name = reg_name(I->Idx, n_color, "radium");
2273   color->Color[0] = 0.000000000F;
2274   color->Color[1] = 0.490196078F;
2275   color->Color[2] = 0.000000000F;
2276   n_color++;
2277   color++;
2278 
2279   color->Name = reg_name(I->Idx, n_color, "actinium");
2280   color->Color[0] = 0.439215686F;
2281   color->Color[1] = 0.670588235F;
2282   color->Color[2] = 0.980392157F;
2283   n_color++;
2284   color++;
2285 
2286   color->Name = reg_name(I->Idx, n_color, "thorium");
2287   color->Color[0] = 0.000000000F;
2288   color->Color[1] = 0.729411765F;
2289   color->Color[2] = 1.000000000F;
2290   n_color++;
2291   color++;
2292 
2293   color->Name = reg_name(I->Idx, n_color, "protactinium");
2294   color->Color[0] = 0.000000000F;
2295   color->Color[1] = 0.631372549F;
2296   color->Color[2] = 1.000000000F;
2297   n_color++;
2298   color++;
2299 
2300   color->Name = reg_name(I->Idx, n_color, "uranium");
2301   color->Color[0] = 0.000000000F;
2302   color->Color[1] = 0.560784314F;
2303   color->Color[2] = 1.000000000F;
2304   n_color++;
2305   color++;
2306 
2307   color->Name = reg_name(I->Idx, n_color, "neptunium");
2308   color->Color[0] = 0.000000000F;
2309   color->Color[1] = 0.501960784F;
2310   color->Color[2] = 1.000000000F;
2311   n_color++;
2312   color++;
2313 
2314   color->Name = reg_name(I->Idx, n_color, "plutonium");
2315   color->Color[0] = 0.000000000F;
2316   color->Color[1] = 0.419607843F;
2317   color->Color[2] = 1.000000000F;
2318   n_color++;
2319   color++;
2320 
2321   color->Name = reg_name(I->Idx, n_color, "americium");
2322   color->Color[0] = 0.329411765F;
2323   color->Color[1] = 0.360784314F;
2324   color->Color[2] = 0.949019608F;
2325   n_color++;
2326   color++;
2327 
2328   color->Name = reg_name(I->Idx, n_color, "curium");
2329   color->Color[0] = 0.470588235F;
2330   color->Color[1] = 0.360784314F;
2331   color->Color[2] = 0.890196078F;
2332   n_color++;
2333   color++;
2334 
2335   color->Name = reg_name(I->Idx, n_color, "berkelium");
2336   color->Color[0] = 0.541176471F;
2337   color->Color[1] = 0.309803922F;
2338   color->Color[2] = 0.890196078F;
2339   n_color++;
2340   color++;
2341 
2342   color->Name = reg_name(I->Idx, n_color, "californium");
2343   color->Color[0] = 0.631372549F;
2344   color->Color[1] = 0.211764706F;
2345   color->Color[2] = 0.831372549F;
2346   n_color++;
2347   color++;
2348 
2349   color->Name = reg_name(I->Idx, n_color, "einsteinium");
2350   color->Color[0] = 0.701960784F;
2351   color->Color[1] = 0.121568627F;
2352   color->Color[2] = 0.831372549F;
2353   n_color++;
2354   color++;
2355 
2356   color->Name = reg_name(I->Idx, n_color, "fermium");
2357   color->Color[0] = 0.701960784F;
2358   color->Color[1] = 0.121568627F;
2359   color->Color[2] = 0.729411765F;
2360   n_color++;
2361   color++;
2362 
2363   color->Name = reg_name(I->Idx, n_color, "mendelevium");
2364   color->Color[0] = 0.701960784F;
2365   color->Color[1] = 0.050980392F;
2366   color->Color[2] = 0.650980392F;
2367   n_color++;
2368   color++;
2369 
2370   color->Name = reg_name(I->Idx, n_color, "nobelium");
2371   color->Color[0] = 0.741176471F;
2372   color->Color[1] = 0.050980392F;
2373   color->Color[2] = 0.529411765F;
2374   n_color++;
2375   color++;
2376 
2377   color->Name = reg_name(I->Idx, n_color, "lawrencium");
2378   color->Color[0] = 0.780392157F;
2379   color->Color[1] = 0.000000000F;
2380   color->Color[2] = 0.400000000F;
2381   n_color++;
2382   color++;
2383 
2384   color->Name = reg_name(I->Idx, n_color, "rutherfordium");
2385   color->Color[0] = 0.800000000F;
2386   color->Color[1] = 0.000000000F;
2387   color->Color[2] = 0.349019608F;
2388   n_color++;
2389   color++;
2390 
2391   color->Name = reg_name(I->Idx, n_color, "dubnium");
2392   color->Color[0] = 0.819607843F;
2393   color->Color[1] = 0.000000000F;
2394   color->Color[2] = 0.309803922F;
2395   n_color++;
2396   color++;
2397 
2398   color->Name = reg_name(I->Idx, n_color, "seaborgium");
2399   color->Color[0] = 0.850980392F;
2400   color->Color[1] = 0.000000000F;
2401   color->Color[2] = 0.270588235F;
2402   n_color++;
2403   color++;
2404 
2405   color->Name = reg_name(I->Idx, n_color, "bohrium");
2406   color->Color[0] = 0.878431373F;
2407   color->Color[1] = 0.000000000F;
2408   color->Color[2] = 0.219607843F;
2409   n_color++;
2410   color++;
2411 
2412   color->Name = reg_name(I->Idx, n_color, "hassium");
2413   color->Color[0] = 0.901960784F;
2414   color->Color[1] = 0.000000000F;
2415   color->Color[2] = 0.180392157F;
2416   n_color++;
2417   color++;
2418 
2419   color->Name = reg_name(I->Idx, n_color, "meitnerium");
2420   color->Color[0] = 0.921568627F;
2421   color->Color[1] = 0.000000000F;
2422   color->Color[2] = 0.149019608F;
2423   n_color++;
2424   color++;
2425 
2426   color->Name = reg_name(I->Idx, n_color, "deuterium");
2427   color->Color[0] = 0.9F;
2428   color->Color[1] = 0.9F;
2429   color->Color[2] = 0.9F;
2430   n_color++;
2431   color++;
2432 
2433   color->Name = reg_name(I->Idx, n_color, "lonepair");
2434   color->Color[0] = 0.5F;
2435   color->Color[1] = 0.5F;
2436   color->Color[2] = 0.5F;
2437   n_color++;
2438   color++;
2439 
2440   color->Name = reg_name(I->Idx, n_color, "pseudoatom");
2441   color->Color[0] = 0.9F;
2442   color->Color[1] = 0.9F;
2443   color->Color[2] = 0.9F;
2444   n_color++;
2445   color++;
2446 
2447   color = I->Color;
2448   for(a = 0; a < n_color; a++) {
2449     /* mark all current colors non-custom so that they don't get saved in session files */
2450     color[a].Custom = false;
2451   }
2452 
2453   I->NColor = n_color;
2454   I->NExt = 0;
2455 }
2456 
ColorTableLoad(PyMOLGlobals * G,const char * fname,float gamma,int quiet)2457 int ColorTableLoad(PyMOLGlobals * G, const char *fname, float gamma, int quiet)
2458 {
2459   CColor *I = G->Color;
2460   int ok = true;
2461 
2462   I->Gamma = gamma;
2463   if(!fname[0]) {
2464     ColorUpdateFromLut(G, -1);
2465   } else {
2466     int width = 512, height = 512;
2467     if(!strcmp(fname, "rgb")) {
2468       if(!I->ColorTable.empty()) {
2469         I->ColorTable.clear();
2470         PRINTFB(G, FB_Color, FB_Actions)
2471           " Color: purged table; restoring RGB colors.\n" ENDFB(G);
2472       }
2473       ColorUpdateFromLut(G, -1);
2474     } else if(!strcmp(fname, "greyscale")) {
2475 
2476       int x, y;
2477       unsigned int r = 0, g = 0, b = 0;
2478       unsigned int *pixel, mask, *p;
2479       unsigned int rc;
2480 
2481       if(I->BigEndian)
2482         mask = 0x000000FF;
2483       else
2484         mask = 0xFF000000;
2485 
2486       I->ColorTable.resize(512 * 512);
2487 
2488       p = I->ColorTable.data();
2489       for(x = 0; x < width; x++)
2490         for(y = 0; y < height; y++)
2491           *(p++) = mask;
2492 
2493       for(y = 0; y < height; y++)
2494         for(x = 0; x < width; x++) {
2495           rc = (r + g + b)/3;
2496 
2497           pixel = I->ColorTable.data() + ((width) * y) + x;
2498           if(I->BigEndian) {
2499             *(pixel) = mask | (rc << 24) | (rc << 16) | (rc << 8);
2500           } else {
2501             *(pixel) = mask | (rc << 16) | (rc << 8) | rc;
2502           }
2503           b = b + 4;
2504           if(!(0xFF & b)) {
2505             b = 0;
2506             g = g + 4;
2507             if(!(0xFF & g)) {
2508               g = 0;
2509               r = r + 4;
2510             }
2511           }
2512         }
2513 
2514       if(!quiet) {
2515         PRINTFB(G, FB_Color, FB_Actions)
2516           " Color: defined table '%s'.\n", fname ENDFB(G);
2517       }
2518 
2519       ColorUpdateFromLut(G, -1);
2520       ExecutiveInvalidateRep(G, cKeywordAll, cRepAll, cRepInvColor);
2521       SceneChanged(G);
2522 
2523 
2524     } else if(!strcmp(fname, "pymol")) {
2525 
2526       int x, y;
2527       unsigned int r = 0, g = 0, b = 0;
2528       unsigned int *pixel, mask, *p;
2529       unsigned int rc, bc, gc;
2530       unsigned int gf, bf, rf;
2531 
2532       float green_max = 0.75F;
2533       float red_max = 0.95F;
2534       float blue_max = 0.97F;
2535 
2536       float min_factor = 0.15F;
2537 
2538       red_max = SettingGetGlobal_f(G, cSetting_pymol_space_max_red);
2539       green_max = SettingGetGlobal_f(G, cSetting_pymol_space_max_green);
2540       blue_max = SettingGetGlobal_f(G, cSetting_pymol_space_max_blue);
2541       min_factor = SettingGetGlobal_f(G, cSetting_pymol_space_min_factor);
2542 
2543       if(I->BigEndian)
2544         mask = 0x000000FF;
2545       else
2546         mask = 0xFF000000;
2547 
2548       I->ColorTable.resize(512 * 512);
2549 
2550       p = I->ColorTable.data();
2551       for(x = 0; x < width; x++)
2552         for(y = 0; y < height; y++)
2553           *(p++) = mask;
2554 
2555       for(y = 0; y < height; y++)
2556         for(x = 0; x < width; x++) {
2557           rc = r;
2558           gc = g;
2559           bc = b;
2560 
2561           if((r >= g) && (r >= b)) {
2562             if(rc > 255 * red_max) {
2563               rc = (unsigned int) (red_max * 255);
2564               bc = bc * rc / r;
2565               gc = gc * rc / r;
2566             }
2567           } else if((g >= b) && (g >= r)) {
2568             if(gc > 255 * green_max) {
2569               gc = (unsigned int) (green_max * 255);
2570               bc = bc * gc / g;
2571               rc = rc * gc / g;
2572             }
2573           } else if((b >= g) && (b >= r)) {
2574             if(bc > 255 * blue_max) {
2575               bc = (unsigned int) (blue_max * 255);
2576               gc = gc * bc / b;
2577               rc = rc * bc / b;
2578             }
2579           }
2580 
2581           rf = (int) (min_factor * rc + 0.49999F);
2582           gf = (int) (min_factor * gc + 0.49999F);
2583           bf = (int) (min_factor * bc + 0.49999F);
2584 
2585           if(rc < gf)
2586             rc = (int) gf;
2587           if(bc < gf)
2588             bc = (int) gf;
2589 
2590           if(rc < bf)
2591             rc = (int) bf;
2592           if(gc < bf)
2593             gc = (int) bf;
2594 
2595           if(gc < rf)
2596             gc = (int) rf;
2597           if(bc < rf)
2598             bc = (int) rf;
2599 
2600           if(rc > 255)
2601             rc = 255;
2602           if(bc > 255)
2603             bc = 255;
2604           if(gc > 255)
2605             gc = 255;
2606 
2607           pixel = I->ColorTable.data() + ((width) * y) + x;
2608           if(I->BigEndian) {
2609             *(pixel) = mask | (rc << 24) | (gc << 16) | (bc << 8);
2610           } else {
2611             *(pixel) = mask | (bc << 16) | (gc << 8) | rc;
2612           }
2613           b = b + 4;
2614           if(!(0xFF & b)) {
2615             b = 0;
2616             g = g + 4;
2617             if(!(0xFF & g)) {
2618               g = 0;
2619               r = r + 4;
2620             }
2621           }
2622         }
2623 
2624       if(!quiet) {
2625         PRINTFB(G, FB_Color, FB_Actions)
2626           " Color: defined table '%s'.\n", fname ENDFB(G);
2627       }
2628 
2629       ColorUpdateFromLut(G, -1);
2630       ExecutiveInvalidateRep(G, cKeywordAll, cRepAll, cRepInvColor);
2631       SceneChanged(G);
2632 
2633     } else {
2634       if(strlen(fname)) {
2635 
2636         auto image = MyPNGRead(fname);
2637         if(image) {
2638           std::tie(width, height) = image->getSize();
2639           if((width == 512) && (height == 512)) {
2640             auto imageSize = width * height;
2641             I->ColorTable.resize(imageSize);
2642             std::copy(image->pixels(), image->pixels() + imageSize, I->ColorTable.data());
2643 
2644             if(!quiet) {
2645               PRINTFB(G, FB_Color, FB_Actions)
2646                 " Color: loaded table '%s'.\n", fname ENDFB(G);
2647             }
2648 
2649             ColorUpdateFromLut(G, -1);
2650 
2651           } else {
2652             PRINTFB(G, FB_Color, FB_Errors)
2653               " ColorTableLoad-Error: invalid dimensions w x h  = %d x %d; should be 512 x 512.\n",
2654               width, height ENDFB(G);
2655 
2656             ok = false;
2657           }
2658         } else {
2659           PRINTFB(G, FB_Color, FB_Errors)
2660             " ColorTableLoad-Error: unable to load '%s'.\n", fname ENDFB(G);
2661           ok = false;
2662         }
2663       } else {
2664         PRINTFB(G, FB_Color, FB_Actions)
2665           " Color: purged table; colors unchanged.\n" ENDFB(G);
2666         I->ColorTable.clear();
2667       }
2668     }
2669   }
2670   if(ok) {
2671     ExecutiveInvalidateRep(G, cKeywordAll, cRepAll, cRepInvColor);
2672     SceneChanged(G);
2673   }
2674   return (ok);
2675 }
2676 
lookup_color(CColor * I,const float * in,float * out,int big_endian)2677 static void lookup_color(CColor * I, const float *in, float *out, int big_endian)
2678 {
2679   const float _1 = 1.0F;
2680   unsigned int *table = I->ColorTable.data();
2681   if(table) {
2682     unsigned int r, g, b, rr, gr, br;
2683     unsigned int ra, ga, ba;
2684     unsigned int rc[2][2][2], gc[2][2][2], bc[2][2][2];
2685     unsigned int *entry;
2686     int x, y, z;
2687     float fr, fg, fb, frm1x, fgm1, fbm1, rct, gct, bct;
2688     const float _2 = 2.0F, _0 = 0.0F, _05 = 0.5F, _04999 = 0.4999F;
2689     const float inv255 = 1.0F / 255.0F;
2690 
2691     r = ((int) (255 * in[0] + _05)) & 0xFF;
2692     g = ((int) (255 * in[1] + _05)) & 0xFF;
2693     b = ((int) (255 * in[2] + _05)) & 0xFF;
2694 
2695     rr = r & 0x3;
2696     gr = g & 0x3;
2697     br = b & 0x3;
2698 
2699     r = (r >> 2);
2700     g = (g >> 2);
2701     b = (b >> 2);
2702 
2703     /* now for a crude little trilinear */
2704 
2705     for(x = 0; x < 2; x++) {
2706       ra = r + x;
2707       if(ra > 63)
2708         ra = 63;
2709       for(y = 0; y < 2; y++) {
2710         ga = g + y;
2711         if(ga > 63)
2712           ga = 63;
2713         for(z = 0; z < 2; z++) {
2714           ba = b + z;
2715           if(ba > 63)
2716             ba = 63;
2717 
2718           entry = table + (ra << 12) + (ga << 6) + ba;
2719 
2720           if(big_endian) {
2721             rc[x][y][z] = 0xFF & ((*entry) >> 24);
2722             gc[x][y][z] = 0xFF & ((*entry) >> 16);
2723             bc[x][y][z] = 0xFF & ((*entry) >> 8);
2724           } else {
2725             rc[x][y][z] = 0xFF & ((*entry));
2726             gc[x][y][z] = 0xFF & ((*entry) >> 8);
2727             bc[x][y][z] = 0xFF & ((*entry) >> 16);
2728           }
2729         }
2730       }
2731     }
2732 
2733     frm1x = rr / 4.0F;
2734     fgm1 = gr / 4.0F;
2735     fbm1 = br / 4.0F;
2736 
2737     fr = 1.0F - frm1x;
2738     fg = 1.0F - fgm1;
2739     fb = 1.0F - fbm1;
2740 
2741     rct = _04999 +
2742       (fr * fg * fb * rc[0][0][0]) +
2743       (frm1x * fg * fb * rc[1][0][0]) +
2744       (fr * fgm1 * fb * rc[0][1][0]) +
2745       (fr * fg * fbm1 * rc[0][0][1]) +
2746       (frm1x * fgm1 * fb * rc[1][1][0]) +
2747       (fr * fgm1 * fbm1 * rc[0][1][1]) +
2748       (frm1x * fg * fbm1 * rc[1][0][1]) + (frm1x * fgm1 * fbm1 * rc[1][1][1]);
2749 
2750     gct = _04999 +
2751       (fr * fg * fb * gc[0][0][0]) +
2752       (frm1x * fg * fb * gc[1][0][0]) +
2753       (fr * fgm1 * fb * gc[0][1][0]) +
2754       (fr * fg * fbm1 * gc[0][0][1]) +
2755       (frm1x * fgm1 * fb * gc[1][1][0]) +
2756       (fr * fgm1 * fbm1 * gc[0][1][1]) +
2757       (frm1x * fg * fbm1 * gc[1][0][1]) + (frm1x * fgm1 * fbm1 * gc[1][1][1]);
2758 
2759     bct = _04999 +
2760       (fr * fg * fb * bc[0][0][0]) +
2761       (frm1x * fg * fb * bc[1][0][0]) +
2762       (fr * fgm1 * fb * bc[0][1][0]) +
2763       (fr * fg * fbm1 * bc[0][0][1]) +
2764       (frm1x * fgm1 * fb * bc[1][1][0]) +
2765       (fr * fgm1 * fbm1 * bc[0][1][1]) +
2766       (frm1x * fg * fbm1 * bc[1][0][1]) + (frm1x * fgm1 * fbm1 * bc[1][1][1]);
2767 
2768     if(r >= 63)
2769       rct += rr;
2770     if(g >= 63)
2771       gct += gr;
2772     if(b >= 63)
2773       bct += br;
2774 
2775     if(rct <= _2)
2776       rct = _0;                 /* make sure black is black */
2777     if(gct <= _2)
2778       gct = _0;
2779     if(bct <= _2)
2780       bct = _0;
2781 
2782     out[0] = rct * inv255;
2783     out[1] = gct * inv255;
2784     out[2] = bct * inv255;
2785   } else {
2786     out[0] = in[0];
2787     out[1] = in[1];
2788     out[2] = in[2];
2789   }
2790 
2791   if((I->Gamma != 1.0F) && (I->Gamma > R_SMALL4)) {
2792     float inv_gamma = 1.0F / I->Gamma;
2793     float inp = (out[0] + out[1] + out[2]) * (1 / 3.0F);
2794     if(inp >= R_SMALL4) {
2795       float sig = (float) (pow(inp, inv_gamma)) / inp;
2796       out[0] *= sig;
2797       out[1] *= sig;
2798       out[2] *= sig;
2799     }
2800   }
2801 
2802   if(out[0] > _1)
2803     out[0] = _1;
2804   if(out[1] > _1)
2805     out[1] = _1;
2806   if(out[2] > _1)
2807     out[2] = _1;
2808 
2809 }
2810 
2811 
2812 /*========================================================================*/
ColorUpdateFromLut(PyMOLGlobals * G,int index)2813 void ColorUpdateFromLut(PyMOLGlobals * G, int index)
2814 {
2815   int i;
2816   int once = false;
2817   CColor *I = G->Color;
2818   float *color, *new_color;
2819 
2820   I->LUTActive = (!I->ColorTable.empty() || (I->Gamma != 1.0F));
2821 
2822   i = index;
2823   if(index >= 0) {
2824     once = true;
2825   }
2826   for(i = 0; i < I->NColor; i++) {
2827     if(!once)
2828       index = i;
2829 
2830     if(index < I->NColor) {
2831       if(!I->LUTActive) {
2832         I->Color[index].LutColorFlag = false;
2833       } else if(!I->Color[index].Fixed) {
2834         color = I->Color[index].Color;
2835         new_color = I->Color[index].LutColor;
2836         lookup_color(I, color, new_color, I->BigEndian);
2837 
2838         PRINTFD(G, FB_Color)
2839           "%5.3f %5.3f %5.3f -> %5.3f %5.3f %5.3f\n",
2840           color[0], color[1], color[2], new_color[0], new_color[1], new_color[2]
2841           ENDFD;
2842 
2843         I->Color[index].LutColorFlag = true;
2844       }
2845     }
2846 
2847     if(once)
2848       break;
2849   }
2850 }
2851 
2852 
2853 /*========================================================================*/
ColorLookupColor(PyMOLGlobals * G,float * color)2854 int ColorLookupColor(PyMOLGlobals * G, float *color)
2855 {
2856   CColor *I = G->Color;
2857   if(I->LUTActive) {
2858     lookup_color(I, color, color, I->BigEndian);
2859     return true;
2860   } else {
2861     return false;
2862   }
2863 }
2864 
2865 
2866 /*========================================================================*/
ColorInit(PyMOLGlobals * G)2867 int ColorInit(PyMOLGlobals * G)
2868 {
2869   CColor *I = NULL;
2870 
2871   if ((G->Color = new CColor())) {
2872     I = G->Color;
2873     unsigned int test;
2874     unsigned char *testPtr;
2875 
2876     test = 0xFF000000;
2877     testPtr = (unsigned char *) &test;
2878     I->BigEndian = (*testPtr) & 0x01;
2879 
2880     I->Color = VLACalloc(ColorRec, 5500);
2881     I->Ext = VLACalloc(ExtRec, 2);
2882 
2883     ColorReset(G);              /* will alloc I->Idx and I->Lex */
2884     return 1;
2885   } else {
2886     return 0;
2887   }
2888 }
2889 
ColorUpdateFront(PyMOLGlobals * G,const float * back)2890 void ColorUpdateFront(PyMOLGlobals * G, const float *back)
2891 {
2892   CColor *I = G->Color;
2893   copy3f(back, I->Back);
2894   I->Front[0] = 1.0F - back[0];
2895   I->Front[1] = 1.0F - back[1];
2896   I->Front[2] = 1.0F - back[2];
2897   if(diff3f(I->Front, back) < 0.5F)
2898     zero3f(I->Front);
2899 }
2900 
ColorUpdateFrontFromSettings(PyMOLGlobals * G)2901 void ColorUpdateFrontFromSettings(PyMOLGlobals * G){
2902   int bg_gradient = SettingGet_b(G, NULL, NULL, cSetting_bg_gradient);
2903   const char * bg_image_filename = SettingGet_s(G, NULL, NULL, cSetting_bg_image_filename);
2904   short bg_image = bg_image_filename && bg_image_filename[0];
2905 
2906   if (!bg_gradient){
2907     if (!bg_image && !OrthoBackgroundDataIsSet(*G->Ortho)){
2908       const float *v = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting_bg_rgb));
2909       ColorUpdateFront(G, v);
2910     } else {
2911       float v[] = { 0.f, 0.f, 0.f };
2912       ColorUpdateFront(G, v);
2913     }
2914   } else {
2915     float vv[3];
2916     const float *v = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting_bg_rgb_bottom));
2917     const float *vb = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting_bg_rgb_top));
2918     average3f(v, vb, vv);
2919     ColorUpdateFront(G, vv);
2920   }
2921 }
2922 
2923 
2924 /*========================================================================*/
ColorGetSpecial(PyMOLGlobals * G,int index)2925 const float *ColorGetSpecial(PyMOLGlobals * G, int index)
2926 {
2927   if(index >= 0)
2928     return ColorGet(G, index);
2929   else {
2930     CColor *I = G->Color;
2931     I->RGBColor[0] = (float) index;
2932     I->RGBColor[1] = -1.0F;
2933     I->RGBColor[2] = -1.0F;
2934     return I->RGBColor;
2935   }
2936 }
2937 
ColorGet(PyMOLGlobals * G,int index)2938 const float *ColorGet(PyMOLGlobals * G, int index)
2939 {
2940   CColor *I = G->Color;
2941   const float *ptr;
2942   if((index >= 0) && (index < I->NColor)) {
2943     if(I->Color[index].LutColorFlag && SettingGetGlobal_b(G, cSetting_clamp_colors))
2944       ptr = I->Color[index].LutColor;
2945     else
2946       ptr = I->Color[index].Color;
2947     return (ptr);
2948   } else if((index & cColor_TRGB_Mask) == cColor_TRGB_Bits) {   /* a 24-bit RGB color */
2949     I->RGBColor[0] = ((index & 0x00FF0000) >> 16) / 255.0F;
2950     I->RGBColor[1] = ((index & 0x0000FF00) >> 8) / 255.0F;
2951     I->RGBColor[2] = ((index & 0x000000FF)) / 255.0F;
2952     if(I->LUTActive)
2953       lookup_color(I, I->RGBColor, I->RGBColor, I->BigEndian);
2954     return I->RGBColor;
2955   } else if(index == cColorFront) {
2956     return I->Front;
2957   } else if(index == cColorBack) {
2958     return I->Back;
2959   } else {
2960     /* invalid color id, then simply return white */
2961     return (I->Color[0].Color);
2962   }
2963 }
2964 
ColorGetRaw(PyMOLGlobals * G,int index)2965 const float *ColorGetRaw(PyMOLGlobals * G, int index)
2966 {
2967   CColor *I = G->Color;
2968   const float *ptr;
2969   if((index >= 0) && (index < I->NColor)) {
2970     ptr = I->Color[index].Color;
2971     return (ptr);
2972   } else if((index & cColor_TRGB_Mask) == cColor_TRGB_Bits) {   /* a 24-bit RGB color */
2973     I->RGBColor[0] = ((index & 0x00FF0000) >> 16) / 255.0F;
2974     I->RGBColor[1] = ((index & 0x0000FF00) >> 8) / 255.0F;
2975     I->RGBColor[2] = ((index & 0x000000FF)) / 255.0F;
2976     return I->RGBColor;
2977   } else {
2978     /* invalid color id, then simply return white */
2979     return (I->Color[0].Color);
2980   }
2981 }
2982 
ColorGetEncoded(PyMOLGlobals * G,int index,float * color)2983 int ColorGetEncoded(PyMOLGlobals * G, int index, float *color)
2984 {
2985   CColor *I = G->Color;
2986   float *ptr;
2987   if((index >= 0) && (index < I->NColor)) {
2988     if(I->Color[index].LutColorFlag && SettingGetGlobal_b(G, cSetting_clamp_colors))
2989       ptr = I->Color[index].LutColor;
2990     else
2991       ptr = I->Color[index].Color;
2992     copy3f(ptr, color);
2993   } else if((index & cColor_TRGB_Mask) == cColor_TRGB_Bits) {   /* a 24-bit RGB color */
2994     float rgb_color[3];
2995     rgb_color[0] = ((index & 0x00FF0000) >> 16) / 255.0F;
2996     rgb_color[1] = ((index & 0x0000FF00) >> 8) / 255.0F;
2997     rgb_color[2] = ((index & 0x000000FF)) / 255.0F;
2998     if(I->LUTActive)
2999       lookup_color(I, rgb_color, rgb_color, I->BigEndian);
3000     copy3f(rgb_color, color);
3001   } else if(index <= cColorExtCutoff) {
3002     color[0] = (float) index;
3003     color[1] = 0.0F;
3004     color[2] = 0.0F;
3005   } else if(index == cColorFront) {
3006     copy3f(I->Front, color);
3007   } else if(index == cColorBack) {
3008     copy3f(I->Back, color);
3009   } else {
3010     color[0] = 1.0F;
3011     color[1] = 1.0F;
3012     color[2] = 1.0F;
3013     /* invalid color id, then simply return white */
3014     return 0;
3015   }
3016   return 1;
3017 }
3018 
Color3fToInt(PyMOLGlobals * G,const float * rgb)3019 int Color3fToInt(PyMOLGlobals * G, const float *rgb){
3020   unsigned int rc, gc, bc;
3021   rc = pymol_roundf(rgb[0] * 255.);
3022   gc = pymol_roundf(rgb[1] * 255.);
3023   bc = pymol_roundf(rgb[2] * 255.);
3024   return ( ( cColor_TRGB_Bits & 0xFF000000) |
3025 	   ( ( rc << 16 ) & 0x00FF0000) |
3026 	   ( ( gc << 8 ) & 0x0000FF00) |
3027 	   ( ( bc & 0x000000FF ) ) );
3028 }
3029