diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2016-01-24 16:22:50 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2016-01-24 16:22:50 +0000 |
| commit | 60ec452d043e44bcbb05860381e2077a3b56b09c (patch) | |
| tree | 1eaf13dc05a6da6a53a949fc1a66df6030cab943 /src/cfg_gfx | |
| parent | 49cf30286b505e15ca0496605efca5546c7bbf85 (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.H | 6 | ||||
| -rw-r--r-- | src/cfg_gfx/gdi_color.cxx | 245 | ||||
| -rw-r--r-- | src/cfg_gfx/opengl.H | 6 | ||||
| -rw-r--r-- | src/cfg_gfx/opengl_color.cxx | 70 | ||||
| -rw-r--r-- | src/cfg_gfx/opengl_rect.cxx | 9 | ||||
| -rw-r--r-- | src/cfg_gfx/quartz.H | 7 | ||||
| -rw-r--r-- | src/cfg_gfx/quartz_color.cxx | 80 | ||||
| -rw-r--r-- | src/cfg_gfx/xlib.H | 3 | ||||
| -rw-r--r-- | src/cfg_gfx/xlib_color.cxx | 351 |
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 = ⟼ + 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 = ⟼ + 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$". +// |
