themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / fl_color_win32.cxx
blob7925f2dfe59f9be582c2eef9d0a921a59a5bbcbd
1 //
2 // "$Id: fl_color_win32.cxx 8384 2011-02-06 12:32:23Z manolo $"
3 //
4 // WIN32 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; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // The fltk "colormap". This allows ui colors to be stored in 8-bit
29 // locations, and provides a level of indirection so that global color
30 // changes can be made. Not to be confused with the X colormap, which
31 // I try to hide completely.
33 // SGI compiler seems to have problems with unsigned char arguments
34 // being used to index arrays. So I always copy them to an integer
35 // before use.
37 #include <config.h>
38 #include <FL/Fl.H>
39 #include <FL/x.H>
40 #include <FL/fl_draw.H>
42 static unsigned fl_cmap[256] = {
43 #include "fl_cmap.h" // this is a file produced by "cmap.cxx":
46 // Translations to win32 data structures:
47 Fl_XMap fl_xmap[256];
49 Fl_XMap* fl_current_xmap;
51 HPALETTE fl_palette;
52 static HGDIOBJ tmppen=0;
53 static HPEN savepen=0;
55 void fl_cleanup_pens(void) {
56 for (int i=0; i<256; i++) {
57 if (fl_xmap[i].pen) DeleteObject(fl_xmap[i].pen);
61 void fl_save_pen(void) {
62 if(!tmppen) tmppen = CreatePen(PS_SOLID, 1, 0);
63 savepen = (HPEN)SelectObject(fl_gc, tmppen);
66 void fl_restore_pen(void) {
67 if (savepen) SelectObject(fl_gc, savepen);
68 DeleteObject(tmppen);
69 tmppen = 0;
70 savepen = 0;
73 static void clear_xmap(Fl_XMap& xmap) {
74 if (xmap.pen) {
75 HGDIOBJ tmppen = GetStockObject(BLACK_PEN);
76 HGDIOBJ oldpen = SelectObject(fl_gc, tmppen); // Push out the current pen of the gc
77 if(oldpen != xmap.pen) SelectObject(fl_gc, oldpen); // Put it back if it is not the one we are about to delete
78 DeleteObject((HGDIOBJ)(xmap.pen));
79 xmap.pen = 0;
80 xmap.brush = -1;
84 static void set_xmap(Fl_XMap& xmap, COLORREF c) {
85 xmap.rgb = c;
86 if (xmap.pen) {
87 HGDIOBJ oldpen = SelectObject(fl_gc,GetStockObject(BLACK_PEN)); // replace current pen with safe one
88 if (oldpen != xmap.pen)SelectObject(fl_gc,oldpen); // if old one not xmap.pen, need to put it back
89 DeleteObject(xmap.pen); // delete pen
91 xmap.pen = CreatePen(PS_SOLID, 1, xmap.rgb); // get a pen into xmap.pen
92 xmap.brush = -1;
95 void Fl_GDI_Graphics_Driver::color(Fl_Color i) {
96 if (i & 0xffffff00) {
97 unsigned rgb = (unsigned)i;
98 fl_color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
99 } else {
100 Fl_Graphics_Driver::color(i);
101 Fl_XMap &xmap = fl_xmap[i];
102 if (!xmap.pen) {
103 #if USE_COLORMAP
104 if (fl_palette) {
105 set_xmap(xmap, PALETTEINDEX(i));
106 } else {
107 #endif
108 unsigned c = fl_cmap[i];
109 set_xmap(xmap, RGB(uchar(c>>24), uchar(c>>16), uchar(c>>8)));
110 #if USE_COLORMAP
112 #endif
114 fl_current_xmap = &xmap;
115 SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
119 void Fl_GDI_Graphics_Driver::color(uchar r, uchar g, uchar b) {
120 static Fl_XMap xmap;
121 COLORREF c = RGB(r,g,b);
122 Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
123 if (!xmap.pen || c != xmap.rgb) {
124 clear_xmap(xmap);
125 set_xmap(xmap, c);
127 fl_current_xmap = &xmap;
128 SelectObject(fl_gc, (HGDIOBJ)(xmap.pen));
131 HBRUSH fl_brush() {
132 return fl_brush_action(0);
135 HBRUSH fl_brush_action(int action) {
136 Fl_XMap *xmap = fl_current_xmap;
137 // Wonko: we use some statistics to cache only a limited number
138 // of brushes:
139 #define FL_N_BRUSH 16
140 static struct Fl_Brush {
141 HBRUSH brush;
142 unsigned short usage;
143 Fl_XMap* backref;
144 } brushes[FL_N_BRUSH];
146 if (action) {
147 SelectObject(fl_gc, GetStockObject(BLACK_BRUSH)); // Load stock object
148 for (int i=0; i<FL_N_BRUSH; i++) {
149 if (brushes[i].brush)
150 DeleteObject(brushes[i].brush); // delete all brushes in array
152 return NULL;
155 int i = xmap->brush; // find the associated brush
156 if (i != -1) { // if the brush was allready allocated
157 if (brushes[i].brush == NULL) goto CREATE_BRUSH;
158 if ( (++brushes[i].usage) > 32000 ) { // keep a usage statistic
159 for (int j=0; j<FL_N_BRUSH; j++) {
160 if (brushes[j].usage>16000)
161 brushes[j].usage -= 16000;
162 else
163 brushes[j].usage = 0;
166 return brushes[i].brush;
167 } else {
168 int umin = 32000, imin = 0;
169 for (i=0; i<FL_N_BRUSH; i++) {
170 if (brushes[i].brush == NULL) goto CREATE_BRUSH;
171 if (brushes[i].usage<umin) {
172 umin = brushes[i].usage;
173 imin = i;
176 i = imin;
177 HGDIOBJ tmpbrush = GetStockObject(BLACK_BRUSH); // get a stock brush
178 HGDIOBJ oldbrush = SelectObject(fl_gc,tmpbrush); // load in into current context
179 if (oldbrush != brushes[i].brush) SelectObject(fl_gc,oldbrush); // reload old one
180 DeleteObject(brushes[i].brush); // delete the one in list
181 brushes[i].brush = NULL;
182 brushes[i].backref->brush = -1;
184 CREATE_BRUSH:
185 brushes[i].brush = CreateSolidBrush(xmap->rgb);
186 brushes[i].usage = 0;
187 brushes[i].backref = xmap;
188 xmap->brush = i;
189 return brushes[i].brush;
192 void Fl::free_color(Fl_Color i, int overlay) {
193 if (overlay) return; // do something about GL overlay?
194 clear_xmap(fl_xmap[i]);
197 void Fl::set_color(Fl_Color i, unsigned c) {
198 if (fl_cmap[i] != c) {
199 clear_xmap(fl_xmap[i]);
200 fl_cmap[i] = c;
204 #if USE_COLORMAP
206 // 'fl_select_palette()' - Make a color palette for 8-bit displays if necessary
207 // Thanks to Michael Sweet @ Easy Software Products for this
209 HPALETTE
210 fl_select_palette(void)
212 static char beenhere;
213 if (!beenhere) {
214 beenhere = 1;
216 //if (GetDeviceCaps(fl_gc, BITSPIXEL) > 8) return NULL;
217 int nColors = GetDeviceCaps(fl_gc, SIZEPALETTE);
218 if (nColors <= 0 || nColors > 256) return NULL;
219 // this will try to work on < 256 color screens, but will probably
220 // come out quite badly.
222 // I lamely try to get this variable-sized object allocated on stack:
223 ulong foo[(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY))/sizeof(ulong)+1];
224 LOGPALETTE *pPal = (LOGPALETTE*)foo;
226 pPal->palVersion = 0x300;
227 pPal->palNumEntries = nColors;
229 // Build 256 colors from the standard FLTK colormap...
231 for (int i = 0; i < nColors; i ++) {
232 pPal->palPalEntry[i].peRed = (fl_cmap[i] >> 24) & 255;
233 pPal->palPalEntry[i].peGreen = (fl_cmap[i] >> 16) & 255;
234 pPal->palPalEntry[i].peBlue = (fl_cmap[i] >> 8) & 255;
235 pPal->palPalEntry[i].peFlags = 0;
238 // Create the palette:
239 fl_palette = CreatePalette(pPal);
241 if (fl_palette) {
242 SelectPalette(fl_gc, fl_palette, FALSE);
243 RealizePalette(fl_gc);
245 return fl_palette;
248 #endif
251 // End of "$Id: fl_color_win32.cxx 8384 2011-02-06 12:32:23Z manolo $".