d5f4330b02f44d14508474a2fe4c5f8717f8d2bd
[occt.git] / src / WNT / WNT_GraphicDevice.cxx
1 // Copyright (c) 1996-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 /***********************************************************************
20      FONCTION :
21      ----------
22         Classe WNT_GraphicDevice.cxx :
23
24      HISTORIQUE DES MODIFICATIONS   :
25      --------------------------------
26       03-01-95  : EUG   -> Creation.
27       20-11-97  : FMN   -> Portage WIN95
28       MAR-98    : EUG   -> Porting Win95
29       JUN-98    : EUG   -> Modifications to provide access to this class
30                            from CCL (second constructor + Init () method)
31       SEP-98    : DCB   -> Avoid memory crash when color indices do not follow
32                            each other or do not begin with '1'
33       JAN-99    : EUG   -> Modifications to provide treating display window
34                            as graphic device
35 ************************************************************************/
36
37 /*----------------------------------------------------------------------*/
38 /*
39  * Includes
40  */
41
42 // include windows.h first to have all definitions available
43 #include <windows.h>
44
45 #include <WNT.h>
46 #include <WNT_GraphicDevice.ixx>
47 #include <Aspect_ColorMapEntry.hxx>
48 #include <Aspect_GraphicDriver.hxx>
49 #include <Aspect_Units.hxx>
50
51 #include <stdio.h>
52
53 /*----------------------------------------------------------------------*/
54 /*
55  * Constantes
56  */
57
58 #define PAL           ((PLOGPALETTE)myLogPal)
59 #define MAX_PAL_ERROR (3*256*256L)
60 #define DEFAULT_GAMMA 1.4
61
62 static int  __fastcall _createColorRamp ( HPALETTE* );
63 static BOOL s_SysPalInUse;
64
65 extern HWINSTA ( WINAPI *NTOpenWindowStation       ) ( LPTSTR, BOOL, DWORD        );
66 extern BOOL    ( WINAPI *NTSetProcessWindowStation ) ( HWINSTA                    );
67 extern HDESK   ( WINAPI *NTOpenDesktop             ) ( LPTSTR, DWORD, BOOL, DWORD );
68 extern BOOL    ( WINAPI *NTSetThreadDesktop        ) ( HDESK                      );
69 extern BOOL    ( WINAPI *NTCloseDesktop            ) ( HDESK                      );
70 extern BOOL    ( WINAPI *NTCloseWindowStation      ) ( HWINSTA                    );
71
72 extern OSVERSIONINFO WNT_osVer;
73
74 //=======================================================================
75 //function : WNT_GraphicDevice
76 //purpose  : 
77 //=======================================================================
78
79 WNT_GraphicDevice::WNT_GraphicDevice (
80                       const Standard_Boolean aColorCube,
81                       const Aspect_Handle    aDevContext
82                                          )
83 {
84
85   Init ( aColorCube, aDevContext );
86
87 }  // end constructor ( 1 )
88
89 //=======================================================================
90 //function : WNT_GraphicDevice
91 //purpose  : 
92 //=======================================================================
93
94 WNT_GraphicDevice::WNT_GraphicDevice (
95                       const Standard_Boolean aColorCube,
96                       const Standard_Integer aDevContext
97                      )
98 {
99                      
100   Init (  aColorCube, ( Aspect_Handle )aDevContext  );
101                      
102 }  // end constructor ( 2 )
103
104 //=======================================================================
105 //function : Init
106 //purpose  : 
107 //=======================================================================
108
109 void WNT_GraphicDevice::Init (
110                            const Standard_Boolean aColorCube,
111                            const Aspect_Handle    aDevContext
112                           )
113 {
114                           
115  HDC     hDC;
116  BOOL    palDev;
117  HWND    hwnd = NULL;
118  HBITMAP hBmp = NULL;
119  int     numRes, palSize, nPlanes, nBits;
120
121  hDC  = ( aDevContext == NULL ) ? GetDC ( NULL ) :
122           ( HDC )aDevContext, hwnd = WindowFromDC (  ( HDC )aDevContext  );
123
124 //  It is found that the error occurs in the place in the source code that is
125 // responsible for connecting to the desktop and window pointed by the environment
126 // variable CSF_DISPLAY.
127 // For the moment it is unclear at all what this code is needed for. Therefore it
128 // is removed from the sources in order to fix this bug. This allowed to run the
129 // code without problems on both win32 and win64 platforms.
130 // It is needed to carry out special investigations about this subject. Probably it
131 // can be used to connect to a virtual desktop in order to make snapshots on the
132 // Windows station on which no user is logged in.
133 //
134 // if ( aDevContext == 0 && WNT_osVer.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
135
136 //  HWINSTA hWst = NULL;
137 //  HDESK   hDsk = NULL;
138 //  DWORD   dwLen, dwLenOrig;
139 //  LPTSTR  buff = NULL;
140 //  LPTSTR  sNam = NULL;
141 //  LPTSTR  dNam = NULL;
142 //  BOOL    fSts = FALSE;
143
144 //  dwLenOrig = GetEnvironmentVariable(  TEXT( "CSF_DISPLAY" ), NULL, 0  );
145
146 //  if ( dwLenOrig == 0 ) 
147   
148 //   dwLen = sizeof (  TEXT( "WinSta0\\Default" )  );
149
150 //  else
151
152 //   dwLen = dwLenOrig + sizeof ( TCHAR );
153
154 //  buff = ( LPTSTR )HeapAlloc (
155 //                    GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, dwLen
156 //                   );
157
158 //  if ( dwLenOrig != 0 )
159
160 //   GetEnvironmentVariable (  TEXT( "CSF_DISPLAY" ), buff, dwLen  );
161
162 //  else
163
164 //   lstrcpy (  buff, TEXT( "WinSta0\\Default" )  );
165
166 //  dwLen = 0;
167
168 //  while (  buff[ dwLen ] != TEXT( '\\' ) && buff[ dwLen ] != TEXT( '\x00' )  ) ++dwLen;
169
170 //  sNam = ( LPTSTR )HeapAlloc (
171 //                    GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
172 //                    dwLen * sizeof ( TCHAR ) + sizeof ( TCHAR )
173 //                   );
174
175 //  dwLenOrig = 0;
176
177 //  while ( dwLenOrig != dwLen ) {
178
179 //   sNam[ dwLenOrig ] = buff[ dwLenOrig ];
180 //   ++dwLenOrig;
181
182 //  }  // end while
183
184 //  sNam[ dwLenOrig ] = TEXT( '\x00' );
185
186 //  if (  buff[ dwLen ] == TEXT( '\x00' )  ) goto leave;
187
188 //  lstrcpy ( buff, &buff[ dwLen + 1 ] );
189
190 //  dNam = ( LPTSTR )HeapAlloc (
191 //                    GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS,
192 //                    lstrlen ( buff ) * sizeof ( TCHAR ) + sizeof ( TCHAR )
193 //                   );
194
195 //  lstrcpy ( dNam, buff );
196
197 //  if (   (  hWst = ( *NTOpenWindowStation ) ( sNam, FALSE, MAXIMUM_ALLOWED )  ) == NULL ||
198 //         !( *NTSetProcessWindowStation ) ( hWst )
199 //  ) goto leave;
200
201 //  if (   (  hDsk = ( *NTOpenDesktop ) ( dNam, 0, FALSE, MAXIMUM_ALLOWED )  ) == NULL ||
202 //         !( *NTSetThreadDesktop ) ( hDsk )
203 //  )
204
205 //   if (  GetLastError () == ERROR_BUSY  ) {
206
207 //    if ( hDsk != NULL ) ( *NTCloseDesktop       ) ( hDsk );
208 //    if ( hWst != NULL ) ( *NTCloseWindowStation ) ( hWst );
209      
210 //   } else goto leave;
211
212 //  fSts = TRUE;
213 //leave:
214 //  if ( sNam != NULL ) HeapFree (  GetProcessHeap (), 0, ( LPVOID )sNam  );
215 //  if ( dNam != NULL ) HeapFree (  GetProcessHeap (), 0, ( LPVOID )dNam  );
216 //  if ( buff != NULL ) HeapFree (  GetProcessHeap (), 0, ( LPVOID )buff  );
217
218 //  if ( !fSts ) {
219
220 //   if ( hDsk != NULL ) ( *NTCloseDesktop       ) ( hDsk );
221 //   if ( hWst != NULL ) ( *NTCloseWindowStation ) ( hWst );
222
223 //   Aspect_GraphicDeviceDefinitionError :: Raise ( "Access to station is denied" );
224
225 //  }  // end if
226
227 // }  // end if
228
229   palDev    = (  GetDeviceCaps ( hDC, RASTERCAPS ) & RC_PALETTE  ) ? TRUE : FALSE;  
230   numRes    = GetDeviceCaps ( hDC, NUMRESERVED );
231   palSize   = ( palDev ) ? GetDeviceCaps ( hDC, SIZEPALETTE ) : 0;
232   nPlanes   = GetDeviceCaps ( hDC, PLANES );
233   nBits     = GetDeviceCaps ( hDC, BITSPIXEL );
234   myWidth   = GetDeviceCaps ( hDC, HORZRES );
235   myHeight  = GetDeviceCaps ( hDC, VERTRES );
236   myMWidth  = ( float )GetDeviceCaps ( hDC, HORZSIZE ) / ( 1. MILLIMETER );
237   myMHeight = ( float )GetDeviceCaps ( hDC, VERTSIZE ) / ( 1. MILLIMETER );
238
239   if ( aDevContext != NULL && hwnd != NULL ) {
240
241    RECT r;
242
243    GetClientRect ( hwnd, &r );
244
245    myMWidth  = myMWidth  * r.right  / myWidth;
246    myMHeight = myMHeight * r.bottom / myHeight;
247    myWidth   = r.right;
248    myHeight  = r.bottom;
249
250   } else {
251
252    BITMAP bm;
253
254    hBmp = ( HBITMAP )GetCurrentObject ( hDC, OBJ_BITMAP );
255
256    if (   GetObject (  hBmp, sizeof ( BITMAP ), &bm  )   ) {
257
258     myMWidth  = myMWidth  * bm.bmWidth  / myWidth;
259     myMHeight = myMHeight * bm.bmHeight / myHeight;
260 // Tempory correction for Windows 98
261     if ( WNT_osVer.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS ) { 
262 // 
263     myWidth   = bm.bmWidth;
264     myHeight  = bm.bmHeight;
265
266    } else hBmp = NULL;
267 // Tempory correction for Windows 98
268   }
269 // 
270
271   }  // end else
272
273  if ( aDevContext == NULL ) ReleaseDC ( NULL, hDC );
274
275  myNumColors = (  1 << ( nBits * nPlanes )  );
276
277  if ( palDev ) myNumColors -= numRes;
278
279  myFreeIndex     = 0;
280  myOpenGLPalette = aColorCube;
281
282  if ( palDev ) {
283
284   if ( hwnd == NULL && hBmp == NULL ) {
285
286    myLogPal = HeapAlloc (
287                GetProcessHeap (), HEAP_ZERO_MEMORY,
288                sizeof( LOGPALETTE ) +
289                sizeof( PALETTEENTRY ) * myNumColors
290               );
291
292    if ( !myLogPal )
293
294     Aspect_GraphicDeviceDefinitionError :: Raise ( "Out of memory" );
295
296    PAL -> palVersion    = 0x300;
297    PAL -> palNumEntries = 1;
298
299    myPalette = CreatePalette ( PAL );
300
301    if ( !myPalette ) {
302
303     HeapFree (  GetProcessHeap (), 0, myLogPal  );
304     Aspect_GraphicDeviceDefinitionError :: Raise ( "Unable to create user palette" );   
305
306    }  // end if
307
308    myFreeIndex = 0;
309
310    if (  myOpenGLPalette && !_createColorRamp (  ( HPALETTE* )&myPalette  )  )
311
312     Aspect_GraphicDeviceDefinitionError :: Raise ( "Colorcube creation failed" );
313
314   } else {
315
316    myPalette = GetCurrentObject ( hDC, OBJ_PAL );
317    myLogPal  = NULL;
318
319   }  // end else
320   
321  } else {  // not a palette device
322  
323   myPalette = 0;
324   myLogPal  = NULL;
325  
326  }  // end else ( palDev . . . ) 
327
328  myHighlightColor = RGB( 255, 255, 255 );
329                                                     
330 }  // end WNT_GraphicDevice :: Init
331
332 void WNT_GraphicDevice :: Destroy () {
333
334  if ( myPalette && myLogPal != NULL ) {
335
336   DeletePalette ( myPalette );
337   HeapFree (  GetProcessHeap (), 0, myLogPal  );
338
339  }  // end if
340
341 }  // end WNT_GraphicDevice :: Destroy
342
343 WNT_ColorRef WNT_GraphicDevice :: SetColor (
344                                    const Quantity_Color& aColor,
345                                    const Standard_Boolean aHighlight
346                                   ) {
347
348  Standard_Real    r, g, b;
349  Standard_Integer red, green, blue;
350
351  aColor.Values ( r, g, b, Quantity_TOC_RGB );
352
353  red   = ( Standard_Integer )( 255. * r );
354  green = ( Standard_Integer )( 255. * g );
355  blue  = ( Standard_Integer )( 255. * b );
356
357  return SetColor ( red, green, blue, aHighlight );
358
359 }  // end WNT_GraphicDevice :: SetColor( 1 )
360
361 WNT_ColorRef WNT_GraphicDevice :: SetColor (
362                                    const Standard_Integer aRed,
363                                    const Standard_Integer aGreen,
364                                    const Standard_Integer aBlue,
365                                    const Standard_Boolean aHighlight
366                                   ) {
367                                   
368  int          i;
369  WNT_ColorRef retVal;
370  BYTE         red, green, blue;
371
372  red   = ( BYTE )aRed;
373  green = ( BYTE )aGreen;
374  blue  = ( BYTE )aBlue;
375
376  if ( !myPalette )
377
378   retVal = RGB( red, green, blue );
379
380  else if ( myOpenGLPalette )
381  
382   retVal = PALETTEINDEX(
383             GetNearestPaletteIndex (
384              ( HPALETTE )myPalette, RGB( red, green, blue )
385                         )
386                    );
387
388  else {
389
390   if ( myFreeIndex < myNumColors ) {
391
392    for ( i = 0; i < myFreeIndex; ++i )  // avoid color duplication
393
394     if ( PAL -> palPalEntry[ i ].peRed   == red   &&
395          PAL -> palPalEntry[ i ].peGreen == green &&
396          PAL -> palPalEntry[ i ].peBlue  == blue
397     )
398
399      break;
400
401    if ( i == myFreeIndex ) {  // add new color entry
402
403     PAL -> palPalEntry[ i ].peRed   = red;
404     PAL -> palPalEntry[ i ].peGreen = green;
405     PAL -> palPalEntry[ i ].peBlue  = blue;
406     PAL -> palPalEntry[ i ].peFlags = 0;
407     ++myFreeIndex;
408     ResizePalette (  ( HPALETTE )myPalette, myFreeIndex );
409     SetPaletteEntries (  ( HPALETTE )myPalette, i, 1, &PAL -> palPalEntry[ i ]  );
410
411    }  // end if
412
413    retVal = PALETTEINDEX( i );
414
415   } else  // get closest color
416
417    retVal = PALETTEINDEX(
418              GetNearestPaletteIndex (
419               ( HPALETTE )myPalette, RGB( red, green, blue )
420                          )
421                     );
422
423  }  // end else ( !myPalette . . . )
424
425  if ( aHighlight )
426
427   myHighlightColor = retVal;
428
429  return retVal;
430
431 }  // end WNT_GraphicDevice :: SetColor(2)
432
433 void WNT_GraphicDevice :: SetColor ( const WNT_Long& aPixel ) {
434
435  if ( myPalette && !myOpenGLPalette && myFreeIndex < myNumColors ) {
436
437   int  idx;
438   BYTE red, green, blue;
439
440   blue  = (BYTE) (aPixel & 0xFF);
441   green = (BYTE) (( aPixel >>  8 ) & 0xFF);
442   red   = (BYTE) (( aPixel >> 16 ) & 0xFF);
443
444   idx = myFreeIndex;
445
446   for ( int i = 2; i < myFreeIndex; ++i )  // avoid color duplication
447
448    if ( PAL -> palPalEntry[ i ].peRed   == red   &&
449         PAL -> palPalEntry[ i ].peGreen == green &&
450         PAL -> palPalEntry[ i ].peBlue  == blue
451    )
452
453     return;
454
455   PAL -> palPalEntry[ idx ].peRed   = red;
456   PAL -> palPalEntry[ idx ].peGreen = green;
457   PAL -> palPalEntry[ idx ].peBlue  = blue;
458   PAL -> palPalEntry[ idx ].peFlags = 0;
459   ++myFreeIndex;
460   ResizePalette (  ( HPALETTE )myPalette, myFreeIndex );
461   SetPaletteEntries (  ( HPALETTE )myPalette, idx, 1, &PAL -> palPalEntry[ idx ]  );
462
463  }  // end if ( myPalette . . . )
464
465 }  // end WNT_GraphicDevice :: SetColor(3)
466
467 void WNT_GraphicDevice :: MapColors (
468                            const Handle( Aspect_ColorMap )& aColorMap,
469                                  Handle( WNT_HColorTable )& aColorTable
470                           ) {
471
472  Aspect_ColorMapEntry entry;
473  Quantity_Color       color;
474  COLORREF             dwColor;
475  Standard_Real        r, g, b;
476  int                  i, index;
477
478  if (  myOpenGLPalette || !IsPaletteDevice ()  )  // readonly palette or no palette
479
480   for ( i = 1; i <= aColorMap -> Size (); ++i ) {
481
482    entry = aColorMap -> Entry ( i );
483    color = entry.Color ();
484    aColorTable -> SetValue (  entry.Index (), SetColor ( color )  );
485
486   }  // end for
487
488  else {  // writable palette
489
490   for ( i = 1; i <= aColorMap -> Size (); ++i ) {
491   
492    entry   = aColorMap -> Entry ( i );
493    color   = entry.Color ();
494    dwColor = aColorTable -> Value ( i );
495    index   = dwColor & 0x01000000 ? dwColor & 0x00FFFFFF : 0xFFFFFFFF;
496
497    if ( index != 0xFFFFFFFF && index < myFreeIndex ) {
498    
499     color.Values ( r, g, b, Quantity_TOC_RGB );
500         PAL -> palPalEntry[ index ].peRed   = ( BYTE )( 255. * r );
501         PAL -> palPalEntry[ index ].peGreen = ( BYTE )( 255. * g );
502         PAL -> palPalEntry[ index ].peBlue  = ( BYTE )( 255. * b );
503    
504    } else
505    
506         aColorTable -> SetValue (  i, SetColor ( color )  );
507    
508   }  // end for
509
510   SetPaletteEntries (
511    ( HPALETTE )myPalette, 0, myFreeIndex, &PAL -> palPalEntry[ 0 ]
512   );
513
514  }  // end else
515
516 }  // WNT_GraphicDevice :: MapColors
517
518 Handle( Aspect_GraphicDriver ) WNT_GraphicDevice :: GraphicDriver () const {
519
520  Handle( Aspect_GraphicDriver ) dummy;
521
522  return dummy;
523
524 }  // WNT_GraphicDevice :: GraphicDriver
525 //***//
526 //*** Function to create RGB color map for use with OpenGL.                 ***//
527 //*** For OpenGL RGB rendering we need to know red, green, & blue           ***//
528 //*** component bit sizes and positions. This program creates an RGB color  ***//
529 //*** cube with a default gamma of 1.4.                                     ***//
530 //*** Unfortunately, because the standard 20 colors in the system palette   ***//
531 //*** cannot be changed, if we select this palette into a display DC,       ***//
532 //*** we will not realize all of the logical palette. The function          ***//
533 //*** changes some of the entries in the logical palette to match enties in ***//
534 //*** the system palette using a least-squares calculation to find which    ***//
535 //*** entries to replace.                                                   ***//
536 //***//
537 static int __fastcall _createColorRamp ( HPALETTE* pal ) {
538
539  int                   i, j;
540  int                   sysPalSize, logPalSize;
541  int                   red_max,  green_max,  blue_max,
542                        red_mask, green_mask, blue_mask;
543  int                   iPf;
544  HDC                   hDC;
545  PIXELFORMATDESCRIPTOR pfd;
546  PPALETTEENTRY         sysPal, colorRamp;
547  PBYTE                 gRed, gGreen, gBlue;
548  BYTE                  inc;
549  LONG                  error, min_error, error_index, delta;
550  double                dv, gamma;
551  char                  buff[ 32 ];
552
553  ZeroMemory (  ( PVOID )&pfd, sizeof ( PIXELFORMATDESCRIPTOR )  );
554
555  pfd.nSize      = sizeof ( PIXELFORMATDESCRIPTOR );
556  pfd.nVersion   = 1;
557  pfd.dwFlags    = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
558                   PFD_DOUBLEBUFFER;
559  pfd.iPixelType = PFD_TYPE_RGBA;
560  pfd.cColorBits = 24;
561  pfd.cDepthBits = 32;
562  pfd.iLayerType = PFD_MAIN_PLANE;
563
564  hDC = GetDC ( NULL );
565
566   iPf = ChoosePixelFormat ( hDC, &pfd );
567   i = DescribePixelFormat (
568        hDC, iPf, sizeof ( PIXELFORMATDESCRIPTOR ), &pfd
569           );
570
571   if ( !i ) {
572
573    ReleaseDC ( NULL, hDC );
574
575    return 0;
576
577   }  // end if
578
579   sysPalSize = GetDeviceCaps ( hDC, NUMCOLORS );
580   logPalSize = 1 << pfd.cColorBits;
581   sysPal     = new PALETTEENTRY[ sysPalSize + logPalSize ];
582   colorRamp  = sysPal + sysPalSize;
583   GetSystemPaletteEntries ( hDC, 0, sysPalSize, sysPal );
584
585  ReleaseDC ( NULL, hDC );
586
587  red_max   = 1 << pfd.cRedBits;
588  green_max = 1 << pfd.cGreenBits;
589  blue_max  = 1 << pfd.cBlueBits;
590
591  red_mask   = red_max   - 1;
592  green_mask     = green_max - 1;
593  blue_mask  = blue_max  - 1;
594
595  gRed   = new BYTE[ red_max + green_max + blue_max ];
596  gGreen = gRed + red_max;
597  gBlue  = gGreen + green_max;
598
599  inc = ( BYTE )(  255.0F / ( float )red_mask  );
600
601  if (  GetEnvironmentVariable ( "CSF_GammaValue", buff, 32 )  ) {
602  
603   gamma = atof ( buff );
604
605   if ( gamma == 0.0 )
606
607    gamma = DEFAULT_GAMMA;
608  
609  } else
610
611   gamma = DEFAULT_GAMMA;
612
613  for ( i = 0; i < red_max; ++i ) {
614
615   gRed[ i ] = ( i * inc ) & 0xFF;
616   dv = ( 255. *  pow ( gRed[ i ] / 255., 1. / gamma ) ) + 0.5;
617   gRed[ i ] = ( BYTE )dv;
618
619  }  // end for
620   
621  inc = ( BYTE )(  255.0F / ( float )green_mask  );
622
623  for ( i = 0; i < green_max; ++i ) {
624
625   gGreen[ i ] = ( i * inc ) & 0xFF;
626   dv = (  255. * pow ( gGreen[ i ] / 255., 1. / gamma )  ) + 0.5;
627   gGreen[ i ] = ( BYTE )dv;
628
629  }  // end for
630
631  inc = ( BYTE )(  255.0F / ( float )blue_mask  );
632
633  for ( i = 0; i < blue_max; ++i ) {
634
635   gBlue[ i ] = ( i * inc ) & 0xFF;
636   dv = (  255. * pow ( gBlue[ i ] / 255., 1. / gamma )  ) + 0.5;
637   gBlue[ i ] = ( BYTE )dv;
638
639  }  // end for
640
641  for ( i = 0; i < logPalSize; ++i ) {
642  
643   colorRamp[ i ].peRed =
644    gRed[   ( i >> pfd.cRedShift   ) & red_mask   ];
645   colorRamp[ i ].peGreen =
646    gGreen[ ( i >> pfd.cGreenShift ) & green_mask ];
647   colorRamp[ i ].peBlue =
648    gBlue[  ( i >> pfd.cBlueShift  ) & blue_mask  ];
649   colorRamp[ i ].peFlags = 0;
650
651  }  // end for
652
653  if ( pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ) {
654          
655   s_SysPalInUse = TRUE;
656
657   for ( i = 1; i < logPalSize - 1; ++i ) colorRamp[ i ].peFlags = PC_NOCOLLAPSE;
658
659  } else {
660
661   for ( i = 0; i < sysPalSize; ++i )
662  
663    for ( j = 0; j < logPalSize; ++j ) 
664
665     if (  sysPal[ i ].peRed   == colorRamp[ j ].peRed &&
666           sysPal[ i ].peGreen == colorRamp[ j ].peRed &&
667               sysPal[ i ].peBlue  == colorRamp[ j ].peRed
668     )
669
670      sysPal[ i ].peFlags = colorRamp[ i ].peFlags = 1;
671
672     else
673
674      sysPal[ i ].peFlags = colorRamp[ i ].peFlags = 0;
675
676   for ( i = 0; i < sysPalSize; ++i ) {
677  
678    if ( sysPal[ i ].peFlags ) continue;
679
680    min_error = MAX_PAL_ERROR;
681
682    for ( j = 0; j < logPalSize; ++j ) {
683   
684     if ( colorRamp[ j ].peFlags ) continue;
685     
686     delta = colorRamp[ j ].peRed - sysPal[ i ].peRed;
687     error = delta * delta;
688     delta = colorRamp[ j ].peGreen - sysPal[ i ].peGreen;
689     error += delta * delta;
690     delta = colorRamp[ j ].peBlue - sysPal[ i ].peBlue;
691     error += delta * delta;
692
693     if ( error < min_error ) {
694    
695          error_index = j;
696          min_error   = error;
697    
698     }  // end if
699
700    }  // end for ( j . . . )
701
702    colorRamp[ error_index ].peRed   = sysPal[ i ].peRed;
703    colorRamp[ error_index ].peGreen = sysPal[ i ].peGreen;
704    colorRamp[ error_index ].peBlue  = sysPal[ i ].peBlue;
705    colorRamp[ error_index ].peFlags = PC_EXPLICIT;
706  
707   }  // end for ( i . . . )
708
709  }  // end else
710
711  ResizePalette ( *pal, logPalSize );
712  SetPaletteEntries ( *pal, 0, logPalSize, colorRamp );
713  
714  delete [] gRed;
715  delete [] sysPal;
716
717  return 1;
718
719 }  // end createColorRamp
720
721 int WNT_SysPalInUse ( void ) {
722
723  return s_SysPalInUse;
724
725 }  // end WNT_SysPalInUse