]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dibutils.cpp
added CreateDDB() and CreatePalette()
[wxWidgets.git] / src / msw / dibutils.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: dibutils.cpp
3// Purpose: Utilities for DIBs
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa
JS
8// Copyright: (c) Microsoft, Julian Smart
9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "dibutils.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
2bda0e17
KB
24#include "wx/setup.h"
25#include "wx/defs.h"
2662e49e 26#include "wx/string.h"
2bda0e17
KB
27#endif
28
29#include <windows.h>
30#include <windowsx.h>
31#include <stdio.h>
3f4a0c5b
VZ
32
33#include "wx/msw/dibutils.h"
2bda0e17
KB
34
35#if defined(__WIN32__)
ce3ed50d 36#if !defined(__MWERKS__) && !defined(__SALFORDC__)
2bda0e17 37 #include <memory.h> // for _fmemcpy()
17dff81c 38#endif
3f4a0c5b 39 #define _huge
2bda0e17
KB
40#ifndef hmemcpy
41 #define hmemcpy memcpy
42#endif
43#endif
44
45#define BFT_ICON 0x4349 /* 'IC' */
46#define BFT_BITMAP 0x4d42 /* 'BM' */
e90c1d2a 47#define BFT_CURSOR 0x5450 /* 'PT(' */
2bda0e17 48
2662e49e 49#ifndef SEEK_CUR
2bda0e17
KB
50/* flags for _lseek */
51#define SEEK_CUR 1
52#define SEEK_END 2
53#define SEEK_SET 0
2662e49e
RR
54#endif
55
56/* Copied from PNGhandler for coompilation with MingW32, RR */
57
58#ifndef GlobalAllocPtr
59#define GlobalPtrHandle(lp) \
60 ((HGLOBAL)GlobalHandle(lp))
61
62#define GlobalLockPtr(lp) \
63 ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
64#define GlobalUnlockPtr(lp) \
65 GlobalUnlock(GlobalPtrHandle(lp))
66
67#define GlobalAllocPtr(flags, cb) \
68 (GlobalLock(GlobalAlloc((flags), (cb))))
69#define GlobalReAllocPtr(lp, cbNew, flags) \
70 (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
71#define GlobalFreePtr(lp) \
72 (GlobalUnlockPtr(lp), (BOOL)GlobalFree(GlobalPtrHandle(lp)))
73#endif
2bda0e17 74
2bda0e17
KB
75/*
76 * Open a DIB file and return a MEMORY DIB, a memory handle containing..
77 *
78 * BITMAP INFO bi
79 * palette data
80 * bits....
81 */
82
ef3ab009 83int wxDibWriteFile(LPTSTR szFile, LPBITMAPINFOHEADER lpbi)
2bda0e17 84{
3f4a0c5b
VZ
85 HFILE fh;
86 OFSTRUCT of;
2bda0e17 87
837e5743 88 fh = OpenFile(wxConvFile.cWX2MB(szFile), &of, OF_WRITE | OF_CREATE);
2bda0e17
KB
89
90 if (!fh) {
1cfa5d8e 91 return 0;
2bda0e17
KB
92 }
93
ef3ab009 94 long size = wxDibSize(lpbi);
2bda0e17
KB
95
96 // write file header
97 BITMAPFILEHEADER bmf;
a0c3c734 98 bmf.bfType = BFT_BITMAP;
2bda0e17
KB
99 bmf.bfSize = sizeof(bmf) + size;
100 bmf.bfReserved1 = 0;
101 bmf.bfReserved2 = 0;
ef3ab009 102 bmf.bfOffBits = sizeof(bmf) + (char FAR*)(wxDibPtr(lpbi)) - (char FAR*)lpbi;
b64f0a5f 103#if 1 // defined( __WATCOMC__) || defined(__VISUALC__) || defined(__SC__) || defined(__SALFORDC__) || defined(__MWERKS__) || wxUSE_NORLANDER_HEADERS
a0c3c734
VZ
104 #define HWRITE_2ND_ARG_TYPE LPCSTR
105#else // don't know who needs this...
106 #define HWRITE_2ND_ARG_TYPE LPBYTE
107#endif
108
109 if ( _hwrite(fh, (HWRITE_2ND_ARG_TYPE)(&bmf), sizeof(bmf)) < 0 ||
110 _hwrite(fh, (HWRITE_2ND_ARG_TYPE)lpbi, size) < 0 )
111 {
3f4a0c5b 112 _lclose(fh);
3f4a0c5b 113 return 0;
2bda0e17 114 }
a0c3c734
VZ
115
116#undef HWRITE_2ND_ARG_TYPE
2bda0e17
KB
117
118 _lclose(fh);
119 return 1;
120}
121
ef3ab009 122PDIB wxDibOpenFile(LPTSTR szFile)
2bda0e17 123{
3f4a0c5b
VZ
124 HFILE fh;
125 DWORD dwLen;
126 DWORD dwBits;
127 PDIB pdib;
128 LPVOID p;
129 OFSTRUCT of;
2bda0e17 130
d66dcb60 131#if defined(__WIN32__)
3f4a0c5b 132 #define GetCurrentInstance() GetModuleHandle(NULL)
2bda0e17 133#else
3f4a0c5b 134 #define GetCurrentInstance() (HINSTANCE)SELECTOROF((LPVOID)&of)
2bda0e17
KB
135#endif
136
837e5743 137 fh = OpenFile(wxConvFile.cWX2MB(szFile), &of, OF_READ);
2bda0e17 138
3f4a0c5b
VZ
139 if (fh == -1)
140 {
141 HRSRC h;
2bda0e17
KB
142
143 // TODO: Unicode version
62448488 144#ifdef __WIN16__
3f4a0c5b 145 h = FindResource(GetCurrentInstance(), szFile, RT_BITMAP);
837e5743
OK
146#elif wxUSE_UNICODE
147 h = FindResourceW(GetCurrentInstance(), szFile, RT_BITMAP);
62448488 148#else
3f4a0c5b 149 h = FindResourceA(GetCurrentInstance(), szFile, RT_BITMAP);
62448488 150#endif
2bda0e17 151
62448488 152#if defined(__WIN32__)
3f4a0c5b
VZ
153 //!!! can we call GlobalFree() on this? is it the right format.
154 //!!! can we write to this resource?
155 if (h)
156 return (PDIB)LockResource(LoadResource(GetCurrentInstance(), h));
2bda0e17 157#else
3f4a0c5b
VZ
158 if (h)
159 fh = AccessResource(GetCurrentInstance(), h);
2bda0e17 160#endif
3f4a0c5b 161 }
2bda0e17 162
3f4a0c5b
VZ
163 if (fh == -1)
164 return NULL;
2bda0e17 165
ef3ab009 166 pdib = wxDibReadBitmapInfo(fh);
2bda0e17 167
3f4a0c5b
VZ
168 if (!pdib)
169 return NULL;
2bda0e17
KB
170
171 /* How much memory do we need to hold the DIB */
172
173 dwBits = pdib->biSizeImage;
ef3ab009 174 dwLen = pdib->biSize + wxDibPaletteSize(pdib) + dwBits;
2bda0e17
KB
175
176 /* Can we get more memory? */
177
3f4a0c5b 178 p = GlobalReAllocPtr(pdib,dwLen,0);
2bda0e17
KB
179
180 if (!p)
181 {
3f4a0c5b 182 GlobalFreePtr(pdib);
2bda0e17
KB
183 pdib = NULL;
184 }
185 else
186 {
187 pdib = (PDIB)p;
188 }
189
190 if (pdib)
191 {
3f4a0c5b 192 /* read in the bits */
ef3ab009 193 _hread(fh, (LPBYTE)pdib + (UINT)pdib->biSize + wxDibPaletteSize(pdib), dwBits);
2bda0e17
KB
194 }
195
196 _lclose(fh);
197
198 return pdib;
199}
200
201
202/*
203 * ReadDibBitmapInfo()
204 *
205 * Will read a file in DIB format and return a global HANDLE to its
206 * BITMAPINFO. This function will work with both "old" and "new"
207 * bitmap formats, but will always return a "new" BITMAPINFO.
208 */
209
ef3ab009 210PDIB wxDibReadBitmapInfo(HFILE fh)
2bda0e17
KB
211{
212 DWORD off;
2bda0e17
KB
213 int size;
214 int i;
215 int nNumColors;
216
217 RGBQUAD FAR *pRgb;
218 BITMAPINFOHEADER bi;
219 BITMAPCOREHEADER bc;
220 BITMAPFILEHEADER bf;
221 PDIB pdib;
222
223 if (fh == -1)
224 return NULL;
225
226 off = _llseek(fh,0L,SEEK_CUR);
227
228 if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
f7f50f49 229 return NULL;
2bda0e17
KB
230
231 /*
232 * do we have a RC HEADER?
233 */
234 if (bf.bfType != BFT_BITMAP)
235 {
236 bf.bfOffBits = 0L;
237 _llseek(fh,off,SEEK_SET);
238 }
239
240 if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
6703082e 241 return NULL;
2bda0e17
KB
242
243 /*
244 * what type of bitmap info is this?
245 */
246 switch (size = (int)bi.biSize)
247 {
248 default:
249 case sizeof(BITMAPINFOHEADER):
250 break;
251
252 case sizeof(BITMAPCOREHEADER):
253 bc = *(BITMAPCOREHEADER*)&bi;
254 bi.biSize = sizeof(BITMAPINFOHEADER);
255 bi.biWidth = (DWORD)bc.bcWidth;
256 bi.biHeight = (DWORD)bc.bcHeight;
33ac7e6f
KB
257 bi.biPlanes = (WORD)bc.bcPlanes;
258 bi.biBitCount = (WORD)bc.bcBitCount;
2bda0e17
KB
259 bi.biCompression = BI_RGB;
260 bi.biSizeImage = 0;
261 bi.biXPelsPerMeter = 0;
262 bi.biYPelsPerMeter = 0;
263 bi.biClrUsed = 0;
264 bi.biClrImportant = 0;
265
266 _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
267
268 break;
269 }
270
ef3ab009 271 nNumColors = wxDibNumColors(&bi);
2bda0e17
KB
272
273#if 0
274 if (bi.biSizeImage == 0)
275 bi.biSizeImage = DibSizeImage(&bi);
276
277 if (bi.biClrUsed == 0)
ef3ab009 278 bi.biClrUsed = wxDibNumColors(&bi);
2bda0e17 279#else
ef3ab009 280 wxFixBitmapInfo(&bi);
2bda0e17
KB
281#endif
282
283 pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
284
285 if (!pdib)
286 return NULL;
287
288 *pdib = bi;
289
ef3ab009 290 pRgb = wxDibColors(pdib);
2bda0e17
KB
291
292 if (nNumColors)
293 {
294 if (size == sizeof(BITMAPCOREHEADER))
295 {
296 /*
297 * convert a old color table (3 byte entries) to a new
298 * color table (4 byte entries)
299 */
300 _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE));
301
302 for (i=nNumColors-1; i>=0; i--)
303 {
304 RGBQUAD rgb;
305
306 rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
307 rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
308 rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
309 rgb.rgbReserved = (BYTE)0;
310
311 pRgb[i] = rgb;
312 }
313 }
314 else
315 {
316 _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
317 }
318 }
319
320 if (bf.bfOffBits != 0L)
321 _llseek(fh,off + bf.bfOffBits,SEEK_SET);
322
323 return pdib;
324}
325
326/*
327 * DibSetUsage(hdib,hpal,wUsage)
328 *
329 * Modifies the color table of the passed DIB for use with the wUsage
330 * parameter specifed.
331 *
332 * if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
333 * if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
334 * in the passed palette
335 */
336
ef3ab009 337BOOL wxDibSetUsage(PDIB pdib, HPALETTE hpal,UINT wUsage)
2bda0e17
KB
338{
339 PALETTEENTRY ape[256];
340 RGBQUAD FAR * pRgb;
341 WORD FAR * pw;
342 int nColors;
343 int n;
344
345 if (hpal == NULL)
346 hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
347
348 if (!pdib)
349 return FALSE;
350
ef3ab009 351 nColors = wxDibNumColors(pdib);
a0c3c734 352
ef3ab009 353 if (nColors == 3 && wxDibCompression(pdib) == BI_BITFIELDS)
2bda0e17
KB
354 nColors = 0;
355
356 if (nColors > 0)
357 {
ef3ab009 358 pRgb = wxDibColors(pdib);
2bda0e17
KB
359
360 switch (wUsage)
361 {
362 //
363 // Set the DIB color table to palette indexes
364 //
365 case DIB_PAL_COLORS:
366 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
367 *pw = n;
368 break;
369
370 //
371 // Set the DIB color table to RGBQUADS
372 //
373 default:
374 case DIB_RGB_COLORS:
375 nColors = (nColors < 256) ? nColors: 256;
376
377 GetPaletteEntries(hpal,0,nColors,ape);
378
379 for (n=0; n<nColors; n++)
380 {
381 pRgb[n].rgbRed = ape[n].peRed;
382 pRgb[n].rgbGreen = ape[n].peGreen;
383 pRgb[n].rgbBlue = ape[n].peBlue;
384 pRgb[n].rgbReserved = 0;
385 }
386 break;
387 }
388 }
389 return TRUE;
390}
391
392/*
393 * DibCreate(bits, dx, dy)
394 *
395 * Creates a new packed DIB with the given dimensions and the
396 * given number of bits per pixel
397 */
398
ef3ab009 399PDIB wxDibCreate(int bits, int dx, int dy)
2bda0e17
KB
400{
401 LPBITMAPINFOHEADER lpbi ;
402 DWORD dwSizeImage;
403 int i;
404 DWORD FAR *pdw;
405
406 dwSizeImage = dy*(DWORD)((dx*bits/8+3)&~3);
407
408 lpbi = (PDIB)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
409
410 if (lpbi == NULL)
411 return NULL;
412
413 lpbi->biSize = sizeof(BITMAPINFOHEADER) ;
414 lpbi->biWidth = dx;
415 lpbi->biHeight = dy;
416 lpbi->biPlanes = 1;
417 lpbi->biBitCount = bits ;
418 lpbi->biCompression = BI_RGB ;
419 lpbi->biSizeImage = dwSizeImage;
420 lpbi->biXPelsPerMeter = 0 ;
421 lpbi->biYPelsPerMeter = 0 ;
422 lpbi->biClrUsed = 0 ;
423 lpbi->biClrImportant = 0 ;
424
425 if (bits == 4)
426 lpbi->biClrUsed = 16;
427
428 else if (bits == 8)
429 lpbi->biClrUsed = 256;
430
431 pdw = (DWORD FAR *)((LPBYTE)lpbi+(int)lpbi->biSize);
432
433 for (i=0; i<(int)lpbi->biClrUsed/16; i++)
434 {
435 *pdw++ = 0x00000000; // 0000 black
436 *pdw++ = 0x00800000; // 0001 dark red
437 *pdw++ = 0x00008000; // 0010 dark green
3f4a0c5b 438 *pdw++ = 0x00808000; // 0011 mustard
2bda0e17
KB
439 *pdw++ = 0x00000080; // 0100 dark blue
440 *pdw++ = 0x00800080; // 0101 purple
441 *pdw++ = 0x00008080; // 0110 dark turquoise
442 *pdw++ = 0x00C0C0C0; // 1000 gray
443 *pdw++ = 0x00808080; // 0111 dark gray
444 *pdw++ = 0x00FF0000; // 1001 red
445 *pdw++ = 0x0000FF00; // 1010 green
3f4a0c5b 446 *pdw++ = 0x00FFFF00; // 1011 yellow
2bda0e17
KB
447 *pdw++ = 0x000000FF; // 1100 blue
448 *pdw++ = 0x00FF00FF; // 1101 pink (magenta)
449 *pdw++ = 0x0000FFFF; // 1110 cyan
450 *pdw++ = 0x00FFFFFF; // 1111 white
451 }
452
453 return (PDIB)lpbi;
454}
455
456static void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
457{
458 DWORD dw;
459
460#ifdef __cplusplus
461 for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
462#else
463 for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
464#endif
465 *pb = xlat[*pb];
466}
467
468static void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
469{
470 DWORD dw;
471
472#ifdef __cplusplus
473 for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
474#else
475 for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
476#endif
477 *pb = (BYTE)(xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4));
478}
479
480#define RLE_ESCAPE 0
481#define RLE_EOL 0
482#define RLE_EOF 1
483#define RLE_JMP 2
484
33ac7e6f 485static void xlatRle8(BYTE FAR *pb, DWORD WXUNUSED(dwSize), BYTE FAR *xlat)
2bda0e17
KB
486{
487 BYTE cnt;
488 BYTE b;
489 BYTE _huge *prle = pb;
490
491 for(;;)
492 {
493 cnt = *prle++;
494 b = *prle;
495
496 if (cnt == RLE_ESCAPE)
497 {
498 prle++;
499
500 switch (b)
501 {
502 case RLE_EOF:
503 return;
504
505 case RLE_EOL:
506 break;
507
508 case RLE_JMP:
509 prle++; // skip dX
510 prle++; // skip dY
511 break;
512
513 default:
514 cnt = b;
515 for (b=0; b<cnt; b++,prle++)
516 *prle = xlat[*prle];
517
518 if (cnt & 1)
519 prle++;
520
521 break;
522 }
523 }
524 else
525 {
526 *prle++ = xlat[b];
527 }
528 }
529}
530
33ac7e6f 531static void xlatRle4(BYTE FAR *WXUNUSED(pb), DWORD WXUNUSED(dwSize), BYTE FAR *WXUNUSED(xlat))
2bda0e17
KB
532{
533}
534
535static void hmemmove(BYTE _huge *d, BYTE _huge *s, LONG len)
536{
537 d += len-1;
538 s += len-1;
539
540 while (len--)
541 *d-- = *s--;
542}
543
544/*
545 * DibMapToPalette(pdib, hpal)
546 *
547 * Map the colors of the DIB, using GetNearestPaletteIndex, to
548 * the colors of the given palette.
549 */
550
ef3ab009 551BOOL wxDibMapToPalette(PDIB pdib, HPALETTE hpal)
2bda0e17 552{
3f4a0c5b
VZ
553 LPBITMAPINFOHEADER lpbi;
554 PALETTEENTRY pe;
555 int n;
556 int nDibColors;
557 int nPalColors=0;
558 BYTE FAR * lpBits;
559 RGBQUAD FAR * lpRgb;
560 BYTE xlat[256];
561 DWORD SizeImage;
562
563 if (!hpal || !pdib)
564 return FALSE;
565
566 lpbi = (LPBITMAPINFOHEADER)pdib;
ef3ab009 567 lpRgb = wxDibColors(pdib);
3f4a0c5b
VZ
568
569 GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
ef3ab009 570 nDibColors = wxDibNumColors(pdib);
3f4a0c5b
VZ
571
572 if ((SizeImage = lpbi->biSizeImage) == 0)
ef3ab009 573 SizeImage = wxDibSizeImage(lpbi);
3f4a0c5b
VZ
574
575 //
576 // build a xlat table. from the current DIB colors to the given
577 // palette.
578 //
579 for (n=0; n<nDibColors; n++)
580 xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
581
ef3ab009 582 lpBits = (LPBYTE)wxDibPtr(lpbi);
3f4a0c5b
VZ
583 lpbi->biClrUsed = nPalColors;
584
585 //
586 // re-size the DIB
587 //
588 if (nPalColors > nDibColors)
589 {
590 GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
ef3ab009
UJ
591 hmemmove((BYTE _huge *)wxDibPtr(lpbi), (BYTE _huge *)lpBits, SizeImage);
592 lpBits = (LPBYTE)wxDibPtr(lpbi);
3f4a0c5b
VZ
593 }
594 else if (nPalColors < nDibColors)
595 {
ef3ab009 596 hmemcpy(wxDibPtr(lpbi), lpBits, SizeImage);
3f4a0c5b 597 GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
ef3ab009 598 lpBits = (LPBYTE)wxDibPtr(lpbi);
3f4a0c5b
VZ
599 }
600
601 //
602 // translate the DIB bits
603 //
604 switch (lpbi->biCompression)
605 {
606 case BI_RLE8:
607 xlatRle8(lpBits, SizeImage, xlat);
608 break;
609
610 case BI_RLE4:
611 xlatRle4(lpBits, SizeImage, xlat);
612 break;
2bda0e17
KB
613
614 case BI_RGB:
3f4a0c5b 615 if (lpbi->biBitCount == 8)
2bda0e17
KB
616 xlatClut8(lpBits, SizeImage, xlat);
617 else
618 xlatClut4(lpBits, SizeImage, xlat);
619 break;
620 }
621
622 //
623 // Now copy the RGBs in the logical palette to the dib color table
624 //
625 for (n=0; n<nPalColors; n++)
626 {
627 GetPaletteEntries(hpal,n,1,&pe);
628
629 lpRgb[n].rgbRed = pe.peRed;
3f4a0c5b
VZ
630 lpRgb[n].rgbGreen = pe.peGreen;
631 lpRgb[n].rgbBlue = pe.peBlue;
632 lpRgb[n].rgbReserved = (BYTE)0;
633 }
2bda0e17 634
3f4a0c5b 635 return TRUE;
2bda0e17
KB
636}
637
638
ef3ab009 639HPALETTE wxMakePalette(const BITMAPINFO FAR* Info, UINT flags)
2bda0e17
KB
640{
641 HPALETTE hPalette;
2662e49e 642 const RGBQUAD FAR* rgb = Info->bmiColors;
2bda0e17 643
33ac7e6f 644 WORD nColors = (WORD)Info->bmiHeader.biClrUsed;
2bda0e17 645 if (nColors) {
3f4a0c5b
VZ
646 LOGPALETTE* logPal = (LOGPALETTE*)
647 new BYTE[sizeof(LOGPALETTE) + (nColors-1)*sizeof(PALETTEENTRY)];
648
649 logPal->palVersion = 0x300; // Windows 3.0 version
650 logPal->palNumEntries = nColors;
48c12cb1 651 for (WORD n = 0; n < nColors; n++) {
3f4a0c5b
VZ
652 logPal->palPalEntry[n].peRed = rgb[n].rgbRed;
653 logPal->palPalEntry[n].peGreen = rgb[n].rgbGreen;
654 logPal->palPalEntry[n].peBlue = rgb[n].rgbBlue;
655 logPal->palPalEntry[n].peFlags = (BYTE)flags;
656 }
657 hPalette = ::CreatePalette(logPal);
658 delete logPal;
2bda0e17 659 } else
3f4a0c5b 660 hPalette = 0;
2bda0e17
KB
661
662 return hPalette;
663}
664