]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bitmap.cpp
Project file corrections, doc corrections
[wxWidgets.git] / src / msw / bitmap.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: bitmap.cpp
3// Purpose: wxBitmap
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
1d792928 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
10fcf31a
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
10fcf31a 21 #pragma implementation "bitmap.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
10fcf31a 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
10fcf31a
VZ
32 #include <stdio.h>
33
34 #include "wx/list.h"
35 #include "wx/utils.h"
36 #include "wx/app.h"
37 #include "wx/palette.h"
38 #include "wx/dcmemory.h"
39 #include "wx/bitmap.h"
40 #include "wx/icon.h"
2bda0e17
KB
41#endif
42
43#include "wx/msw/private.h"
1d792928
VZ
44#include "wx/log.h"
45
04ef50df 46#if !defined(__WXMICROWIN__)
2bda0e17 47#include "wx/msw/dib.h"
04ef50df
JS
48#endif
49
b75dd496 50#include "wx/image.h"
66e23ad2 51#include "wx/xpmdecod.h"
2bda0e17 52
3c1a88d8
VZ
53// missing from mingw32 header
54#ifndef CLR_INVALID
55 #define CLR_INVALID ((COLORREF)-1)
56#endif // no CLR_INVALID
57
10fcf31a
VZ
58// ----------------------------------------------------------------------------
59// macros
60// ----------------------------------------------------------------------------
61
4b7f2165
VZ
62IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
63IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
6d167489 64
4b7f2165 65IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
2bda0e17 66
10fcf31a
VZ
67// ============================================================================
68// implementation
69// ============================================================================
70
71// ----------------------------------------------------------------------------
72// wxBitmapRefData
73// ----------------------------------------------------------------------------
74
75wxBitmapRefData::wxBitmapRefData()
2bda0e17 76{
6d167489
VZ
77 m_quality = 0;
78 m_selectedInto = NULL;
79 m_numColors = 0;
80 m_bitmapMask = NULL;
340196c0 81 m_hBitmap = (WXHBITMAP) NULL;
2bda0e17
KB
82}
83
6d167489 84void wxBitmapRefData::Free()
2bda0e17 85{
d59ceba5
VZ
86 wxASSERT_MSG( !m_selectedInto,
87 wxT("deleting bitmap still selected into wxMemoryDC") );
2bda0e17 88
d59ceba5 89 if ( m_hBitmap)
6d167489
VZ
90 {
91 if ( !::DeleteObject((HBITMAP)m_hBitmap) )
92 {
f6bcfd97 93 wxLogLastError(wxT("DeleteObject(hbitmap)"));
6d167489
VZ
94 }
95 }
e7003166 96
6d167489
VZ
97 delete m_bitmapMask;
98 m_bitmapMask = NULL;
2bda0e17
KB
99}
100
10fcf31a 101// ----------------------------------------------------------------------------
6d167489 102// wxBitmap creation
10fcf31a
VZ
103// ----------------------------------------------------------------------------
104
4fe5383d
VZ
105// this function should be called from all wxBitmap ctors
106void wxBitmap::Init()
2bda0e17 107{
4fe5383d 108 // m_refData = NULL; done in the base class ctor
2bda0e17 109
07cf98cb
VZ
110 if ( wxTheBitmapList )
111 wxTheBitmapList->AddBitmap(this);
4fe5383d
VZ
112}
113
6d167489
VZ
114#ifdef __WIN32__
115
116bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon)
117{
04ef50df 118#ifndef __WXMICROWIN__
6d167489
VZ
119 // it may be either HICON or HCURSOR
120 HICON hicon = (HICON)icon.GetHandle();
121
122 ICONINFO iconInfo;
123 if ( !::GetIconInfo(hicon, &iconInfo) )
124 {
f6bcfd97 125 wxLogLastError(wxT("GetIconInfo"));
6d167489
VZ
126
127 return FALSE;
128 }
129
130 wxBitmapRefData *refData = new wxBitmapRefData;
131 m_refData = refData;
132
d9c8e68e
VZ
133 int w = icon.GetWidth(),
134 h = icon.GetHeight();
135
136 refData->m_width = w;
137 refData->m_height = h;
6d167489
VZ
138 refData->m_depth = wxDisplayDepth();
139
140 refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor;
d9c8e68e
VZ
141
142 // the mask returned by GetIconInfo() is inversed compared to the usual
143 // wxWin convention
4b7f2165
VZ
144 refData->m_bitmapMask = new wxMask((WXHBITMAP)
145 wxInvertMask(iconInfo.hbmMask, w, h));
6d167489 146
68f36a2c
VZ
147
148 // delete the old one now as we don't need it any more
149 ::DeleteObject(iconInfo.hbmMask);
150
6d167489
VZ
151#if WXWIN_COMPATIBILITY_2
152 refData->m_ok = TRUE;
153#endif // WXWIN_COMPATIBILITY_2
154
155 return TRUE;
04ef50df
JS
156#else
157 return FALSE;
158#endif
6d167489
VZ
159}
160
161#endif // Win32
162
163bool wxBitmap::CopyFromCursor(const wxCursor& cursor)
4fe5383d
VZ
164{
165 UnRef();
07cf98cb 166
6d167489 167 if ( !cursor.Ok() )
4fe5383d 168 return FALSE;
07cf98cb 169
6d167489
VZ
170#ifdef __WIN16__
171 wxFAIL_MSG( _T("don't know how to convert cursor to bitmap") );
172
173 return FALSE;
8f177c8e 174#else
6d167489 175 return CopyFromIconOrCursor(cursor);
8f177c8e 176#endif // Win16
6d167489
VZ
177}
178
179bool wxBitmap::CopyFromIcon(const wxIcon& icon)
180{
181 UnRef();
07cf98cb 182
6d167489
VZ
183 if ( !icon.Ok() )
184 return FALSE;
4fe5383d
VZ
185
186 // GetIconInfo() doesn't exist under Win16 and I don't know any other way
187 // to create a bitmap from icon there - but using this way we won't have
188 // the mask (FIXME)
189#ifdef __WIN16__
6d167489
VZ
190 int width = icon.GetWidth(),
191 height = icon.GetHeight();
192
4fe5383d 193 // copy the icon to the bitmap
6d167489 194 ScreenHDC hdcScreen;
4fe5383d
VZ
195 HDC hdc = ::CreateCompatibleDC(hdcScreen);
196 HBITMAP hbitmap = ::CreateCompatibleBitmap(hdcScreen, width, height);
07cf98cb
VZ
197 HBITMAP hbmpOld = (HBITMAP)::SelectObject(hdc, hbitmap);
198
6d167489 199 ::DrawIcon(hdc, 0, 0, GetHiconOf(icon));
07cf98cb
VZ
200
201 ::SelectObject(hdc, hbmpOld);
202 ::DeleteDC(hdc);
4fe5383d 203
6d167489
VZ
204 wxBitmapRefData *refData = new wxBitmapRefData;
205 m_refData = refData;
4fe5383d 206
6d167489
VZ
207 refData->m_width = width;
208 refData->m_height = height;
209 refData->m_depth = wxDisplayDepth();
07cf98cb 210
6d167489 211 refData->m_hBitmap = (WXHBITMAP)hbitmap;
07cf98cb 212
6d167489
VZ
213#if WXWIN_COMPATIBILITY_2
214 refData->m_ok = TRUE;
215#endif // WXWIN_COMPATIBILITY_2
222594ea 216
4fe5383d 217 return TRUE;
6d167489
VZ
218#else // Win32
219 return CopyFromIconOrCursor(icon);
220#endif // Win16/Win32
10fcf31a
VZ
221}
222
223wxBitmap::~wxBitmap()
2bda0e17
KB
224{
225 if (wxTheBitmapList)
226 wxTheBitmapList->DeleteObject(this);
227}
228
5bd3a2da 229wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
2bda0e17 230{
4fe5383d 231 Init();
2bda0e17 232
04ef50df 233#ifndef __WXMICROWIN__
6d167489
VZ
234 wxBitmapRefData *refData = new wxBitmapRefData;
235 m_refData = refData;
2bda0e17 236
5bd3a2da
VZ
237 refData->m_width = width;
238 refData->m_height = height;
239 refData->m_depth = depth;
6d167489
VZ
240 refData->m_numColors = 0;
241 refData->m_selectedInto = NULL;
2bda0e17 242
5bd3a2da
VZ
243 char *data;
244 if ( depth == 1 )
245 {
246 // we assume that it is in XBM format which is not quite the same as
247 // the format CreateBitmap() wants because the order of bytes in the
248 // line is inversed!
4d24ece7
VZ
249 const size_t bytesPerLine = (width + 7) / 8;
250 const size_t padding = bytesPerLine % 2;
251 const size_t len = height * ( padding + bytesPerLine );
5bd3a2da
VZ
252 data = (char *)malloc(len);
253 const char *src = bits;
254 char *dst = data;
255
256 for ( int rows = 0; rows < height; rows++ )
257 {
0765adca 258 for ( size_t cols = 0; cols < bytesPerLine; cols++ )
5bd3a2da 259 {
0765adca
VZ
260 unsigned char val = *src++;
261 unsigned char reversed = 0;
262
263 for ( int bits = 0; bits < 8; bits++)
264 {
265 reversed <<= 1;
266 reversed |= (val & 0x01);
267 val >>= 1;
268 }
269 *dst++ = reversed;
5bd3a2da
VZ
270 }
271
272 if ( padding )
273 *dst++ = 0;
5bd3a2da
VZ
274 }
275 }
276 else
277 {
278 // bits should already be in Windows standard format
279 data = (char *)bits; // const_cast is harmless
280 }
281
282 HBITMAP hbmp = ::CreateBitmap(width, height, 1, depth, data);
6d167489
VZ
283 if ( !hbmp )
284 {
f6bcfd97 285 wxLogLastError(wxT("CreateBitmap"));
6d167489 286 }
2bda0e17 287
5bd3a2da
VZ
288 if ( data != bits )
289 {
290 free(data);
291 }
292
6d167489 293 SetHBITMAP((WXHBITMAP)hbmp);
04ef50df 294#endif
2bda0e17
KB
295}
296
2fd284a4 297// Create from XPM data
4b7f2165 298bool wxBitmap::CreateFromXpm(const char **data)
2fd284a4 299{
66e23ad2 300#if wxUSE_IMAGE && wxUSE_XPM
4fe5383d
VZ
301 Init();
302
66e23ad2 303 wxCHECK_MSG( data != NULL, FALSE, wxT("invalid bitmap data") )
4d24ece7 304
66e23ad2
VS
305 wxXPMDecoder decoder;
306 wxImage img = decoder.ReadData(data);
307 wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid bitmap data") )
4d24ece7 308
c59b4b01 309 *this = wxBitmap(img);
66e23ad2
VS
310 return TRUE;
311#else
4d24ece7 312 return FALSE;
66e23ad2 313#endif
2fd284a4
JS
314}
315
debe6624 316wxBitmap::wxBitmap(int w, int h, int d)
2bda0e17 317{
4fe5383d 318 Init();
2bda0e17 319
4fe5383d 320 (void)Create(w, h, d);
2bda0e17
KB
321}
322
debe6624 323wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
2bda0e17 324{
4fe5383d 325 Init();
2bda0e17 326
6d167489 327 (void)Create(data, type, width, height, depth);
2bda0e17
KB
328}
329
2aeec9ec 330wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
2bda0e17 331{
4fe5383d 332 Init();
2bda0e17 333
4fe5383d 334 LoadFile(filename, (int)type);
2bda0e17
KB
335}
336
debe6624 337bool wxBitmap::Create(int w, int h, int d)
2bda0e17 338{
04ef50df 339#ifndef __WXMICROWIN__
6d167489
VZ
340 UnRef();
341
342 m_refData = new wxBitmapRefData;
343
344 GetBitmapData()->m_width = w;
345 GetBitmapData()->m_height = h;
346 GetBitmapData()->m_depth = d;
347
348 HBITMAP hbmp;
349
350 if ( d > 0 )
351 {
352 hbmp = ::CreateBitmap(w, h, 1, d, NULL);
353 if ( !hbmp )
354 {
f6bcfd97 355 wxLogLastError(wxT("CreateBitmap"));
6d167489
VZ
356 }
357 }
358 else
359 {
360 ScreenHDC dc;
361 hbmp = ::CreateCompatibleBitmap(dc, w, h);
362 if ( !hbmp )
363 {
f6bcfd97 364 wxLogLastError(wxT("CreateCompatibleBitmap"));
6d167489
VZ
365 }
366
367 GetBitmapData()->m_depth = wxDisplayDepth();
368 }
2bda0e17 369
6d167489 370 SetHBITMAP((WXHBITMAP)hbmp);
2bda0e17 371
6d167489
VZ
372#if WXWIN_COMPATIBILITY_2
373 GetBitmapData()->m_ok = hbmp != 0;
374#endif // WXWIN_COMPATIBILITY_2
6d167489 375 return Ok();
04ef50df
JS
376#else
377 return FALSE;
378#endif
2bda0e17
KB
379}
380
6d51f220
VZ
381// ----------------------------------------------------------------------------
382// wxImage to/from conversions
383// ----------------------------------------------------------------------------
384
385#if wxUSE_IMAGE
386
fec19ea9
VS
387bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
388{
8cb172b4
JS
389#ifdef __WXMICROWIN__
390 // TODO
391 return FALSE;
392#else
fec19ea9
VS
393 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
394
395 m_refData = new wxBitmapRefData();
396
397 // sizeLimit is the MS upper limit for the DIB size
398#ifdef WIN32
399 int sizeLimit = 1024*768*3;
400#else
401 int sizeLimit = 0x7fff ;
402#endif
403
404 // width and height of the device-dependent bitmap
405 int width = image.GetWidth();
406 int bmpHeight = image.GetHeight();
407
408 // calc the number of bytes per scanline and padding
409 int bytePerLine = width*3;
410 int sizeDWORD = sizeof( DWORD );
411 int lineBoundary = bytePerLine % sizeDWORD;
412 int padding = 0;
413 if( lineBoundary > 0 )
414 {
415 padding = sizeDWORD - lineBoundary;
416 bytePerLine += padding;
417 }
418 // calc the number of DIBs and heights of DIBs
419 int numDIB = 1;
420 int hRemain = 0;
421 int height = sizeLimit/bytePerLine;
422 if( height >= bmpHeight )
423 height = bmpHeight;
424 else
425 {
426 numDIB = bmpHeight / height;
427 hRemain = bmpHeight % height;
428 if( hRemain >0 ) numDIB++;
429 }
430
431 // set bitmap parameters
c447ce17 432 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") );
fec19ea9
VS
433 SetWidth( width );
434 SetHeight( bmpHeight );
435 if (depth == -1) depth = wxDisplayDepth();
436 SetDepth( depth );
437
19193a2c
KB
438 // Copy the palette from the source image
439 SetPalette(image.GetPalette());
440
fec19ea9
VS
441 // create a DIB header
442 int headersize = sizeof(BITMAPINFOHEADER);
443 BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize );
097aeb99 444 wxCHECK_MSG( lpDIBh, FALSE, wxT("could not allocate memory for DIB header") );
fec19ea9
VS
445 // Fill in the DIB header
446 lpDIBh->bmiHeader.biSize = headersize;
447 lpDIBh->bmiHeader.biWidth = (DWORD)width;
448 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
449 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
450 // the general formula for biSizeImage:
451 // ( ( ( ((DWORD)width*24) +31 ) & ~31 ) >> 3 ) * height;
452 lpDIBh->bmiHeader.biPlanes = 1;
453 lpDIBh->bmiHeader.biBitCount = 24;
454 lpDIBh->bmiHeader.biCompression = BI_RGB;
455 lpDIBh->bmiHeader.biClrUsed = 0;
456 // These seem not really needed for our purpose here.
457 lpDIBh->bmiHeader.biClrImportant = 0;
458 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
459 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
460 // memory for DIB data
461 unsigned char *lpBits;
462 lpBits = (unsigned char *)malloc( lpDIBh->bmiHeader.biSizeImage );
463 if( !lpBits )
464 {
465 wxFAIL_MSG( wxT("could not allocate memory for DIB") );
466 free( lpDIBh );
467 return FALSE;
468 }
469
470 // create and set the device-dependent bitmap
471 HDC hdc = ::GetDC(NULL);
472 HDC memdc = ::CreateCompatibleDC( hdc );
473 HBITMAP hbitmap;
474 hbitmap = ::CreateCompatibleBitmap( hdc, width, bmpHeight );
475 ::SelectObject( memdc, hbitmap);
476
d275c7eb 477#if wxUSE_PALETTE
fec19ea9
VS
478 HPALETTE hOldPalette = 0;
479 if (image.GetPalette().Ok())
480 {
481 hOldPalette = ::SelectPalette(memdc, (HPALETTE) image.GetPalette().GetHPALETTE(), FALSE);
482 ::RealizePalette(memdc);
483 }
d275c7eb 484#endif // wxUSE_PALETTE
fec19ea9
VS
485
486 // copy image data into DIB data and then into DDB (in a loop)
487 unsigned char *data = image.GetData();
488 int i, j, n;
489 int origin = 0;
490 unsigned char *ptdata = data;
491 unsigned char *ptbits;
492
493 for( n=0; n<numDIB; n++ )
494 {
495 if( numDIB > 1 && n == numDIB-1 && hRemain > 0 )
496 {
497 // redefine height and size of the (possibly) last smaller DIB
498 // memory is not reallocated
499 height = hRemain;
500 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
501 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
502 }
503 ptbits = lpBits;
504
505 for( j=0; j<height; j++ )
506 {
507 for( i=0; i<width; i++ )
508 {
509 *(ptbits++) = *(ptdata+2);
510 *(ptbits++) = *(ptdata+1);
511 *(ptbits++) = *(ptdata );
512 ptdata += 3;
513 }
514 for( i=0; i< padding; i++ ) *(ptbits++) = 0;
515 }
516 ::StretchDIBits( memdc, 0, origin, width, height,\
517 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
518 origin += height;
519 // if numDIB = 1, lines below can also be used
520 // hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
521 // The above line is equivalent to the following two lines.
522 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
523 // ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
524 // or the following lines
525 // hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
526 // HDC memdc = ::CreateCompatibleDC( hdc );
527 // ::SelectObject( memdc, hbitmap);
528 // ::SetDIBitsToDevice( memdc, 0, 0, width, height,
529 // 0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
530 // ::SelectObject( memdc, 0 );
531 // ::DeleteDC( memdc );
532 }
533 SetHBITMAP( (WXHBITMAP) hbitmap );
534
d275c7eb 535#if wxUSE_PALETTE
fec19ea9
VS
536 if (hOldPalette)
537 SelectPalette(memdc, hOldPalette, FALSE);
d275c7eb 538#endif // wxUSE_PALETTE
fec19ea9
VS
539
540 // similarly, created an mono-bitmap for the possible mask
541 if( image.HasMask() )
542 {
543 hbitmap = ::CreateBitmap( (WORD)width, (WORD)bmpHeight, 1, 1, NULL );
544 HGDIOBJ hbmpOld = ::SelectObject( memdc, hbitmap);
545 if( numDIB == 1 ) height = bmpHeight;
546 else height = sizeLimit/bytePerLine;
547 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
548 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
549 origin = 0;
550 unsigned char r = image.GetMaskRed();
551 unsigned char g = image.GetMaskGreen();
552 unsigned char b = image.GetMaskBlue();
553 unsigned char zero = 0, one = 255;
554 ptdata = data;
555 for( n=0; n<numDIB; n++ )
556 {
557 if( numDIB > 1 && n == numDIB - 1 && hRemain > 0 )
558 {
559 // redefine height and size of the (possibly) last smaller DIB
560 // memory is not reallocated
561 height = hRemain;
562 lpDIBh->bmiHeader.biHeight = (DWORD)(-height);
563 lpDIBh->bmiHeader.biSizeImage = bytePerLine*height;
564 }
565 ptbits = lpBits;
566 for( int j=0; j<height; j++ )
567 {
568 for(i=0; i<width; i++ )
569 {
570 // was causing a code gen bug in cw : if( ( cr !=r) || (cg!=g) || (cb!=b) )
571 unsigned char cr = (*(ptdata++)) ;
572 unsigned char cg = (*(ptdata++)) ;
573 unsigned char cb = (*(ptdata++)) ;
574
575 if( ( cr !=r) || (cg!=g) || (cb!=b) )
576 {
577 *(ptbits++) = one;
578 *(ptbits++) = one;
579 *(ptbits++) = one;
580 }
581 else
582 {
583 *(ptbits++) = zero;
584 *(ptbits++) = zero;
585 *(ptbits++) = zero;
586 }
587 }
588 for( i=0; i< padding; i++ ) *(ptbits++) = zero;
589 }
590 ::StretchDIBits( memdc, 0, origin, width, height,\
591 0, 0, width, height, lpBits, lpDIBh, DIB_RGB_COLORS, SRCCOPY);
592 origin += height;
593 }
594 // create a wxMask object
595 wxMask *mask = new wxMask();
596 mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
597 SetMask( mask );
598 // It will be deleted when the wxBitmap object is deleted (as of 01/1999)
599 /* The following can also be used but is slow to run
600 wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
601 wxMask *mask = new wxMask( *this, colour );
602 SetMask( mask );
603 */
604
605 ::SelectObject( memdc, hbmpOld );
606 }
607
608 // free allocated resources
609 ::DeleteDC( memdc );
610 ::ReleaseDC(NULL, hdc);
611 free(lpDIBh);
612 free(lpBits);
613
614#if WXWIN_COMPATIBILITY_2
615 // check the wxBitmap object
616 GetBitmapData()->SetOk();
617#endif // WXWIN_COMPATIBILITY_2
6d51f220 618
fec19ea9
VS
619 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
620
621 return TRUE;
8cb172b4 622#endif
fec19ea9
VS
623}
624
625wxImage wxBitmap::ConvertToImage() const
626{
8cb172b4
JS
627#ifdef __WXMICROWIN__
628 // TODO
629 return wxImage();
630#else
fec19ea9 631 wxImage image;
6d51f220 632
fec19ea9
VS
633 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
634
635 // create an wxImage object
636 int width = GetWidth();
637 int height = GetHeight();
638 image.Create( width, height );
639 unsigned char *data = image.GetData();
640 if( !data )
641 {
642 wxFAIL_MSG( wxT("could not allocate data for image") );
643 return wxNullImage;
644 }
645
646 // calc the number of bytes per scanline and padding in the DIB
647 int bytePerLine = width*3;
648 int sizeDWORD = sizeof( DWORD );
649 int lineBoundary = bytePerLine % sizeDWORD;
650 int padding = 0;
651 if( lineBoundary > 0 )
652 {
653 padding = sizeDWORD - lineBoundary;
654 bytePerLine += padding;
655 }
656
657 // create a DIB header
658 int headersize = sizeof(BITMAPINFOHEADER);
659 BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize );
660 if( !lpDIBh )
661 {
662 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
663 free( data );
664 return wxNullImage;
665 }
666 // Fill in the DIB header
667 lpDIBh->bmiHeader.biSize = headersize;
668 lpDIBh->bmiHeader.biWidth = width;
669 lpDIBh->bmiHeader.biHeight = -height;
670 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
671 lpDIBh->bmiHeader.biPlanes = 1;
672 lpDIBh->bmiHeader.biBitCount = 24;
673 lpDIBh->bmiHeader.biCompression = BI_RGB;
674 lpDIBh->bmiHeader.biClrUsed = 0;
675 // These seem not really needed for our purpose here.
676 lpDIBh->bmiHeader.biClrImportant = 0;
677 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
678 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
679 // memory for DIB data
680 unsigned char *lpBits;
681 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
682 if( !lpBits )
683 {
684 wxFAIL_MSG( wxT("could not allocate data for DIB") );
685 free( data );
686 free( lpDIBh );
687 return wxNullImage;
688 }
689
690 // copy data from the device-dependent bitmap to the DIB
691 HDC hdc = ::GetDC(NULL);
692 HBITMAP hbitmap;
693 hbitmap = (HBITMAP) GetHBITMAP();
694 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
695
696 // copy DIB data into the wxImage object
697 int i, j;
698 unsigned char *ptdata = data;
699 unsigned char *ptbits = lpBits;
700 for( i=0; i<height; i++ )
701 {
702 for( j=0; j<width; j++ )
703 {
704 *(ptdata++) = *(ptbits+2);
705 *(ptdata++) = *(ptbits+1);
706 *(ptdata++) = *(ptbits );
707 ptbits += 3;
708 }
709 ptbits += padding;
710 }
711
712 // similarly, set data according to the possible mask bitmap
713 if( GetMask() && GetMask()->GetMaskBitmap() )
714 {
715 hbitmap = (HBITMAP) GetMask()->GetMaskBitmap();
716 // memory DC created, color set, data copied, and memory DC deleted
717 HDC memdc = ::CreateCompatibleDC( hdc );
718 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
719 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
720 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
721 ::DeleteDC( memdc );
722 // background color set to RGB(16,16,16) in consistent with wxGTK
723 unsigned char r=16, g=16, b=16;
724 ptdata = data;
725 ptbits = lpBits;
726 for( i=0; i<height; i++ )
727 {
728 for( j=0; j<width; j++ )
729 {
730 if( *ptbits != 0 )
731 ptdata += 3;
732 else
733 {
734 *(ptdata++) = r;
735 *(ptdata++) = g;
736 *(ptdata++) = b;
737 }
738 ptbits += 3;
739 }
740 ptbits += padding;
741 }
742 image.SetMaskColour( r, g, b );
743 image.SetMask( TRUE );
744 }
745 else
746 {
747 image.SetMask( FALSE );
748 }
749 // free allocated resources
750 ::ReleaseDC(NULL, hdc);
751 free(lpDIBh);
752 free(lpBits);
753
754 return image;
8cb172b4 755#endif
fec19ea9
VS
756}
757
6d51f220
VZ
758#endif // wxUSE_IMAGE
759
debe6624 760bool wxBitmap::LoadFile(const wxString& filename, long type)
2bda0e17 761{
6d167489 762 UnRef();
2bda0e17 763
6d167489 764 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 765
6d167489
VZ
766 if ( handler )
767 {
768 m_refData = new wxBitmapRefData;
2bda0e17 769
6d167489
VZ
770 return handler->LoadFile(this, filename, type, -1, -1);
771 }
6d51f220 772#if wxUSE_IMAGE
6d167489 773 else
b75dd496 774 {
6d167489 775 wxImage image;
6d51f220
VZ
776 if ( image.LoadFile( filename, type ) && image.Ok() )
777 {
778 *this = image.ConvertToBitmap();
6d167489 779
6d51f220
VZ
780 return TRUE;
781 }
b75dd496 782 }
6d51f220
VZ
783#endif // wxUSE_IMAGE
784
785 return FALSE;
2bda0e17
KB
786}
787
debe6624 788bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
2bda0e17 789{
6d167489 790 UnRef();
2bda0e17 791
6d167489 792 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 793
6d167489
VZ
794 if ( !handler )
795 {
f6bcfd97 796 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %d defined."), type);
2bda0e17 797
6d167489
VZ
798 return FALSE;
799 }
1d792928 800
6d167489 801 m_refData = new wxBitmapRefData;
1d792928 802
6d167489 803 return handler->Create(this, data, type, width, height, depth);
2bda0e17
KB
804}
805
d275c7eb
VZ
806bool wxBitmap::SaveFile(const wxString& filename,
807 int type,
808 const wxPalette *palette)
2bda0e17 809{
6d167489 810 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 811
6d167489
VZ
812 if ( handler )
813 {
814 return handler->SaveFile(this, filename, type, palette);
815 }
6d51f220 816#if wxUSE_IMAGE
6d167489
VZ
817 else
818 {
819 // FIXME what about palette? shouldn't we use it?
820 wxImage image( *this );
6d51f220
VZ
821 if ( image.Ok() )
822 {
823 return image.SaveFile(filename, type);
824 }
6d167489 825 }
6d51f220
VZ
826#endif // wxUSE_IMAGE
827
828 return FALSE;
2bda0e17
KB
829}
830
4b7f2165
VZ
831// ----------------------------------------------------------------------------
832// sub bitmap extraction
833// ----------------------------------------------------------------------------
834
835wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
836{
04ef50df 837#ifndef __WXMICROWIN__
4b7f2165
VZ
838 wxCHECK_MSG( Ok() &&
839 (rect.x >= 0) && (rect.y >= 0) &&
840 (rect.x+rect.width <= GetWidth()) &&
841 (rect.y+rect.height <= GetHeight()),
842 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
843
844 wxBitmap ret( rect.width, rect.height, GetDepth() );
845 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
846
847 // copy bitmap data
848 HDC dcSrc = ::CreateCompatibleDC(NULL);
849 HDC dcDst = ::CreateCompatibleDC(NULL);
850 SelectObject(dcSrc, (HBITMAP) GetHBITMAP());
851 SelectObject(dcDst, (HBITMAP) ret.GetHBITMAP());
852 BitBlt(dcDst, 0, 0, rect.width, rect.height, dcSrc, rect.x, rect.y, SRCCOPY);
853
854 // copy mask if there is one
855 if (GetMask())
856 {
857 HBITMAP hbmpMask = ::CreateBitmap(rect.width, rect.height, 1, 1, 0);
858
859 SelectObject(dcSrc, (HBITMAP) GetMask()->GetMaskBitmap());
860 SelectObject(dcDst, (HBITMAP) hbmpMask);
861 BitBlt(dcDst, 0, 0, rect.width, rect.height, dcSrc, rect.x, rect.y, SRCCOPY);
862
863 wxMask *mask = new wxMask((WXHBITMAP) hbmpMask);
864 ret.SetMask(mask);
865 }
866
867 SelectObject(dcDst, NULL);
868 SelectObject(dcSrc, NULL);
869 DeleteDC(dcDst);
870 DeleteDC(dcSrc);
871
872 return ret;
04ef50df
JS
873#else
874 return wxBitmap();
875#endif
4b7f2165
VZ
876}
877
6d167489
VZ
878// ----------------------------------------------------------------------------
879// wxBitmap accessors
880// ----------------------------------------------------------------------------
2bda0e17
KB
881
882void wxBitmap::SetQuality(int q)
883{
6d167489 884 EnsureHasData();
2bda0e17 885
6d167489 886 GetBitmapData()->m_quality = q;
2bda0e17
KB
887}
888
6d167489 889#if WXWIN_COMPATIBILITY_2
2bda0e17
KB
890void wxBitmap::SetOk(bool isOk)
891{
6d167489 892 EnsureHasData();
2bda0e17 893
6d167489 894 GetBitmapData()->m_ok = isOk;
2bda0e17 895}
6d167489 896#endif // WXWIN_COMPATIBILITY_2
2bda0e17 897
d275c7eb
VZ
898#if wxUSE_PALETTE
899
2bda0e17
KB
900void wxBitmap::SetPalette(const wxPalette& palette)
901{
6d167489 902 EnsureHasData();
2bda0e17 903
6d167489 904 GetBitmapData()->m_bitmapPalette = palette;
2bda0e17
KB
905}
906
d275c7eb
VZ
907#endif // wxUSE_PALETTE
908
2bda0e17
KB
909void wxBitmap::SetMask(wxMask *mask)
910{
6d167489 911 EnsureHasData();
2bda0e17 912
6d167489 913 GetBitmapData()->m_bitmapMask = mask;
2bda0e17
KB
914}
915
7b46ecac
JS
916// Creates a bitmap that matches the device context, from
917// an arbitray bitmap. At present, the original bitmap must have an
918// associated palette. TODO: use a default palette if no palette exists.
919// Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
920wxBitmap wxBitmap::GetBitmapForDC(wxDC& dc) const
921{
04ef50df
JS
922#ifdef __WXMICROWIN__
923 return wxBitmap();
924#else
7b46ecac 925 wxMemoryDC memDC;
4b7f2165 926 wxBitmap tmpBitmap(GetWidth(), GetHeight(), dc.GetDepth());
57c208c5 927 HPALETTE hPal = (HPALETTE) NULL;
7b46ecac 928 LPBITMAPINFO lpDib;
57c208c5 929 void *lpBits = (void*) NULL;
7b46ecac 930
d275c7eb 931#if wxUSE_PALETTE
6d167489 932 if( GetPalette() && GetPalette()->Ok() )
a367b9b3 933 {
6d167489 934 tmpBitmap.SetPalette(*GetPalette());
a367b9b3 935 memDC.SelectObject(tmpBitmap);
6d167489
VZ
936 memDC.SetPalette(*GetPalette());
937 hPal = (HPALETTE)GetPalette()->GetHPALETTE();
a367b9b3
JS
938 }
939 else
940 {
941 hPal = (HPALETTE) ::GetStockObject(DEFAULT_PALETTE);
942 wxPalette palette;
943 palette.SetHPALETTE( (WXHPALETTE)hPal );
944 tmpBitmap.SetPalette( palette );
945 memDC.SelectObject(tmpBitmap);
946 memDC.SetPalette( palette );
947 }
d275c7eb
VZ
948#else // !wxUSE_PALETTE
949 hPal = (HPALETTE) ::GetStockObject(DEFAULT_PALETTE);
950#endif // wxUSE_PALETTE/!wxUSE_PALETTE
7b46ecac 951
6d167489
VZ
952 // set the height negative because in a DIB the order of the lines is
953 // reversed
954 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal, &lpDib) )
955 {
956 return wxNullBitmap;
957 }
7b46ecac
JS
958
959 lpBits = malloc(lpDib->bmiHeader.biSizeImage);
960
6d167489 961 ::GetBitmapBits(GetHbitmap(), lpDib->bmiHeader.biSizeImage, lpBits);
7b46ecac 962
6d167489
VZ
963 ::SetDIBitsToDevice(GetHdcOf(memDC), 0, 0,
964 GetWidth(), GetHeight(),
965 0, 0, 0, GetHeight(),
966 lpBits, lpDib, DIB_RGB_COLORS);
7b46ecac
JS
967
968 free(lpBits);
969
6d167489
VZ
970 wxFreeDIB(lpDib);
971
972 return tmpBitmap;
04ef50df 973#endif
7b46ecac
JS
974}
975
6d167489
VZ
976// ----------------------------------------------------------------------------
977// wxMask
978// ----------------------------------------------------------------------------
2bda0e17 979
10fcf31a 980wxMask::wxMask()
2bda0e17
KB
981{
982 m_maskBitmap = 0;
983}
984
985// Construct a mask from a bitmap and a colour indicating
986// the transparent area
987wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
988{
989 m_maskBitmap = 0;
6d167489 990 Create(bitmap, colour);
2bda0e17
KB
991}
992
993// Construct a mask from a bitmap and a palette index indicating
994// the transparent area
debe6624 995wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
996{
997 m_maskBitmap = 0;
6d167489 998 Create(bitmap, paletteIndex);
2bda0e17
KB
999}
1000
1001// Construct a mask from a mono bitmap (copies the bitmap).
1002wxMask::wxMask(const wxBitmap& bitmap)
1003{
1004 m_maskBitmap = 0;
6d167489 1005 Create(bitmap);
2bda0e17
KB
1006}
1007
10fcf31a 1008wxMask::~wxMask()
2bda0e17
KB
1009{
1010 if ( m_maskBitmap )
1011 ::DeleteObject((HBITMAP) m_maskBitmap);
1012}
1013
1014// Create a mask from a mono bitmap (copies the bitmap).
1015bool wxMask::Create(const wxBitmap& bitmap)
1016{
04ef50df 1017#ifndef __WXMICROWIN__
a58a12e9
VZ
1018 wxCHECK_MSG( bitmap.Ok() && bitmap.GetDepth() == 1, FALSE,
1019 _T("can't create mask from invalid or not monochrome bitmap") );
1020
2bda0e17 1021 if ( m_maskBitmap )
6d167489
VZ
1022 {
1023 ::DeleteObject((HBITMAP) m_maskBitmap);
1024 m_maskBitmap = 0;
1025 }
a58a12e9 1026
6d167489
VZ
1027 m_maskBitmap = (WXHBITMAP) CreateBitmap(
1028 bitmap.GetWidth(),
1029 bitmap.GetHeight(),
1030 1, 1, 0
1031 );
1032 HDC srcDC = CreateCompatibleDC(0);
1033 SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
1034 HDC destDC = CreateCompatibleDC(0);
1035 SelectObject(destDC, (HBITMAP) m_maskBitmap);
1036 BitBlt(destDC, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), srcDC, 0, 0, SRCCOPY);
1037 SelectObject(srcDC, 0);
1038 DeleteDC(srcDC);
1039 SelectObject(destDC, 0);
1040 DeleteDC(destDC);
1041 return TRUE;
04ef50df
JS
1042#else
1043 return FALSE;
1044#endif
2bda0e17
KB
1045}
1046
1047// Create a mask from a bitmap and a palette index indicating
1048// the transparent area
debe6624 1049bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
1050{
1051 if ( m_maskBitmap )
1d792928 1052 {
6d167489
VZ
1053 ::DeleteObject((HBITMAP) m_maskBitmap);
1054 m_maskBitmap = 0;
1d792928 1055 }
d275c7eb
VZ
1056
1057#if wxUSE_PALETTE
6d167489
VZ
1058 if (bitmap.Ok() && bitmap.GetPalette()->Ok())
1059 {
1060 unsigned char red, green, blue;
1061 if (bitmap.GetPalette()->GetRGB(paletteIndex, &red, &green, &blue))
1062 {
1063 wxColour transparentColour(red, green, blue);
1064 return Create(bitmap, transparentColour);
1065 }
1066 }
d275c7eb
VZ
1067#endif // wxUSE_PALETTE
1068
6d167489 1069 return FALSE;
2bda0e17
KB
1070}
1071
1072// Create a mask from a bitmap and a colour indicating
1073// the transparent area
1074bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
1075{
04ef50df 1076#ifndef __WXMICROWIN__
4b7f2165
VZ
1077 wxCHECK_MSG( bitmap.Ok(), FALSE, _T("invalid bitmap in wxMask::Create") );
1078
2bda0e17 1079 if ( m_maskBitmap )
1d792928 1080 {
6d167489
VZ
1081 ::DeleteObject((HBITMAP) m_maskBitmap);
1082 m_maskBitmap = 0;
1083 }
4b7f2165
VZ
1084
1085 int width = bitmap.GetWidth(),
1086 height = bitmap.GetHeight();
1087
1088 // scan the bitmap for the transparent colour and set the corresponding
1089 // pixels in the mask to BLACK and the rest to WHITE
25acfd4c 1090 COLORREF maskColour = RGB(colour.Red(), colour.Green(), colour.Blue());
4b7f2165
VZ
1091 m_maskBitmap = (WXHBITMAP)::CreateBitmap(width, height, 1, 1, 0);
1092
1093 HDC srcDC = ::CreateCompatibleDC(NULL);
1094 HDC destDC = ::CreateCompatibleDC(NULL);
1095 if ( !srcDC || !destDC )
1096 {
f6bcfd97 1097 wxLogLastError(wxT("CreateCompatibleDC"));
4b7f2165
VZ
1098 }
1099
0bafad0c
VZ
1100 bool ok = TRUE;
1101
1e6feb95
VZ
1102 // SelectObject() will fail
1103 wxASSERT_MSG( !bitmap.GetSelectedInto(),
1104 _T("bitmap can't be selected in another DC") );
1105
0bafad0c
VZ
1106 HGDIOBJ hbmpSrcOld = ::SelectObject(srcDC, GetHbitmapOf(bitmap));
1107 if ( !hbmpSrcOld )
6d167489 1108 {
f6bcfd97 1109 wxLogLastError(wxT("SelectObject"));
0bafad0c
VZ
1110
1111 ok = FALSE;
4b7f2165 1112 }
0bafad0c
VZ
1113
1114 HGDIOBJ hbmpDstOld = ::SelectObject(destDC, (HBITMAP)m_maskBitmap);
1115 if ( !hbmpDstOld )
4b7f2165 1116 {
f6bcfd97 1117 wxLogLastError(wxT("SelectObject"));
0bafad0c
VZ
1118
1119 ok = FALSE;
1d792928 1120 }
2bda0e17 1121
4b7f2165
VZ
1122 // this is not very efficient, but I can't think of a better way of doing
1123 // it
0bafad0c 1124 for ( int w = 0; ok && (w < width); w++ )
2bda0e17 1125 {
0bafad0c 1126 for ( int h = 0; ok && (h < height); h++ )
c793fa87 1127 {
6d167489 1128 COLORREF col = GetPixel(srcDC, w, h);
4b7f2165
VZ
1129 if ( col == CLR_INVALID )
1130 {
f6bcfd97 1131 wxLogLastError(wxT("GetPixel"));
4b7f2165
VZ
1132
1133 // doesn't make sense to continue
0bafad0c 1134 ok = FALSE;
4b7f2165 1135
0bafad0c 1136 break;
4b7f2165
VZ
1137 }
1138
1139 if ( col == maskColour )
6d167489
VZ
1140 {
1141 ::SetPixel(destDC, w, h, RGB(0, 0, 0));
1142 }
1143 else
1144 {
1145 ::SetPixel(destDC, w, h, RGB(255, 255, 255));
1146 }
c793fa87 1147 }
2bda0e17 1148 }
4b7f2165 1149
0bafad0c 1150 ::SelectObject(srcDC, hbmpSrcOld);
6d167489 1151 ::DeleteDC(srcDC);
0bafad0c 1152 ::SelectObject(destDC, hbmpDstOld);
6d167489 1153 ::DeleteDC(destDC);
4b7f2165 1154
0bafad0c 1155 return ok;
04ef50df
JS
1156#else
1157 return FALSE;
1158#endif
6d167489
VZ
1159}
1160
1161// ----------------------------------------------------------------------------
1162// wxBitmapHandler
1163// ----------------------------------------------------------------------------
1d792928 1164
6d167489
VZ
1165bool wxBitmapHandler::Create(wxGDIImage *image,
1166 void *data,
1167 long flags,
1168 int width, int height, int depth)
1169{
1170 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
1d792928 1171
8c1375b9 1172 return bitmap ? Create(bitmap, data, flags, width, height, depth) : FALSE;
2bda0e17
KB
1173}
1174
6d167489
VZ
1175bool wxBitmapHandler::Load(wxGDIImage *image,
1176 const wxString& name,
1177 long flags,
1178 int width, int height)
2bda0e17 1179{
6d167489 1180 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
2bda0e17 1181
6d167489
VZ
1182 return bitmap ? LoadFile(bitmap, name, flags, width, height) : FALSE;
1183}
2bda0e17 1184
6d167489
VZ
1185bool wxBitmapHandler::Save(wxGDIImage *image,
1186 const wxString& name,
1187 int type)
2bda0e17 1188{
6d167489
VZ
1189 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
1190
1191 return bitmap ? SaveFile(bitmap, name, type) : FALSE;
2bda0e17
KB
1192}
1193
6d167489
VZ
1194bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap),
1195 void *WXUNUSED(data),
1196 long WXUNUSED(type),
1197 int WXUNUSED(width),
1198 int WXUNUSED(height),
1199 int WXUNUSED(depth))
2bda0e17 1200{
6d167489 1201 return FALSE;
2bda0e17
KB
1202}
1203
6d167489
VZ
1204bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap),
1205 const wxString& WXUNUSED(name),
1206 long WXUNUSED(type),
1207 int WXUNUSED(desiredWidth),
1208 int WXUNUSED(desiredHeight))
2bda0e17 1209{
6d167489 1210 return FALSE;
2bda0e17
KB
1211}
1212
6d167489
VZ
1213bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap),
1214 const wxString& WXUNUSED(name),
1215 int WXUNUSED(type),
1216 const wxPalette *WXUNUSED(palette))
2bda0e17 1217{
6d167489 1218 return FALSE;
7b46ecac
JS
1219}
1220
6d167489
VZ
1221// ----------------------------------------------------------------------------
1222// DIB functions
1223// ----------------------------------------------------------------------------
1224
04ef50df 1225#ifndef __WXMICROWIN__
6d167489
VZ
1226bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel,
1227 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader)
7b46ecac
JS
1228{
1229 unsigned long i, headerSize;
1230 LPBITMAPINFO lpDIBheader = NULL;
1231 LPPALETTEENTRY lpPe = NULL;
1232
1233
1234 // Allocate space for a DIB header
1235 headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY)));
1236 lpDIBheader = (BITMAPINFO *) malloc(headerSize);
1237 lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER));
1238
1239 GetPaletteEntries(hPal, 0, 256, lpPe);
1240
7b46ecac
JS
1241 memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER));
1242
7b46ecac
JS
1243 // Fill in the static parts of the DIB header
1244 lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1245 lpDIBheader->bmiHeader.biWidth = xSize;
1246 lpDIBheader->bmiHeader.biHeight = ySize;
1247 lpDIBheader->bmiHeader.biPlanes = 1;
1248
1249 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
1250 lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel);
1251 lpDIBheader->bmiHeader.biCompression = BI_RGB;
6d167489 1252 lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >> 3;
7b46ecac
JS
1253 lpDIBheader->bmiHeader.biClrUsed = 256;
1254
1255
1256 // Initialize the DIB palette
1257 for (i = 0; i < 256; i++) {
1258 lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags;
1259 lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed;
1260 lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen;
1261 lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue;
1262 }
1263
1264 *lpDIBHeader = lpDIBheader;
1265
6d167489 1266 return TRUE;
7b46ecac
JS
1267}
1268
6d167489 1269void wxFreeDIB(LPBITMAPINFO lpDIBHeader)
7b46ecac 1270{
6d167489 1271 free(lpDIBHeader);
7b46ecac 1272}
04ef50df 1273#endif
7b46ecac 1274
4b7f2165
VZ
1275// ----------------------------------------------------------------------------
1276// other helper functions
1277// ----------------------------------------------------------------------------
1278
1279extern HBITMAP wxInvertMask(HBITMAP hbmpMask, int w, int h)
1280{
04ef50df 1281#ifndef __WXMICROWIN__
4b7f2165
VZ
1282 wxCHECK_MSG( hbmpMask, 0, _T("invalid bitmap in wxInvertMask") );
1283
1284 // get width/height from the bitmap if not given
1285 if ( !w || !h )
1286 {
1287 BITMAP bm;
1288 ::GetObject(hbmpMask, sizeof(BITMAP), (LPVOID)&bm);
1289 w = bm.bmWidth;
1290 h = bm.bmHeight;
1291 }
1292
1293 HDC hdcSrc = ::CreateCompatibleDC(NULL);
1294 HDC hdcDst = ::CreateCompatibleDC(NULL);
1295 if ( !hdcSrc || !hdcDst )
1296 {
f6bcfd97 1297 wxLogLastError(wxT("CreateCompatibleDC"));
4b7f2165
VZ
1298 }
1299
1300 HBITMAP hbmpInvMask = ::CreateBitmap(w, h, 1, 1, 0);
1301 if ( !hbmpInvMask )
1302 {
f6bcfd97 1303 wxLogLastError(wxT("CreateBitmap"));
4b7f2165
VZ
1304 }
1305
1306 ::SelectObject(hdcSrc, hbmpMask);
1307 ::SelectObject(hdcDst, hbmpInvMask);
1308 if ( !::BitBlt(hdcDst, 0, 0, w, h,
1309 hdcSrc, 0, 0,
1310 NOTSRCCOPY) )
1311 {
f6bcfd97 1312 wxLogLastError(wxT("BitBlt"));
4b7f2165 1313 }
7b46ecac 1314
4b7f2165
VZ
1315 ::DeleteDC(hdcSrc);
1316 ::DeleteDC(hdcDst);
1317
1318 return hbmpInvMask;
04ef50df
JS
1319#else
1320 return 0;
1321#endif
4b7f2165 1322}