summaryrefslogtreecommitdiff
path: root/src/cfg_gfx
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2016-01-24 16:22:50 +0000
committerMatthias Melcher <fltk@matthiasm.com>2016-01-24 16:22:50 +0000
commit60ec452d043e44bcbb05860381e2077a3b56b09c (patch)
tree1eaf13dc05a6da6a53a949fc1a66df6030cab943 /src/cfg_gfx
parent49cf30286b505e15ca0496605efca5546c7bbf85 (diff)
Reorganizing color drawing code.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11045 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/cfg_gfx')
-rw-r--r--src/cfg_gfx/gdi.H6
-rw-r--r--src/cfg_gfx/gdi_color.cxx245
-rw-r--r--src/cfg_gfx/opengl.H6
-rw-r--r--src/cfg_gfx/opengl_color.cxx70
-rw-r--r--src/cfg_gfx/opengl_rect.cxx9
-rw-r--r--src/cfg_gfx/quartz.H7
-rw-r--r--src/cfg_gfx/quartz_color.cxx80
-rw-r--r--src/cfg_gfx/xlib.H3
-rw-r--r--src/cfg_gfx/xlib_color.cxx351
9 files changed, 763 insertions, 14 deletions
diff --git a/src/cfg_gfx/gdi.H b/src/cfg_gfx/gdi.H
index 5fe4ca89b..1c70e2277 100644
--- a/src/cfg_gfx/gdi.H
+++ b/src/cfg_gfx/gdi.H
@@ -34,6 +34,9 @@
This class is implemented only on the MSWindows platform.
*/
class FL_EXPORT Fl_GDI_Graphics_Driver : public Fl_Graphics_Driver {
+protected:
+ int numcount;
+ int counts[20];
public:
static const char *class_id;
const char *class_name() {return class_id;};
@@ -101,6 +104,9 @@ protected:
void pie(int x, int y, int w, int h, double a1, double a2);
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
void line_style(int style, int width=0, char* dashes=0);
+ // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
+ void color(Fl_Color c);
+ void color(uchar r, uchar g, uchar b);
};
diff --git a/src/cfg_gfx/gdi_color.cxx b/src/cfg_gfx/gdi_color.cxx
new file mode 100644
index 000000000..624546f39
--- /dev/null
+++ b/src/cfg_gfx/gdi_color.cxx
@@ -0,0 +1,245 @@
+//
+// "$Id$"
+//
+// MSWidnows' GDI color functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+// The fltk "colormap". This allows ui colors to be stored in 8-bit
+// locations, and provides a level of indirection so that global color
+// changes can be made. Not to be confused with the X colormap, which
+// I try to hide completely.
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+// FIXME: all the global functions in this file should probably be protected
+// members of the driver class. Starting with 1.4 we will allow multiple drivers
+// to co-exist, creating conflicts with multipe mapping.
+
+// FIXME: maybe we can forget about color mapping and assume RGB?
+
+static unsigned fl_cmap[256] = {
+#include "fl_cmap.h" // this is a file produced by "cmap.cxx":
+};
+
+// Translations to win32 data structures:
+Fl_XMap fl_xmap[256];
+
+Fl_XMap* fl_current_xmap;
+
+HPALETTE fl_palette;
+static HGDIOBJ tmppen=0;
+static HPEN savepen=0;
+
+void fl_cleanup_pens(void) {
+ for (int i=0; i<256; i++) {
+ if (fl_xmap[i].pen) DeleteObject(fl_xmap[i].pen);
+ }
+}
+
+void fl_save_pen(void) {
+ if(!tmppen) tmppen = CreatePen(PS_SOLID, 1, 0);
+ savepen = (HPEN)SelectObject(fl_gc, tmppen);
+}
+
+void fl_restore_pen(void) {
+ if (savepen) SelectObject(fl_gc, savepen);
+ DeleteObject(tmppen);
+ tmppen = 0;
+ savepen = 0;
+}
+
+static void clear_xmap(Fl_XMap& xmap) {
+ if (xmap.pen) {
+ HGDIOBJ tmppen = GetStockObject(BLACK_PEN);
+ HGDIOBJ oldpen = SelectObject(fl_gc, tmppen); // Push out the current pen of the gc
+ if(oldpen != xmap.pen) SelectObject(fl_gc, oldpen); // Put it back if it is not the one we are about to delete
+ DeleteObject((HGDIOBJ)(xmap.pen));
+ xmap.pen = 0;
+ xmap.brush = -1;
+ }
+}
+
+static void set_xmap(Fl_XMap& xmap, COLORREF c) {
+ xmap.rgb = c;
+ if (xmap.pen) {
+ HGDIOBJ oldpen = SelectObject(fl_gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one
+ if (oldpen != xmap.pen)SelectObject(fl_gc,oldpen); // if old one not xmap.pen, need to put it back
+ DeleteObject(xmap.pen); // delete pen
+ }
+ xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb); // get a pen into xmap.pen
+ xmap.brush = -1;
+}
+
+void Fl_GDI_Graphics_Driver::color(Fl_Color i) {
+ if (i & 0xffffff00) {
+ unsigned rgb = (unsigned)i;
+ fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
+ } else {
+ Fl_Graphics_Driver::color(i);
+ Fl_XMap &xmap = fl_xmap[i];
+ if (!xmap.pen) {
+#if USE_COLORMAP
+ if (fl_palette) {
+ set_xmap(xmap, PALETTEINDEX(i));
+ } else {
+#endif
+ unsigned c = fl_cmap[i];
+ set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)));
+#if USE_COLORMAP
+ }
+#endif
+ }
+ fl_current_xmap = &xmap;
+ SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
+ }
+}
+
+void Fl_GDI_Graphics_Driver::color(uchar r, uchar g, uchar b) {
+ static Fl_XMap xmap;
+ COLORREF c = RGB(r,g,b);
+ Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
+ if (!xmap.pen || c != xmap.rgb) {
+ clear_xmap(xmap);
+ set_xmap(xmap, c);
+ }
+ fl_current_xmap = &xmap;
+ SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
+}
+
+HBRUSH fl_brush() {
+ return fl_brush_action(0);
+}
+
+HBRUSH fl_brush_action(int action) {
+ Fl_XMap *xmap = fl_current_xmap;
+ // Wonko: we use some statistics to cache only a limited number
+ // of brushes:
+#define FL_N_BRUSH 16
+ static struct Fl_Brush {
+ HBRUSH brush;
+ unsigned short usage;
+ Fl_XMap* backref;
+ } brushes[FL_N_BRUSH];
+
+ if (action) {
+ SelectObject(fl_gc, GetStockObject(BLACK_BRUSH)); // Load stock object
+ for (int i=0; i<FL_N_BRUSH; i++) {
+ if (brushes[i].brush)
+ DeleteObject(brushes[i].brush); // delete all brushes in array
+ }
+ return NULL;
+ }
+
+ int i = xmap->brush; // find the associated brush
+ if (i != -1) { // if the brush was allready allocated
+ if (brushes[i].brush == NULL) goto CREATE_BRUSH;
+ if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic
+ for (int j=0; j<FL_N_BRUSH; j++) {
+ if (brushes[j].usage>16000)
+ brushes[j].usage -= 16000;
+ else
+ brushes[j].usage = 0;
+ }
+ }
+ return brushes[i].brush;
+ } else {
+ int umin = 32000, imin = 0;
+ for (i=0; i<FL_N_BRUSH; i++) {
+ if (brushes[i].brush == NULL) goto CREATE_BRUSH;
+ if (brushes[i].usage<umin) {
+ umin = brushes[i].usage;
+ imin = i;
+ }
+ }
+ i = imin;
+ HGDIOBJ tmpbrush = GetStockObject(BLACK_BRUSH); // get a stock brush
+ HGDIOBJ oldbrush = SelectObject(fl_gc,tmpbrush); // load in into current context
+ if (oldbrush != brushes[i].brush) SelectObject(fl_gc,oldbrush); // reload old one
+ DeleteObject(brushes[i].brush); // delete the one in list
+ brushes[i].brush = NULL;
+ brushes[i].backref->brush = -1;
+ }
+CREATE_BRUSH:
+ brushes[i].brush = CreateSolidBrush(xmap->rgb);
+ brushes[i].usage = 0;
+ brushes[i].backref = xmap;
+ xmap->brush = i;
+ return brushes[i].brush;
+}
+
+void Fl::free_color(Fl_Color i, int overlay) {
+ if (overlay) return; // do something about GL overlay?
+ clear_xmap(fl_xmap[i]);
+}
+
+void Fl::set_color(Fl_Color i, unsigned c) {
+ if (fl_cmap[i] != c) {
+ clear_xmap(fl_xmap[i]);
+ fl_cmap[i] = c;
+ }
+}
+
+#if USE_COLORMAP
+
+// 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary
+// Thanks to Michael Sweet @ Easy Software Products for this
+
+HPALETTE
+fl_select_palette(void)
+{
+ static char beenhere;
+ if (!beenhere) {
+ beenhere = 1;
+
+ //if (GetDeviceCaps(fl_gc, BITSPIXEL) > 8) return NULL;
+ int nColors = GetDeviceCaps(fl_gc, SIZEPALETTE);
+ if (nColors <= 0 || nColors > 256) return NULL;
+ // this will try to work on < 256 color screens, but will probably
+ // come out quite badly.
+
+ // I lamely try to get this variable-sized object allocated on stack:
+ ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1];
+ LOGPALETTE *pPal = (LOGPALETTE*)foo;
+
+ pPal->palVersion = 0x300;
+ pPal->palNumEntries = nColors;
+
+ // Build 256 colors from the standard FLTK colormap...
+
+ for (int i = 0; i < nColors; i ++) {
+ pPal->palPalEntry[i].peRed = (fl_cmap[i] >> 24) & 255;
+ pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255;
+ pPal->palPalEntry[i].peBlue = (fl_cmap[i] >> 8) & 255;
+ pPal->palPalEntry[i].peFlags = 0;
+ };
+
+ // Create the palette:
+ fl_palette = CreatePalette(pPal);
+ }
+ if (fl_palette) {
+ SelectPalette(fl_gc, fl_palette, FALSE);
+ RealizePalette(fl_gc);
+ }
+ return fl_palette;
+}
+
+#endif
+
+//
+// End of "$Id$".
+//
diff --git a/src/cfg_gfx/opengl.H b/src/cfg_gfx/opengl.H
index b8dd2bb86..8987e9e37 100644
--- a/src/cfg_gfx/opengl.H
+++ b/src/cfg_gfx/opengl.H
@@ -36,9 +36,6 @@ public:
static const char *class_id;
const char *class_name() {return class_id;};
void draw(const char* str, int n, int x, int y);
- void color(Fl_Color c);
- void color(uchar r, uchar g, uchar b);
-
// --- line and polygon drawing with integer coordinates
void point(int x, int y);
void rect(int x, int y, int w, int h);
@@ -85,6 +82,9 @@ public:
void pie(int x, int y, int w, int h, double a1, double a2);
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
void line_style(int style, int width=0, char* dashes=0);
+ // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
+ void color(Fl_Color c);
+ void color(uchar r, uchar g, uchar b);
};
diff --git a/src/cfg_gfx/opengl_color.cxx b/src/cfg_gfx/opengl_color.cxx
new file mode 100644
index 000000000..9413be75e
--- /dev/null
+++ b/src/cfg_gfx/opengl_color.cxx
@@ -0,0 +1,70 @@
+//
+// "$Id$"
+//
+// Color functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+/**
+ \file fl_color.cxx
+ \brief Color handling
+*/
+
+#include "opengl.H"
+#include <FL/gl.h>
+
+// Implementation of fl_color(i), fl_color(r,g,b).
+
+void Fl_OpenGL_Graphics_Driver::color(Fl_Color i) {
+ // FIXME: do we need the code below?
+ /*
+#if HAVE_GL_OVERLAY
+#if defined(WIN32)
+ if (fl_overlay && fl_overlay_depth) {
+ if (fl_overlay_depth < 8) {
+ // only black & white produce the expected colors. This could
+ // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx
+ int size = 1<<fl_overlay_depth;
+ if (!i) glIndexi(size-2);
+ else if (i >= size-2) glIndexi(size-1);
+ else glIndexi(i);
+ } else {
+ glIndexi(i ? i : FL_GRAY_RAMP);
+ }
+ return;
+ }
+#else
+ if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return;}
+#endif
+#endif
+*/
+ if (i & 0xffffff00) {
+ unsigned rgb = (unsigned)i;
+ fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
+ } else {
+ Fl_Graphics_Driver::color(i);
+ uchar red, green, blue;
+ Fl::get_color(i, red, green, blue);
+ glColor3ub(red, green, blue);
+ }
+}
+
+void Fl_OpenGL_Graphics_Driver::color(uchar r,uchar g,uchar b) {
+ Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
+ glColor3ub(r,g,b);
+}
+
+//
+// End of "$Id$".
+//
diff --git a/src/cfg_gfx/opengl_rect.cxx b/src/cfg_gfx/opengl_rect.cxx
index 8511d8c93..ff10474a1 100644
--- a/src/cfg_gfx/opengl_rect.cxx
+++ b/src/cfg_gfx/opengl_rect.cxx
@@ -32,15 +32,6 @@ void Fl_OpenGL_Graphics_Driver::draw(const char* str, int n, int x, int y) {
gl_draw(str, n, x, y);
}
-void Fl_OpenGL_Graphics_Driver::color(Fl_Color c) {
- gl_color(c);
-}
-
-void Fl_OpenGL_Graphics_Driver::color(uchar r, uchar g, uchar b) {
- unsigned int c = (r<<24)|(g<<16)|(b<<8);
- gl_color(c);
-}
-
// --- line and polygon drawing with integer coordinates
void Fl_OpenGL_Graphics_Driver::point(int x, int y) {
diff --git a/src/cfg_gfx/quartz.H b/src/cfg_gfx/quartz.H
index 33ef68086..a85f200c1 100644
--- a/src/cfg_gfx/quartz.H
+++ b/src/cfg_gfx/quartz.H
@@ -43,8 +43,8 @@ class FL_EXPORT Fl_Quartz_Graphics_Driver : public Fl_Graphics_Driver {
public:
static const char *class_id;
const char *class_name() {return class_id;};
- void color(Fl_Color c);
- void color(uchar r, uchar g, uchar b);
+// void color(Fl_Color c);
+// void color(uchar r, uchar g, uchar b);
void draw(const char* str, int n, int x, int y);
#ifdef __APPLE__
void draw(const char *str, int n, float x, float y);
@@ -111,6 +111,9 @@ protected:
void pie(int x, int y, int w, int h, double a1, double a2);
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
void line_style(int style, int width=0, char* dashes=0);
+ // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
+ void color(Fl_Color c);
+ void color(uchar r, uchar g, uchar b);
};
diff --git a/src/cfg_gfx/quartz_color.cxx b/src/cfg_gfx/quartz_color.cxx
new file mode 100644
index 000000000..b4ca35f7c
--- /dev/null
+++ b/src/cfg_gfx/quartz_color.cxx
@@ -0,0 +1,80 @@
+//
+// "$Id$"
+//
+// MacOS color functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2016 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+// The fltk "colormap". This allows ui colors to be stored in 8-bit
+// locations, and provides a level of indirection so that global color
+// changes can be made. Not to be confused with the X colormap, which
+// I try to hide completely.
+
+// matt: Neither Quartz nor Quickdraw support colormaps in this implementation
+// matt: Quartz support done
+
+#include <config.h>
+#include <FL/Fl.H>
+#include <FL/x.H>
+#include <FL/fl_draw.H>
+
+static unsigned fl_cmap[256] = {
+#include "../fl_cmap.h" // this is a file produced by "cmap.cxx":
+};
+
+void Fl_Quartz_Graphics_Driver::color(Fl_Color i) {
+ Fl_Graphics_Driver::color(i);
+ int index;
+ uchar r, g, b;
+ if (i & 0xFFFFFF00) {
+ // translate rgb colors into color index
+ r = i>>24;
+ g = i>>16;
+ b = i>> 8;
+ } else {
+ // translate index into rgb:
+ index = i;
+ unsigned c = fl_cmap[i];
+ r = c>>24;
+ g = c>>16;
+ b = c>> 8;
+ }
+ if (!fl_gc) return; // no context yet? We will assign the color later.
+ float fr = r/255.0f;
+ float fg = g/255.0f;
+ float fb = b/255.0f;
+ CGContextSetRGBFillColor(fl_gc, fr, fg, fb, 1.0f);
+ CGContextSetRGBStrokeColor(fl_gc, fr, fg, fb, 1.0f);
+}
+
+void Fl_Quartz_Graphics_Driver::color(uchar r, uchar g, uchar b) {
+ Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
+ float fr = r/255.0f;
+ float fg = g/255.0f;
+ float fb = b/255.0f;
+ if (!fl_gc) return; // no context yet? We will assign the color later.
+ CGContextSetRGBFillColor(fl_gc, fr, fg, fb, 1.0f);
+ CGContextSetRGBStrokeColor(fl_gc, fr, fg, fb, 1.0f);
+}
+
+// FIXME: this function should not be here! It's not part of the driver.
+void Fl::set_color(Fl_Color i, unsigned c) {
+ if (fl_cmap[i] != c) {
+ fl_cmap[i] = c;
+ }
+}
+
+//
+// End of "$Id$".
+//
diff --git a/src/cfg_gfx/xlib.H b/src/cfg_gfx/xlib.H
index 460e02e10..c0102a726 100644
--- a/src/cfg_gfx/xlib.H
+++ b/src/cfg_gfx/xlib.H
@@ -100,6 +100,9 @@ protected:
void pie(int x, int y, int w, int h, double a1, double a2);
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
void line_style(int style, int width=0, char* dashes=0);
+ // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
+ void color(Fl_Color c);
+ void color(uchar r, uchar g, uchar b);
};
diff --git a/src/cfg_gfx/xlib_color.cxx b/src/cfg_gfx/xlib_color.cxx
new file mode 100644
index 000000000..f7e1ac5e6
--- /dev/null
+++ b/src/cfg_gfx/xlib_color.cxx
@@ -0,0 +1,351 @@
+//
+// "$Id$"
+//
+// Color functions for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2010 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// http://www.fltk.org/COPYING.php
+//
+// Please report all bugs and problems on the following page:
+//
+// http://www.fltk.org/str.php
+//
+
+// Implementation of fl_color(i), fl_color(r,g,b).
+
+// FIXME: all the global functions in this file should probably be protected
+// members of the driver class. Starting with 1.4 we will allow multiple drivers
+// to co-exist, creating conflicts with multipe mapping.
+
+// FIXME: maybe we can forget about color mapping and assume RGB?
+
+// Also code to look at the X visual and figure out the best way to turn
+// a color into a pixel value.
+
+// SGI compiler seems to have problems with unsigned char arguments
+// being used to index arrays. So I always copy them to an integer
+// before use.
+
+# include "Fl_XColor.H"
+# include <FL/Fl.H>
+# include <FL/x.H>
+# include <FL/fl_draw.H>
+
+////////////////////////////////////////////////////////////////
+// figure_out_visual() calculates masks & shifts for generating
+// pixels in true-color visuals:
+
+uchar fl_redmask; /**< color mask used in current color map handling */
+uchar fl_greenmask; /**< color mask used in current color map handling */
+uchar fl_bluemask; /**< color mask used in current color map handling */
+
+int fl_redshift; /**< color shift used in current color map handling */
+int fl_greenshift; /**< color shift used in current color map handling */
+int fl_blueshift; /**< color shift used in current color map handling */
+int fl_extrashift; /**< color shift used in current color map handling */
+
+static uchar beenhere;
+
+static void figure_out_visual() {
+ beenhere = 1;
+ if (!fl_visual->red_mask || !fl_visual->green_mask || !fl_visual->blue_mask){
+# if USE_COLORMAP
+ fl_redmask = 0;
+ return;
+# else
+ Fl::fatal("Requires true color visual");
+# endif
+ }
+
+ // get the bit masks into a more useful form:
+ int i,j,m;
+
+ for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->red_mask & m) break;
+ for (j = i; m; j++, m<<=1) if (!(fl_visual->red_mask & m)) break;
+ fl_redshift = j-8;
+ fl_redmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+ for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->green_mask & m) break;
+ for (j = i; m; j++, m<<=1) if (!(fl_visual->green_mask & m)) break;
+ fl_greenshift = j-8;
+ fl_greenmask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+ for (i = 0, m = 1; m; i++, m<<=1) if (fl_visual->blue_mask & m) break;
+ for (j = i; m; j++, m<<=1) if (!(fl_visual->blue_mask & m)) break;
+ fl_blueshift = j-8;
+ fl_bluemask = (j-i >= 8) ? 0xFF : 0xFF-(255>>(j-i));
+
+ i = fl_redshift;
+ if (fl_greenshift < i) i = fl_greenshift;
+ if (fl_blueshift < i) i = fl_blueshift;
+ if (i < 0) {
+ fl_extrashift = -i;
+ fl_redshift -= i; fl_greenshift -= i; fl_blueshift -= i;
+ } else
+ fl_extrashift = 0;
+
+}
+
+static unsigned fl_cmap[256] = {
+#include "fl_cmap.h" // this is a file produced by "cmap.cxx":
+};
+
+# if HAVE_OVERLAY
+/** HAVE_OVERLAY determines whether fl_xmap is one or two planes */
+Fl_XColor fl_xmap[2][256];
+/** HAVE_OVERLAY determines whether fl_overlay is variable or defined as 0 */
+uchar fl_overlay;
+Colormap fl_overlay_colormap;
+XVisualInfo* fl_overlay_visual;
+ulong fl_transparent_pixel;
+# else
+/** HAVE_OVERLAY determines whether fl_xmap is one or two planes */
+Fl_XColor fl_xmap[1][256];
+/** HAVE_OVERLAY determines whether fl_overlay is variable or defined as 0 */
+# define fl_overlay 0
+# endif
+
+void Fl_Xlib_Graphics_Driver::color(Fl_Color i) {
+ if (i & 0xffffff00) {
+ unsigned rgb = (unsigned)i;
+ fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
+ } else {
+ Fl_Graphics_Driver::color(i);
+ if(!fl_gc) return; // don't get a default gc if current window is not yet created/valid
+ XSetForeground(fl_display, fl_gc, fl_xpixel(i));
+ }
+}
+
+void Fl_Xlib_Graphics_Driver::color(uchar r,uchar g,uchar b) {
+ Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
+ if(!fl_gc) return; // don't get a default gc if current window is not yet created/valid
+ XSetForeground(fl_display, fl_gc, fl_xpixel(r,g,b));
+}
+
+/** \addtogroup fl_attributes
+ @{ */
+////////////////////////////////////////////////////////////////
+// Get an rgb color. This is easy for a truecolor visual. For
+// colormapped it picks the closest color out of the cube in the
+// fltk colormap. However if this color cube entry has been
+// requested before, you will get the earlier requested color, and
+// even this may be approximated if the X colormap was full.
+
+/**
+ Returns the X pixel number used to draw the given rgb color.
+ This is the X pixel that fl_color() would use.
+ \param[in] r,g,b color components
+ \return X pixel number
+*/
+ulong fl_xpixel(uchar r,uchar g,uchar b) {
+ if (!beenhere) figure_out_visual();
+# if USE_COLORMAP
+ if (!fl_redmask) {
+ // find closest entry in the colormap:
+ Fl_Color i =
+ fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256);
+ Fl_XColor &xmap = fl_xmap[fl_overlay][i];
+ if (xmap.mapped) return xmap.pixel;
+ // if not black or white, change the entry to be an exact match:
+ if (i != FL_COLOR_CUBE && i != 0xFF)
+ fl_cmap[i] = (r<<24)|(g<<16)|(b<<8);
+ return fl_xpixel(i); // allocate an X color
+ }
+# endif
+ return
+ (((r&fl_redmask) << fl_redshift)+
+ ((g&fl_greenmask)<<fl_greenshift)+
+ ((b&fl_bluemask)<< fl_blueshift)
+ ) >> fl_extrashift;
+}
+
+////////////////////////////////////////////////////////////////
+// Get a color out of the fltk colormap. Again for truecolor
+// visuals this is easy. For colormap this actually tries to allocate
+// an X color, and does a least-squares match to find the closest
+// color if X cannot allocate that color.
+
+// calculate what color is actually on the screen for a mask:
+static inline uchar realcolor(uchar color, uchar mask) {
+# if 0
+ // accurate version if the display has linear gamma, but fl_draw_image
+ // works better with the simpler version on most screens...
+ uchar m = mask;
+ uchar result = color&m;
+ for (;;) {
+ while (m&mask) {m>>=1; color>>=1;}
+ if (!m) break;
+ mask = m;
+ result |= color&m;
+ }
+ return result;
+# else
+ return (color&mask) | ( (~mask)&(mask>>1) );
+# endif
+}
+
+/**
+ Returns the X pixel number used to draw the given FLTK color index.
+ This is the X pixel that fl_color() would use.
+ \param[in] i color index
+ \return X pixel number
+*/
+ulong fl_xpixel(Fl_Color i) {
+ if (i & 0xffffff00) {
+ return fl_xpixel((i >> 24) & 255, (i >> 16) & 255, (i >> 8) & 255);
+ }
+
+ Fl_XColor &xmap = fl_xmap[fl_overlay][i];
+ if (xmap.mapped) return xmap.pixel;
+
+ if (!beenhere) figure_out_visual();
+
+ uchar r,g,b;
+ {unsigned c = fl_cmap[i]; r=uchar(c>>24); g=uchar(c>>16); b=uchar(c>>8);}
+
+# if USE_COLORMAP
+ Colormap colormap = fl_colormap;
+# if HAVE_OVERLAY
+ if (fl_overlay) colormap = fl_overlay_colormap; else
+# endif
+ if (fl_redmask) {
+# endif
+ // return color for a truecolor visual:
+ xmap.mapped = 2; // 2 prevents XFreeColor from being called
+ xmap.r = realcolor(r, fl_redmask);
+ xmap.g = realcolor(g, fl_greenmask);
+ xmap.b = realcolor(b, fl_bluemask);
+ return xmap.pixel =
+ (((r&fl_redmask) << fl_redshift)+
+ ((g&fl_greenmask)<<fl_greenshift)+
+ ((b&fl_bluemask)<< fl_blueshift)
+ ) >> fl_extrashift;
+# if USE_COLORMAP
+ }
+# if HAVE_OVERLAY
+ static XColor* ac[2];
+ XColor*& allcolors = ac[fl_overlay];
+ static int nc[2];
+ int& numcolors = nc[fl_overlay];
+# else
+ static XColor *allcolors;
+ static int numcolors;
+# endif
+
+ // I don't try to allocate colors with XAllocColor once it fails
+ // with any color. It is possible that it will work, since a color
+ // may have been freed, but some servers are extremely slow and this
+ // avoids one round trip:
+ if (!numcolors) { // don't try after a failure
+ XColor xcol;
+ xcol.red = r<<8; xcol.green = g<<8; xcol.blue = b<<8;
+ if (XAllocColor(fl_display, colormap, &xcol)) {
+ xmap.mapped = 1;
+ xmap.r = xcol.red>>8;
+ xmap.g = xcol.green>>8;
+ xmap.b = xcol.blue>>8;
+ return xmap.pixel = xcol.pixel;
+ }
+
+ // I only read the colormap once. Again this is due to the slowness
+ // of round-trips to the X server, even though other programs may alter
+ // the colormap after this and make decisions here wrong.
+# if HAVE_OVERLAY
+ if (fl_overlay) numcolors = fl_overlay_visual->colormap_size; else
+# endif
+ numcolors = fl_visual->colormap_size;
+ if (!allcolors) allcolors = new XColor[numcolors];
+ for (int p = numcolors; p--;) allcolors[p].pixel = p;
+ XQueryColors(fl_display, colormap, allcolors, numcolors);
+ }
+
+ // find least-squares match:
+ int mindist = 0x7FFFFFFF;
+ unsigned int bestmatch = 0;
+ for (unsigned int n = numcolors; n--;) {
+# if HAVE_OVERLAY
+ if (fl_overlay && n == fl_transparent_pixel) continue;
+# endif
+ XColor &a = allcolors[n];
+ int d, t;
+ t = int(r)-int(a.red>>8); d = t*t;
+ t = int(g)-int(a.green>>8); d += t*t;
+ t = int(b)-int(a.blue>>8); d += t*t;
+ if (d <= mindist) {bestmatch = n; mindist = d;}
+ }
+ XColor &p = allcolors[bestmatch];
+
+ // It appears to "work" to not call this XAllocColor, which will
+ // avoid another round-trip to the server. But then X does not
+ // know that this program "owns" this value, and can (and will)
+ // change it when the program that did allocate it exits:
+ if (XAllocColor(fl_display, colormap, &p)) {
+ xmap.mapped = 1;
+ xmap.pixel = p.pixel;
+ } else {
+ // However, if that XAllocColor fails, I have to give up and
+ // assume the pixel is ok for the duration of the program. This
+ // is due to bugs (?) in the Solaris X and some X terminals
+ // where XAllocColor *always* fails when the colormap is full,
+ // even if we ask for a color already in it...
+ xmap.mapped = 2; // 2 prevents XFreeColor from being called
+ xmap.pixel = bestmatch;
+ }
+ xmap.r = p.red>>8;
+ xmap.g = p.green>>8;
+ xmap.b = p.blue>>8;
+ return xmap.pixel;
+# endif
+}
+
+/**
+ Free color \p i if used, and clear mapping table entry.
+ \param[in] i color index
+ \param[in] overlay 0 for normal, 1 for overlay color
+*/
+void Fl::free_color(Fl_Color i, int overlay) {
+# if HAVE_OVERLAY
+# else
+ if (overlay) return;
+# endif
+ if (fl_xmap[overlay][i].mapped) {
+# if USE_COLORMAP
+# if HAVE_OVERLAY
+ Colormap colormap = overlay ? fl_overlay_colormap : fl_colormap;
+# else
+ Colormap colormap = fl_colormap;
+# endif
+ if (fl_xmap[overlay][i].mapped == 1)
+ XFreeColors(fl_display, colormap, &(fl_xmap[overlay][i].pixel), 1, 0);
+# endif
+ fl_xmap[overlay][i].mapped = 0;
+ }
+}
+
+/**
+ Set color mapping table entry \p i to color \p c
+ \param[in] i color index
+ \param[in] c color
+*/
+void Fl::set_color(Fl_Color i, unsigned c) {
+ if (fl_cmap[i] != c) {
+ free_color(i,0);
+# if HAVE_OVERLAY
+ free_color(i,1);
+# endif
+ fl_cmap[i] = c;
+ }
+}
+
+/**
+ @}
+ */
+
+//
+// End of "$Id$".
+//