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

fl_color_win32.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: fl_color_win32.cxx 8129 2010-12-28 15:33:36Z manolo $"
00003 //
00004 // WIN32 color functions for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 // The fltk "colormap".  This allows ui colors to be stored in 8-bit
00029 // locations, and provides a level of indirection so that global color
00030 // changes can be made.  Not to be confused with the X colormap, which
00031 // I try to hide completely.
00032 
00033 // SGI compiler seems to have problems with unsigned char arguments
00034 // being used to index arrays.  So I always copy them to an integer
00035 // before use.
00036 
00037 #include <config.h>
00038 #include <FL/Fl.H>
00039 #include <FL/x.H>
00040 #include <FL/fl_draw.H>
00041 
00042 static unsigned fl_cmap[256] = {
00043 #include "fl_cmap.h" // this is a file produced by "cmap.cxx":
00044 };
00045 
00046 // Translations to win32 data structures:
00047 Fl_XMap fl_xmap[256];
00048 
00049 Fl_XMap* fl_current_xmap;
00050 
00051 HPALETTE fl_palette;
00052 static HGDIOBJ tmppen=0;
00053 static HPEN savepen=0;
00054 
00055 void fl_cleanup_pens(void) {
00056   for (int i=0; i<256; i++) {
00057     if (fl_xmap[i].pen) DeleteObject(fl_xmap[i].pen);
00058   }
00059 }
00060 
00061 void fl_save_pen(void) {
00062     if(!tmppen) tmppen = CreatePen(PS_SOLID, 1, 0);
00063     savepen = (HPEN)SelectObject(fl_gc, tmppen);
00064 }
00065 
00066 void fl_restore_pen(void) {
00067     if (savepen) SelectObject(fl_gc, savepen);
00068     DeleteObject(tmppen);
00069     tmppen = 0;
00070     savepen = 0;
00071 }
00072 
00073 static void clear_xmap(Fl_XMap& xmap) {
00074   if (xmap.pen) {
00075     HGDIOBJ tmppen = GetStockObject(BLACK_PEN);
00076     HGDIOBJ oldpen = SelectObject(fl_gc, tmppen);       // Push out the current pen of the gc
00077     if(oldpen != xmap.pen) SelectObject(fl_gc, oldpen); // Put it back if it is not the one we are about to delete
00078     DeleteObject((HGDIOBJ)(xmap.pen));
00079     xmap.pen = 0;
00080     xmap.brush = -1;
00081   }
00082 }
00083 
00084 static void set_xmap(Fl_XMap& xmap, COLORREF c) {
00085   xmap.rgb = c;
00086   if (xmap.pen) {
00087       HGDIOBJ oldpen = SelectObject(fl_gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one
00088       if (oldpen != xmap.pen)SelectObject(fl_gc,oldpen);              // if old one not xmap.pen, need to put it back
00089       DeleteObject(xmap.pen);                                         // delete pen
00090   }
00091   xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb);                        // get a pen into xmap.pen
00092   xmap.brush = -1;
00093 }
00094 
00095 Fl_Color fl_color_;
00096 
00097 void Fl_GDI_Graphics_Driver::color(Fl_Color i) {
00098   if (i & 0xffffff00) {
00099     unsigned rgb = (unsigned)i;
00100     fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
00101   } else {
00102     fl_color_ = i;
00103     Fl_XMap &xmap = fl_xmap[i];
00104     if (!xmap.pen) {
00105 #if USE_COLORMAP
00106       if (fl_palette) {
00107         set_xmap(xmap, PALETTEINDEX(i));
00108       } else {
00109 #endif
00110         unsigned c = fl_cmap[i];
00111         set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)));
00112 #if USE_COLORMAP
00113       }
00114 #endif
00115     }
00116     fl_current_xmap = &xmap;
00117     SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
00118   }
00119 }
00120 
00121 void Fl_GDI_Graphics_Driver::color(uchar r, uchar g, uchar b) {
00122   static Fl_XMap xmap;
00123   COLORREF c = RGB(r,g,b);
00124   fl_color_ = fl_rgb_color(r, g, b);
00125   if (!xmap.pen || c != xmap.rgb) {
00126     clear_xmap(xmap);
00127     set_xmap(xmap, c);
00128   }
00129   fl_current_xmap = &xmap;
00130   SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
00131 }
00132 
00133 HBRUSH fl_brush() {
00134   return fl_brush_action(0);
00135 }
00136 
00137 HBRUSH fl_brush_action(int action) {
00138   Fl_XMap *xmap = fl_current_xmap;
00139   // Wonko: we use some statistics to cache only a limited number
00140   // of brushes:
00141 #define FL_N_BRUSH 16
00142   static struct Fl_Brush {
00143     HBRUSH brush;
00144     unsigned short usage;
00145     Fl_XMap* backref;
00146   } brushes[FL_N_BRUSH];
00147 
00148   if (action) {
00149     SelectObject(fl_gc, GetStockObject(BLACK_BRUSH));  // Load stock object
00150     for (int i=0; i<FL_N_BRUSH; i++) {
00151       if (brushes[i].brush)
00152         DeleteObject(brushes[i].brush); // delete all brushes in array
00153     }
00154     return NULL;
00155   }
00156 
00157   int i = xmap->brush; // find the associated brush
00158   if (i != -1) { // if the brush was allready allocated
00159     if (brushes[i].brush == NULL) goto CREATE_BRUSH;
00160     if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic
00161       for (int j=0; j<FL_N_BRUSH; j++) {
00162         if (brushes[j].usage>16000)
00163           brushes[j].usage -= 16000;
00164         else 
00165           brushes[j].usage = 0;
00166       }
00167     }
00168     return brushes[i].brush;
00169   } else {
00170     int umin = 32000, imin = 0;
00171     for (i=0; i<FL_N_BRUSH; i++) {
00172       if (brushes[i].brush == NULL) goto CREATE_BRUSH;
00173       if (brushes[i].usage<umin) {
00174         umin = brushes[i].usage;
00175         imin = i;
00176       }
00177     }
00178     i = imin;
00179     HGDIOBJ tmpbrush = GetStockObject(BLACK_BRUSH);  // get a stock brush
00180     HGDIOBJ oldbrush = SelectObject(fl_gc,tmpbrush); // load in into current context
00181     if (oldbrush != brushes[i].brush) SelectObject(fl_gc,oldbrush);  // reload old one
00182     DeleteObject(brushes[i].brush);      // delete the one in list
00183     brushes[i].brush = NULL;
00184     brushes[i].backref->brush = -1;
00185   }
00186 CREATE_BRUSH:
00187   brushes[i].brush = CreateSolidBrush(xmap->rgb);
00188   brushes[i].usage = 0;
00189   brushes[i].backref = xmap;
00190   xmap->brush = i;
00191   return brushes[i].brush;
00192 }
00193 
00194 void Fl::free_color(Fl_Color i, int overlay) {
00195   if (overlay) return; // do something about GL overlay?
00196   clear_xmap(fl_xmap[i]);
00197 }
00198 
00199 void Fl::set_color(Fl_Color i, unsigned c) {
00200   if (fl_cmap[i] != c) {
00201     clear_xmap(fl_xmap[i]);
00202     fl_cmap[i] = c;
00203   }
00204 }
00205 
00206 #if USE_COLORMAP
00207 
00208 // 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary
00209 // Thanks to Michael Sweet @ Easy Software Products for this
00210 
00211 HPALETTE
00212 fl_select_palette(void)
00213 {
00214   static char beenhere;
00215   if (!beenhere) {
00216     beenhere = 1;
00217 
00218     //if (GetDeviceCaps(fl_gc, BITSPIXEL) > 8) return NULL;
00219     int nColors = GetDeviceCaps(fl_gc, SIZEPALETTE);
00220     if (nColors <= 0 || nColors > 256) return NULL;
00221     // this will try to work on < 256 color screens, but will probably
00222     // come out quite badly.
00223 
00224     // I lamely try to get this variable-sized object allocated on stack:
00225     ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1];
00226     LOGPALETTE *pPal = (LOGPALETTE*)foo;
00227 
00228     pPal->palVersion    = 0x300;
00229     pPal->palNumEntries = nColors;
00230 
00231     // Build 256 colors from the standard FLTK colormap...
00232 
00233     for (int i = 0; i < nColors; i ++) {
00234       pPal->palPalEntry[i].peRed   = (fl_cmap[i] >> 24) & 255;
00235       pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255;
00236       pPal->palPalEntry[i].peBlue  = (fl_cmap[i] >>  8) & 255;
00237       pPal->palPalEntry[i].peFlags = 0;
00238     };
00239 
00240     // Create the palette:
00241     fl_palette = CreatePalette(pPal);
00242   }
00243   if (fl_palette) {
00244     SelectPalette(fl_gc, fl_palette, FALSE);
00245     RealizePalette(fl_gc);
00246   }
00247   return fl_palette;
00248 }
00249 
00250 #endif
00251 
00252 //
00253 // End of "$Id: fl_color_win32.cxx 8129 2010-12-28 15:33:36Z manolo $".
00254 //