fltk  1.3.5-source
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X.
  Fossies Dox: fltk-1.3.5-source.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

fl_color.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Color functions for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file. If this
10 // file is missing or damaged, see the license at:
11 //
12 // http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 // http://www.fltk.org/str.php
17 //
18 
24 // Implementation of fl_color(i), fl_color(r,g,b).
25 
26 #ifdef WIN32
27 # include "fl_color_win32.cxx"
28 #elif defined(__APPLE__)
29 # include "fl_color_mac.cxx"
30 #else
31 
32 // Also code to look at the X visual and figure out the best way to turn
33 // a color into a pixel value.
34 
35 // SGI compiler seems to have problems with unsigned char arguments
36 // being used to index arrays. So I always copy them to an integer
37 // before use.
38 
39 # include "Fl_XColor.H"
40 # include <FL/Fl.H>
41 # include <FL/x.H>
42 # include <FL/fl_draw.H>
43 
45 // figure_out_visual() calculates masks & shifts for generating
46 // pixels in true-color visuals:
47 
57 static uchar beenhere;
58 
59 static void figure_out_visual() {
60  beenhere = 1;
61  if (!fl_visual->red_mask || !fl_visual->green_mask || !fl_visual->blue_mask){
62 # if USE_COLORMAP
63  fl_redmask = 0;
64  return;
65 # else
66  Fl::fatal("Requires true color visual");
67 # endif
68  }
69 
70  // get the bit masks into a more useful form:
71  int i,j,m;
72 
73  for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->red_mask & m) break;
74  for (j = i; m; j++, m<<=1) if (!(fl_visual->red_mask & m)) break;
75  fl_redshift = j-8;
76  fl_redmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
77 
78  for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->green_mask & m) break;
79  for (j = i; m; j++, m<<=1) if (!(fl_visual->green_mask & m)) break;
80  fl_greenshift = j-8;
81  fl_greenmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
82 
83  for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->blue_mask & m) break;
84  for (j = i; m; j++, m<<=1) if (!(fl_visual->blue_mask & m)) break;
85  fl_blueshift = j-8;
86  fl_bluemask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
87 
88  i = fl_redshift;
89  if (fl_greenshift < i) i = fl_greenshift;
90  if (fl_blueshift < i) i = fl_blueshift;
91  if (i < 0) {
92  fl_extrashift = -i;
93  fl_redshift -= i; fl_greenshift -= i; fl_blueshift -= i;
94  } else
95  fl_extrashift = 0;
96 
97 }
98 
99 static unsigned fl_cmap[256] = {
100 #include "fl_cmap.h" // this is a file produced by "cmap.cxx":
101 };
102 
103 # if HAVE_OVERLAY
104 
105 Fl_XColor fl_xmap[2][256];
108 Colormap fl_overlay_colormap;
109 XVisualInfo* fl_overlay_visual;
110 ulong fl_transparent_pixel;
111 # else
112 
115 # define fl_overlay 0
116 # endif
117 
119  if (i & 0xffffff00) {
120  unsigned rgb = (unsigned)i;
121  fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
122  } else {
124  if(!fl_gc) return; // don't get a default gc if current window is not yet created/valid
125  XSetForeground(fl_display, fl_gc, fl_xpixel(i));
126  }
127 }
128 
131  if(!fl_gc) return; // don't get a default gc if current window is not yet created/valid
132  XSetForeground(fl_display, fl_gc, fl_xpixel(r,g,b));
133 }
134 
137 // Get an rgb color. This is easy for a truecolor visual. For
139 // colormapped it picks the closest color out of the cube in the
140 // fltk colormap. However if this color cube entry has been
141 // requested before, you will get the earlier requested color, and
142 // even this may be approximated if the X colormap was full.
143 
151  if (!beenhere) figure_out_visual();
152 # if USE_COLORMAP
153  if (!fl_redmask) {
154  // find closest entry in the colormap:
155  Fl_Color i =
157  Fl_XColor &xmap = fl_xmap[fl_overlay][i];
158  if (xmap.mapped) return xmap.pixel;
159  // if not black or white, change the entry to be an exact match:
160  if (i != FL_COLOR_CUBE && i != 0xFF)
161  fl_cmap[i] = (r<<24)|(g<<16)|(b<<8);
162  return fl_xpixel(i); // allocate an X color
163  }
164 # endif
165  return
166  (((r&fl_redmask) << fl_redshift)+
169  ) >> fl_extrashift;
170 }
171 
173 // Get a color out of the fltk colormap. Again for truecolor
174 // visuals this is easy. For colormap this actually tries to allocate
175 // an X color, and does a least-squares match to find the closest
176 // color if X cannot allocate that color.
177 
178 // calculate what color is actually on the screen for a mask:
179 static inline uchar realcolor(uchar color, uchar mask) {
180 # if 0
181  // accurate version if the display has linear gamma, but fl_draw_image
182  // works better with the simpler version on most screens...
183  uchar m = mask;
184  uchar result = color&m;
185  for (;;) {
186  while (m&mask) {m>>=1; color>>=1;}
187  if (!m) break;
188  mask = m;
189  result |= color&m;
190  }
191  return result;
192 # else
193  return (color&mask) | ( (~mask)&(mask>>1) );
194 # endif
195 }
196 
204  if (i & 0xffffff00) {
205  return fl_xpixel((i >> 24) & 255, (i >> 16) & 255, (i >> 8) & 255);
206  }
207 
208  Fl_XColor &xmap = fl_xmap[fl_overlay][i];
209  if (xmap.mapped) return xmap.pixel;
210 
211  if (!beenhere) figure_out_visual();
212 
213  uchar r,g,b;
214  {unsigned c = fl_cmap[i]; r=uchar(c>>24); g=uchar(c>>16); b=uchar(c>>8);}
215 
216 # if USE_COLORMAP
217  Colormap colormap = fl_colormap;
218 # if HAVE_OVERLAY
219  if (fl_overlay) colormap = fl_overlay_colormap; else
220 # endif
221  if (fl_redmask) {
222 # endif
223  // return color for a truecolor visual:
224  xmap.mapped = 2; // 2 prevents XFreeColor from being called
225  xmap.r = realcolor(r, fl_redmask);
226  xmap.g = realcolor(g, fl_greenmask);
227  xmap.b = realcolor(b, fl_bluemask);
228  return xmap.pixel =
229  (((r&fl_redmask) << fl_redshift)+
232  ) >> fl_extrashift;
233 # if USE_COLORMAP
234  }
235 # if HAVE_OVERLAY
236  static XColor* ac[2];
237  XColor*& allcolors = ac[fl_overlay];
238  static int nc[2];
239  int& numcolors = nc[fl_overlay];
240 # else
241  static XColor *allcolors;
242  static int numcolors;
243 # endif
244 
245  // I don't try to allocate colors with XAllocColor once it fails
246  // with any color. It is possible that it will work, since a color
247  // may have been freed, but some servers are extremely slow and this
248  // avoids one round trip:
249  if (!numcolors) { // don't try after a failure
250  XColor xcol;
251  xcol.red = r<<8; xcol.green = g<<8; xcol.blue = b<<8;
252  if (XAllocColor(fl_display, colormap, &xcol)) {
253  xmap.mapped = 1;
254  xmap.r = xcol.red>>8;
255  xmap.g = xcol.green>>8;
256  xmap.b = xcol.blue>>8;
257  return xmap.pixel = xcol.pixel;
258  }
259 
260  // I only read the colormap once. Again this is due to the slowness
261  // of round-trips to the X server, even though other programs may alter
262  // the colormap after this and make decisions here wrong.
263 # if HAVE_OVERLAY
264  if (fl_overlay) numcolors = fl_overlay_visual->colormap_size; else
265 # endif
266  numcolors = fl_visual->colormap_size;
267  if (!allcolors) allcolors = new XColor[numcolors];
268  for (int p = numcolors; p--;) allcolors[p].pixel = p;
269  XQueryColors(fl_display, colormap, allcolors, numcolors);
270  }
271 
272  // find least-squares match:
273  int mindist = 0x7FFFFFFF;
274  unsigned int bestmatch = 0;
275  for (unsigned int n = numcolors; n--;) {
276 # if HAVE_OVERLAY
277  if (fl_overlay && n == fl_transparent_pixel) continue;
278 # endif
279  XColor &a = allcolors[n];
280  int d, t;
281  t = int(r)-int(a.red>>8); d = t*t;
282  t = int(g)-int(a.green>>8); d += t*t;
283  t = int(b)-int(a.blue>>8); d += t*t;
284  if (d <= mindist) {bestmatch = n; mindist = d;}
285  }
286  XColor &p = allcolors[bestmatch];
287 
288  // It appears to "work" to not call this XAllocColor, which will
289  // avoid another round-trip to the server. But then X does not
290  // know that this program "owns" this value, and can (and will)
291  // change it when the program that did allocate it exits:
292  if (XAllocColor(fl_display, colormap, &p)) {
293  xmap.mapped = 1;
294  xmap.pixel = p.pixel;
295  } else {
296  // However, if that XAllocColor fails, I have to give up and
297  // assume the pixel is ok for the duration of the program. This
298  // is due to bugs (?) in the Solaris X and some X terminals
299  // where XAllocColor *always* fails when the colormap is full,
300  // even if we ask for a color already in it...
301  xmap.mapped = 2; // 2 prevents XFreeColor from being called
302  xmap.pixel = bestmatch;
303  }
304  xmap.r = p.red>>8;
305  xmap.g = p.green>>8;
306  xmap.b = p.blue>>8;
307  return xmap.pixel;
308 # endif
309 }
310 
316 void Fl::free_color(Fl_Color i, int overlay) {
317 # if HAVE_OVERLAY
318 # else
319  if (overlay) return;
320 # endif
321  if (fl_xmap[overlay][i].mapped) {
322 # if USE_COLORMAP
323 # if HAVE_OVERLAY
324  Colormap colormap = overlay ? fl_overlay_colormap : fl_colormap;
325 # else
326  Colormap colormap = fl_colormap;
327 # endif
328  if (fl_xmap[overlay][i].mapped == 1)
329  XFreeColors(fl_display, colormap, &(fl_xmap[overlay][i].pixel), 1, 0);
330 # endif
331  fl_xmap[overlay][i].mapped = 0;
332  }
333 }
334 
340 void Fl::set_color(Fl_Color i, unsigned c) {
341  if (fl_cmap[i] != c) {
342  free_color(i,0);
343 # if HAVE_OVERLAY
344  free_color(i,1);
345 # endif
346  fl_cmap[i] = c;
347  }
348 }
349 
350 #endif // end of X-specific code
351 
359 unsigned Fl::get_color(Fl_Color i) {
360  if (i & 0xffffff00) return (i);
361  else return fl_cmap[i];
362 }
368 void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue) {
369  Fl::set_color((Fl_Color)(i & 255),
370  ((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8));
371 }
380 void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) {
381  unsigned c;
382 
383  if (i & 0xffffff00) c = (unsigned)i;
384  else c = fl_cmap[i];
385 
386  red = uchar(c>>24);
387  green = uchar(c>>16);
388  blue = uchar(c>>8);
389 }
390 
402 Fl_Color fl_color_average(Fl_Color color1, Fl_Color color2, float weight) {
403  unsigned rgb1;
404  unsigned rgb2;
405  uchar r, g, b;
406 
407  if (color1 & 0xffffff00) rgb1 = color1;
408  else rgb1 = fl_cmap[color1 & 255];
409 
410  if (color2 & 0xffffff00) rgb2 = color2;
411  else rgb2 = fl_cmap[color2 & 255];
412 
413  r = (uchar)(((uchar)(rgb1>>24))*weight + ((uchar)(rgb2>>24))*(1-weight));
414  g = (uchar)(((uchar)(rgb1>>16))*weight + ((uchar)(rgb2>>16))*(1-weight));
415  b = (uchar)(((uchar)(rgb1>>8))*weight + ((uchar)(rgb2>>8))*(1-weight));
416 
417  return fl_rgb_color(r, g, b);
418 }
419 
424  return fl_color_average(c, FL_GRAY, .33f);
425 }
426 
436  unsigned c1, c2; // RGB colors
437  int l1, l2; // Luminosities
438 
439 
440  // Get the RGB values for each color...
441  if (fg & 0xffffff00) c1 = (unsigned)fg;
442  else c1 = fl_cmap[fg];
443 
444  if (bg & 0xffffff00) c2 = (unsigned)bg;
445  else c2 = fl_cmap[bg];
446 
447  // Compute the luminosity...
448  l1 = ((c1 >> 24) * 30 + ((c1 >> 16) & 255) * 59 + ((c1 >> 8) & 255) * 11) / 100;
449  l2 = ((c2 >> 24) * 30 + ((c2 >> 16) & 255) * 59 + ((c2 >> 8) & 255) * 11) / 100;
450 
451  // Compare and return the contrasting color...
452  if ((l1 - l2) > 99) return fg;
453  else if ((l2 - l1) > 99) return fg;
454  else if (l2 > 127) return FL_BLACK;
455  else return FL_WHITE;
456 }
460 //
461 // End of "$Id$".
462 //
fl_cmap
static unsigned fl_cmap[256]
Definition: fl_color.cxx:99
Fl.H
fl_blueshift
int fl_blueshift
Definition: fl_color.cxx:54
fl_greenmask
uchar fl_greenmask
Definition: fl_color.cxx:49
Fl_Graphics_Driver::color
Fl_Color color()
see fl_color(void).
Definition: Fl_Device.H:402
realcolor
static uchar realcolor(uchar color, uchar mask)
Definition: fl_color.cxx:179
Fl_Color
unsigned int Fl_Color
Definition: Enumerations.H:934
fl_cmap.h
Fl_XColor::pixel
unsigned long pixel
Definition: Fl_XColor.H:27
Fl::fatal
static void(* fatal)(const char *,...)
Definition: Fl.H:530
fl_rgb_color
Fl_Color fl_rgb_color(uchar r, uchar g, uchar b)
Definition: Enumerations.H:997
FL_WHITE
const Fl_Color FL_WHITE
Definition: Enumerations.H:971
Fl_XColor::r
unsigned char r
Definition: Fl_XColor.H:25
x.H
Fl_XColor::b
unsigned char b
Definition: Fl_XColor.H:25
fl_visual
XVisualInfo * fl_visual
Definition: Fl_x.cxx:317
fl_contrast
Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg)
Definition: fl_color.cxx:435
fl_redshift
int fl_redshift
Definition: fl_color.cxx:52
Fl_XColor::g
unsigned char g
Definition: Fl_XColor.H:25
b
long b
Definition: jpegint.h:397
FL_BLACK
const Fl_Color FL_BLACK
Definition: Enumerations.H:956
fl_extrashift
int fl_extrashift
Definition: fl_color.cxx:55
fl_color_mac.cxx
fl_colormap
Colormap fl_colormap
Definition: Fl_x.cxx:318
p
static menustate * p
Definition: Fl_Menu.cxx:606
FL_NUM_RED
#define FL_NUM_RED
Definition: Enumerations.H:980
FL_COLOR_CUBE
#define FL_COLOR_CUBE
Definition: Enumerations.H:979
Fl::get_color
static unsigned get_color(Fl_Color i)
Definition: fl_color.cxx:359
FL_NUM_GREEN
#define FL_NUM_GREEN
Definition: Enumerations.H:981
fl_color_win32.cxx
fl_draw.H
utility header to pull drawing functions together
fl_redmask
uchar fl_redmask
Definition: fl_color.cxx:48
fl_inactive
Fl_Color fl_inactive(Fl_Color c)
Definition: fl_color.cxx:423
fl_greenshift
int fl_greenshift
Definition: fl_color.cxx:53
Fl_XColor
Definition: Fl_XColor.H:24
ulong
unsigned long ulong
Definition: fl_types.h:32
fl_display
FL_EXPORT HINSTANCE fl_display
END TIMERS.
Definition: Fl_win32.cxx:2147
FL_NUM_BLUE
#define FL_NUM_BLUE
Definition: Enumerations.H:982
Fl::free_color
static void free_color(Fl_Color i, int overlay=0)
Definition: fl_color.cxx:316
fl_xpixel
ulong fl_xpixel(uchar r, uchar g, uchar b)
Definition: fl_color.cxx:150
color
void color(int n)
Definition: gl2opengl.h:29
fl_color_cube
Fl_Color fl_color_cube(int r, int g, int b)
Definition: Enumerations.H:1032
fl_bluemask
uchar fl_bluemask
Definition: fl_color.cxx:50
Fl::set_color
static void set_color(Fl_Color, uchar, uchar, uchar)
Definition: fl_color.cxx:368
fl_gc
CGContextRef fl_gc
Definition: Fl_win32.cxx:2568
FL_GRAY
#define FL_GRAY
Definition: Enumerations.H:978
f
Fl_Box_Draw_F * f
Definition: fl_boxtype.cxx:285
fl_overlay
#define fl_overlay
Definition: fl_color.cxx:115
fl_xmap
Fl_XColor fl_xmap[1][256]
Definition: fl_color.cxx:113
Fl_Graphics_Driver::fl_color
friend void fl_color(Fl_Color c)
Definition: fl_draw.H:52
fl_color_average
Fl_Color fl_color_average(Fl_Color color1, Fl_Color color2, float weight)
Definition: fl_color.cxx:402
uchar
unsigned char uchar
Definition: fl_types.h:30
figure_out_visual
static void figure_out_visual()
Definition: fl_color.cxx:59
Fl_XColor::mapped
unsigned char mapped
Definition: Fl_XColor.H:26
beenhere
static uchar beenhere
Definition: fl_color.cxx:57
Fl_XColor.H