imported catch-22 sol clone with authors permission
[reactos.git] / rosapps / games / solitaire / cardlib / cardcolor.cpp
1 //
2 // Colour support
3 //
4 #include <windows.h>
5
6 #define MakeRGB RGB
7
8 #define MIN3(a,b,c) ( (a)<=(b) ? (a)<=(c)?(a):(c) : (b)<=(c)?(b):(c) )
9 #define MAX3(a,b,c) ( (a)>=(b) ? (a)>=(c)?(a):(c) : (b)>=(c)?(b):(c) )
10
11 inline double fMax(double a, double b)
12 {
13 return a < b ? b : a;
14 }
15
16 inline double fMin(double a, double b)
17 {
18 return a < b ? a : b;
19 }
20 /******************************************************************************
21 FUNCTION: RGBtoHLS
22 PURPOSE: Convert from RGB to HLS
23 IN: RGB color (0xBBGGRR)
24 OUT: Hue, Saturation, Luminance from 0 to 1
25 COPYRIGHT:1995-1997 Robert Mashlan
26 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
27 ******************************************************************************/
28 void RGBtoHLS(const COLORREF rgb, double *H, double *L, double *S )
29 {
30 double delta;
31 double r = (double)((rgb )&0xFF)/255;
32 double g = (double)((rgb>> 8)&0xFF)/255;
33 double b = (double)((rgb>>16)&0xFF)/255;
34 double cmax = MAX3(r,g,b);
35 double cmin = MIN3(r,g,b);
36 *L=(cmax+cmin)/2.0;
37
38 if(cmax == cmin)
39 {
40 *S = *H = 0; // it's really undefined
41 }
42 else
43 {
44 if(*L < 0.5) *S = (cmax-cmin)/(cmax+cmin);
45 else *S = (cmax-cmin)/(2.0-cmax-cmin);
46
47 delta = cmax - cmin;
48
49 if(r == cmax)
50 {
51 *H = (g - b) / delta;
52 }
53 else
54 {
55 if(g == cmax) *H = 2.0 + (b-r) / delta;
56 else *H = 4.0 + (r-g) / delta;
57 }
58 *H /= 6.0;
59 if (*H < 0.0) *H += 1;
60 }
61 }
62
63 /******************************************************************************
64 FUNCTION: HueToRGB
65 PURPOSE: Convert a hue (color) to RGB
66 COPYRIGHT:1995-1997 Robert Mashlan
67 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
68 ******************************************************************************/
69 double HueToRGB(const double m1, const double m2, double h )
70 {
71 if (h<0) h+=1.0;
72 if (h>1) h-=1.0;
73 if (6.0*h < 1 ) return (m1+(m2-m1)*h*6.0);
74 if (2.0*h < 1 ) return m2;
75 if (3.0*h < 2.0) return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);
76 return m1;
77 }
78
79
80 /******************************************************************************
81 FUNCTION: HLStoRGB
82 PURPOSE: Convert from HSL to RGB
83 IN: Hue, Saturation, Luminance from 0 to 1
84 RETURN: RGB color (0xBBGGRR)
85 COPYRIGHT:1995-1997 Robert Mashlan
86 Modified for LabWindows/CVI, 1999 Guillaume Dargaud
87 ******************************************************************************/
88
89 COLORREF HLStoRGB(const double H, const double L, const double S )
90 {
91 double r,g,b;
92 double m1, m2;
93
94 if(S == 0)
95 {
96 r = g = b = L;
97 }
98 else
99 {
100 if (L <= 0.5)
101 m2 = L * (1.0 + S);
102 else
103 m2 = L + S - L * S;
104
105 m1 = 2.0 * L - m2;
106
107 r = HueToRGB(m1,m2,H+1.0/3.0);
108 g = HueToRGB(m1,m2,H);
109 b = HueToRGB(m1,m2,H-1.0/3.0);
110 }
111
112 return RGB(r*255, g*255, b*255);
113 }
114
115
116
117 /******************************************************************************
118 FUNCTION: ColorScaleHSL
119 PURPOSE: Returns the HSL linear interpolated color between 2 colors
120 (more natural looking than RGB interpolation)
121 For instance if the luminance is the same in Col1 and Col2,
122 then the luminance of the result will be the same
123 If Ratio=0, you get Col1,
124 If Ratio=1, you get Col2
125 IN: Col1: low color in hex 0xBBGGRR format
126 Col2: high color in hex 0xBBGGRR format
127 Ratio: 0 for low color, 1 for high color, or in between
128 EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x1F5F3F
129 ******************************************************************************/
130 COLORREF ColorScaleHSL( const COLORREF Col1, const COLORREF Col2, const double Ratio)
131 {
132 static double H1, H2, S1, S2, L1, L2;
133
134 if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
135 else if (Ratio>=1) return Col2;
136
137 RGBtoHLS( Col1, &H1, &L1, &S1);
138 RGBtoHLS( Col2, &H2, &L2, &S2);
139 return HLStoRGB( H1+(H2-H1)*Ratio, L1+(L2-L1)*Ratio, S1+(S2-S1)*Ratio );
140 }
141
142
143 /******************************************************************************
144 FUNCTION: ColorScaleRGB
145 PURPOSE: Returns the RGB linear interpolated color between 2 colors
146 If Ratio=0, you get Col1,
147 If Ratio=1, you get Col2
148 IN: Col1: low color in hex 0xBBGGRR format
149 Col2: high color in hex 0xBBGGRR format
150 Ratio: 0 for low color, 1 for high color, or in between
151 EXAMPLE: Col1=0, Col2=0xFF00FF, Ratio=0.5 returns 0x800080
152 ******************************************************************************/
153 COLORREF ColorScaleRGB( const COLORREF Col1,
154 const COLORREF Col2,
155 const double Ratio) {
156 int R1=(Col1)&0xFF, G1=(Col1>>8)&0xFF, B1=(Col1>>16)&0xFF;
157 int R2=(Col2)&0xFF, G2=(Col2>>8)&0xFF, B2=(Col2>>16)&0xFF;
158
159 if (Ratio<=0) return Col1; // Ratio parameter must be between 0 and 1
160 else if (Ratio>=1) return Col2;
161
162 /* return RGB(
163 (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding
164 (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),
165 (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)
166 );*/
167
168 /*double r = Ratio;
169 if(Col2 == 0)
170 r = 1-Ratio;
171 else
172 r = 1+Ratio;
173 R1 = (int)(double(R1) * r + 0.5);
174 G1 = (int)(double(G1) * r + 0.5);
175 B1 = (int)(double(B1) * r + 0.5);
176 return RGB(R1,G1,B1);*/
177
178 return RGB(
179 (R1 + (R2 - R1) * (Ratio + 0.02) + 0.5), // rounding
180 (G1 + (G2 - G1) * (Ratio - 0.00) + 0.5),
181 (B1 + (B2 - B1) * (Ratio + 0.05) + 0.5)
182 );
183 }
184
185
186
187 COLORREF ColorDarker(COLORREF col, double ratio)
188 {
189 static double Hue, Lum, Sat;
190
191 //RGBtoHLS(col, &Hue, &Lum, &Sat);
192
193 //col = HLStoRGB(Hue, fMax(0.0,Lum-ratio), Sat);
194
195 return ColorScaleHSL(col, RGB(0,0,0), ratio);
196
197 //return col;
198 }
199
200 COLORREF ColorLighter(COLORREF col, double ratio)
201 {
202 static double Hue, Lum, Sat;
203
204 //RGBtoHLS(col, &Hue, &Lum, &Sat);
205
206 //col = HLStoRGB(Hue, fMin(1.0,Lum+ratio), Sat);
207
208 return ColorScaleHSL(col, RGB(255,255,255), ratio);
209
210 //return col;
211 }
212
213 //
214 // Experimental!!!
215 //
216 #if 0
217
218 typedef enum { Red, Green, Blue };
219
220 void RGBtoHLS(COLORREF rgb, double *Hue, double *Lum, double *Sat)
221 {
222 double mn, mx;
223 int major;
224
225 BYTE red, green, blue;
226
227 red = GetRValue(rgb);
228 green = GetGValue(rgb);
229 blue = GetBValue(rgb);
230
231 if(red < green)
232 {
233 mn = red; mx = green; major = Green;
234 }
235 else
236 {
237 mn = green; mx = red; major = Red;
238 }
239
240 if(blue < mn)
241 {
242 mn = blue;
243 }
244 else if(blue > mx)
245 {
246 mx = blue; major = Blue;
247 }
248
249 if(mn == mx)
250 {
251 *Lum = mn / 255;
252 *Sat = 0;
253 *Hue = 0;
254 }
255 else
256 {
257 *Lum = (mx + mn) / 510;
258
259 if(*Lum <= 0.5)
260 *Sat = (mx-mn) / (mn+mx);
261 else
262 *Sat = (mx-mn) / (510-mn-mx);
263
264 switch(major)
265 {
266 case Red: *Hue = (green-blue) * 60.0 / (mx-mn) + 360.0;
267 break;
268
269 case Green: *Hue = (blue-red) * 60.0 / (mx-mn) + 120.0;
270 break;
271
272 case Blue: *Hue = (red-green) * 60.0 / (mx-mn) + 240.0;
273 break;
274
275 }
276
277 if(*Hue > 360.0)
278 *Hue -= 360.0;
279 }
280 }
281
282 static BYTE Value(double m1, double m2, double hue)
283 {
284
285 if(hue > 360) hue -= 360;
286 else if(hue < 0) hue += 360;
287
288 if(hue < 60)
289 m1 = m1 + (m2 - m1) * hue / 60;
290 else if(hue < 180)
291 m1 = m2;
292 else if(hue < 240)
293 m1 = m1 + (m2 - m1) * (240 - hue) / 60;
294
295 return (BYTE)(m1 * 255);
296 }
297
298 COLORREF HLStoRGB(const double Hue, const double Lum, const double Sat)
299 {
300 BYTE red, green, blue;
301
302 if(Sat == 0)
303 {
304 red = green = blue = (BYTE)(Lum * 255);
305 }
306 else
307 {
308 double m1, m2;
309
310 if(Lum <= 0.5)
311 m2 = Lum + Lum * Sat;
312 else
313 m2 = Lum + Sat - Lum * Sat;
314
315 m1 = 2 * Lum - m2;
316
317 red = Value(m1, m2, Hue + 120);
318 green = Value(m1, m2, Hue);
319 blue = Value(m1, m2, Hue - 120);
320 }
321
322 return RGB(red, green, blue);
323 }
324
325 COLORREF ScaleLumRGB(COLORREF col1, double ratio)
326 {
327 double H1, L1, S1;
328
329 RGBtoHLS(col1, &H1, &L1, &S1);
330
331 L1 += L1 * ratio;
332
333 return HLStoRGB(H1, L1, S1);
334 }
335
336 COLORREF ColorScaleHSL(const COLORREF Col1, const COLORREF Col2, const double Ratio)
337 {
338 static double H1, H2, S1, S2, L1, L2;
339
340 if(Ratio <= 0) return Col1; // Ratio parameter must be between 0 and 1
341 else if(Ratio >= 1) return Col2;
342
343 RGBtoHLS( Col1, &H1, &L1, &S1);
344 RGBtoHLS( Col2, &H2, &L2, &S2);
345
346 return HLStoRGB( H1 /*+ (H2 - H1 ) * Ratio*/, L1 + (L2 - L1) * Ratio, S1 + (S2 - S1) * Ratio * 2);
347 }
348
349 COLORREF ColorScaleRGB(const COLORREF Col1, const COLORREF Col2, const double Ratio)
350 {
351 return ColorScaleHSL(Col1, Col2, Ratio);
352 }
353 #endif