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/fl_color.cxx | |
| 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/fl_color.cxx')
| -rw-r--r-- | src/fl_color.cxx | 424 |
1 files changed, 68 insertions, 356 deletions
diff --git a/src/fl_color.cxx b/src/fl_color.cxx index 9723e2b38..ddcb8a3ca 100644 --- a/src/fl_color.cxx +++ b/src/fl_color.cxx @@ -23,362 +23,73 @@ // Implementation of fl_color(i), fl_color(r,g,b). -#ifdef WIN32 -# include "fl_color_win32.cxx" -#elif defined(__APPLE__) -# include "fl_color_mac.cxx" -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement color handling in your own file based on fl_color.cxx" -# include "fl_color_porting.cxx" -#else - -// 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; +#include <config.h> +#include "config_lib.h" -} -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. +#ifdef FL_CFG_GFX_QUARTZ -/** - 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; -} +# include "cfg_gfx/quartz_color.cxx" -//////////////////////////////////////////////////////////////// -// 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 -} +#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; - } -} +// ----------------------------------------------------------------------------- + + +#ifdef FL_CFG_GFX_GDI + +# include "cfg_gfx/gdi_color.cxx" + +#endif + + +// ----------------------------------------------------------------------------- -/** - 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; - } -} -#endif // end of X-specific code +#ifdef FL_CFG_GFX_XLIB + +# include "cfg_gfx/xlib_color.cxx" + +#endif + + +// ----------------------------------------------------------------------------- + +/** \addtogroup fl_attributes + @{ */ + /** - Returns the RGB value(s) for the given FLTK color index. - - This form returns the RGB values packed in a 32-bit unsigned - integer with the red value in the upper 8 bits, the green value - in the next 8 bits, and the blue value in bits 8-15. The lower - 8 bits will always be 0. -*/ + Returns the RGB value(s) for the given FLTK color index. + + This form returns the RGB values packed in a 32-bit unsigned + integer with the red value in the upper 8 bits, the green value + in the next 8 bits, and the blue value in bits 8-15. The lower + 8 bits will always be 0. + */ unsigned Fl::get_color(Fl_Color i) { if (i & 0xffffff00) return (i); else return fl_cmap[i]; } /** - Sets an entry in the fl_color index table. You can set it to - any 8-bit RGB color. The color is not allocated until fl_color(i) - is used. -*/ + Sets an entry in the fl_color index table. You can set it to + any 8-bit RGB color. The color is not allocated until fl_color(i) + is used. + */ void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue) { Fl::set_color((Fl_Color)(i & 255), - ((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8)); + ((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8)); } /** - Returns the RGB value(s) for the given FLTK color index. - - This form returns the red, green, and blue values - separately in referenced variables. + Returns the RGB value(s) for the given FLTK color index. + + This form returns the red, green, and blue values + separately in referenced variables. - See also unsigned get_color(Fl_Color c) + See also unsigned get_color(Fl_Color c) */ void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) { unsigned c; @@ -392,16 +103,16 @@ void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) { } /** - Returns the weighted average color between the two given colors. - The red, green and blue values are averages using the following formula: - \code - color = color1 * weight + color2 * (1 - weight) - \endcode - Thus, a \p weight value of 1.0 will return the first color, while a - value of 0.0 will return the second color. - \param[in] color1, color2 boundary colors - \param[in] weight weighting factor -*/ + Returns the weighted average color between the two given colors. + The red, green and blue values are averages using the following formula: + \code + color = color1 * weight + color2 * (1 - weight) + \endcode + Thus, a \p weight value of 1.0 will return the first color, while a + value of 0.0 will return the second color. + \param[in] color1, color2 boundary colors + \param[in] weight weighting factor + */ Fl_Color fl_color_average(Fl_Color color1, Fl_Color color2, float weight) { unsigned rgb1; unsigned rgb2; @@ -421,20 +132,20 @@ Fl_Color fl_color_average(Fl_Color color1, Fl_Color color2, float weight) { } /** - Returns the inactive, dimmed version of the given color -*/ + Returns the inactive, dimmed version of the given color + */ Fl_Color fl_inactive(Fl_Color c) { return fl_color_average(c, FL_GRAY, .33f); } /** - Returns a color that contrasts with the background color. - This will be the foreground color if it contrasts sufficiently with the - background color. Otherwise, returns \p FL_WHITE or \p FL_BLACK depending - on which color provides the best contrast. - \param[in] fg,bg foreground and background colors - \return contrasting color -*/ + Returns a color that contrasts with the background color. + This will be the foreground color if it contrasts sufficiently with the + background color. Otherwise, returns \p FL_WHITE or \p FL_BLACK depending + on which color provides the best contrast. + \param[in] fg,bg foreground and background colors + \return contrasting color + */ Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg) { unsigned c1, c2; // RGB colors int l1, l2; // Luminosities @@ -458,8 +169,9 @@ Fl_Color fl_contrast(Fl_Color fg, Fl_Color bg) { else return FL_WHITE; } /** - @} -*/ + @} + */ + // // End of "$Id$". // |
