]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bitmap.cpp
Modified vc.t according to last changes to makefile.vc, and regenerated
[wxWidgets.git] / src / msw / bitmap.cpp
CommitLineData
0becd470 1////////////////////////////////////////////////////////////////////////////
2bda0e17
KB
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
8bbbae21
VZ
58// ----------------------------------------------------------------------------
59// Bitmap data
60// ----------------------------------------------------------------------------
61
62class WXDLLEXPORT wxBitmapRefData : public wxGDIImageRefData
63{
64public:
65 wxBitmapRefData();
66 virtual ~wxBitmapRefData() { Free(); }
67
68 virtual void Free();
69
70 // set the mask object to use as the mask, we take ownership of it
71 void SetMask(wxMask *mask)
72 {
73 delete m_bitmapMask;
74 m_bitmapMask = mask;
75 }
76
77 // set the HBITMAP to use as the mask
78 void SetMask(HBITMAP hbmpMask)
79 {
80 SetMask(new wxMask((WXHBITMAP)hbmpMask));
81 }
82
83 // return the mask
84 wxMask *GetMask() const { return m_bitmapMask; }
85
86public:
8bbbae21
VZ
87#if wxUSE_PALETTE
88 wxPalette m_bitmapPalette;
89#endif // wxUSE_PALETTE
90
91 // MSW-specific
92 // ------------
93
acf8e3d2 94#ifdef __WXDEBUG__
8bbbae21
VZ
95 // this field is solely for error checking: we detect selecting a bitmap
96 // into more than one DC at once or deleting a bitmap still selected into a
97 // DC (both are serious programming errors under Windows)
98 wxDC *m_selectedInto;
acf8e3d2 99#endif // __WXDEBUG__
8bbbae21 100
acf8e3d2
VZ
101 // true if we have alpha transparency info and can be drawn using
102 // AlphaBlend()
103 bool m_hasAlpha;
8bbbae21
VZ
104
105private:
106 // optional mask for transparent drawing
107 wxMask *m_bitmapMask;
108
109 DECLARE_NO_COPY_CLASS(wxBitmapRefData)
110};
111
10fcf31a
VZ
112// ----------------------------------------------------------------------------
113// macros
114// ----------------------------------------------------------------------------
115
4b7f2165
VZ
116IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
117IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
6d167489 118
4b7f2165 119IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
2bda0e17 120
10fcf31a
VZ
121// ============================================================================
122// implementation
123// ============================================================================
124
125// ----------------------------------------------------------------------------
126// wxBitmapRefData
127// ----------------------------------------------------------------------------
128
129wxBitmapRefData::wxBitmapRefData()
2bda0e17 130{
3ca22d5e 131#ifdef __WXDEBUG__
6d167489 132 m_selectedInto = NULL;
3ca22d5e 133#endif
6d167489 134 m_bitmapMask = NULL;
340196c0 135 m_hBitmap = (WXHBITMAP) NULL;
acf8e3d2 136 m_hasAlpha = FALSE;
2bda0e17
KB
137}
138
6d167489 139void wxBitmapRefData::Free()
2bda0e17 140{
d59ceba5
VZ
141 wxASSERT_MSG( !m_selectedInto,
142 wxT("deleting bitmap still selected into wxMemoryDC") );
2bda0e17 143
d59ceba5 144 if ( m_hBitmap)
6d167489
VZ
145 {
146 if ( !::DeleteObject((HBITMAP)m_hBitmap) )
147 {
f6bcfd97 148 wxLogLastError(wxT("DeleteObject(hbitmap)"));
6d167489
VZ
149 }
150 }
e7003166 151
6d167489
VZ
152 delete m_bitmapMask;
153 m_bitmapMask = NULL;
2bda0e17
KB
154}
155
10fcf31a 156// ----------------------------------------------------------------------------
6d167489 157// wxBitmap creation
10fcf31a
VZ
158// ----------------------------------------------------------------------------
159
4fe5383d
VZ
160// this function should be called from all wxBitmap ctors
161void wxBitmap::Init()
2bda0e17 162{
4fe5383d 163 // m_refData = NULL; done in the base class ctor
2bda0e17 164
4fe5383d
VZ
165}
166
8bbbae21
VZ
167wxGDIImageRefData *wxBitmap::CreateData() const
168{
169 return new wxBitmapRefData;
170}
171
6d167489
VZ
172#ifdef __WIN32__
173
174bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon)
175{
04ef50df 176#ifndef __WXMICROWIN__
6d167489
VZ
177 // it may be either HICON or HCURSOR
178 HICON hicon = (HICON)icon.GetHandle();
179
180 ICONINFO iconInfo;
181 if ( !::GetIconInfo(hicon, &iconInfo) )
182 {
f6bcfd97 183 wxLogLastError(wxT("GetIconInfo"));
6d167489
VZ
184
185 return FALSE;
186 }
187
188 wxBitmapRefData *refData = new wxBitmapRefData;
189 m_refData = refData;
190
d9c8e68e
VZ
191 int w = icon.GetWidth(),
192 h = icon.GetHeight();
193
194 refData->m_width = w;
195 refData->m_height = h;
6d167489
VZ
196 refData->m_depth = wxDisplayDepth();
197
198 refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor;
d9c8e68e
VZ
199
200 // the mask returned by GetIconInfo() is inversed compared to the usual
201 // wxWin convention
8bbbae21 202 refData->SetMask(wxInvertMask(iconInfo.hbmMask, w, h));
6d167489 203
68f36a2c
VZ
204
205 // delete the old one now as we don't need it any more
206 ::DeleteObject(iconInfo.hbmMask);
207
6d167489
VZ
208#if WXWIN_COMPATIBILITY_2
209 refData->m_ok = TRUE;
210#endif // WXWIN_COMPATIBILITY_2
211
212 return TRUE;
04ef50df
JS
213#else
214 return FALSE;
215#endif
6d167489
VZ
216}
217
218#endif // Win32
219
220bool wxBitmap::CopyFromCursor(const wxCursor& cursor)
4fe5383d
VZ
221{
222 UnRef();
07cf98cb 223
6d167489 224 if ( !cursor.Ok() )
4fe5383d 225 return FALSE;
07cf98cb 226
6d167489
VZ
227#ifdef __WIN16__
228 wxFAIL_MSG( _T("don't know how to convert cursor to bitmap") );
229
230 return FALSE;
8f177c8e 231#else
6d167489 232 return CopyFromIconOrCursor(cursor);
8f177c8e 233#endif // Win16
6d167489
VZ
234}
235
236bool wxBitmap::CopyFromIcon(const wxIcon& icon)
237{
238 UnRef();
07cf98cb 239
6d167489
VZ
240 if ( !icon.Ok() )
241 return FALSE;
4fe5383d
VZ
242
243 // GetIconInfo() doesn't exist under Win16 and I don't know any other way
244 // to create a bitmap from icon there - but using this way we won't have
245 // the mask (FIXME)
246#ifdef __WIN16__
6d167489
VZ
247 int width = icon.GetWidth(),
248 height = icon.GetHeight();
249
4fe5383d 250 // copy the icon to the bitmap
6d167489 251 ScreenHDC hdcScreen;
4fe5383d
VZ
252 HDC hdc = ::CreateCompatibleDC(hdcScreen);
253 HBITMAP hbitmap = ::CreateCompatibleBitmap(hdcScreen, width, height);
07cf98cb
VZ
254 HBITMAP hbmpOld = (HBITMAP)::SelectObject(hdc, hbitmap);
255
6d167489 256 ::DrawIcon(hdc, 0, 0, GetHiconOf(icon));
07cf98cb
VZ
257
258 ::SelectObject(hdc, hbmpOld);
259 ::DeleteDC(hdc);
4fe5383d 260
6d167489
VZ
261 wxBitmapRefData *refData = new wxBitmapRefData;
262 m_refData = refData;
4fe5383d 263
6d167489
VZ
264 refData->m_width = width;
265 refData->m_height = height;
266 refData->m_depth = wxDisplayDepth();
07cf98cb 267
6d167489 268 refData->m_hBitmap = (WXHBITMAP)hbitmap;
07cf98cb 269
6d167489
VZ
270#if WXWIN_COMPATIBILITY_2
271 refData->m_ok = TRUE;
272#endif // WXWIN_COMPATIBILITY_2
222594ea 273
4fe5383d 274 return TRUE;
6d167489
VZ
275#else // Win32
276 return CopyFromIconOrCursor(icon);
277#endif // Win16/Win32
10fcf31a
VZ
278}
279
280wxBitmap::~wxBitmap()
2bda0e17 281{
2bda0e17
KB
282}
283
5bd3a2da 284wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
2bda0e17 285{
4fe5383d 286 Init();
2bda0e17 287
04ef50df 288#ifndef __WXMICROWIN__
6d167489
VZ
289 wxBitmapRefData *refData = new wxBitmapRefData;
290 m_refData = refData;
2bda0e17 291
5bd3a2da
VZ
292 refData->m_width = width;
293 refData->m_height = height;
294 refData->m_depth = depth;
2bda0e17 295
5bd3a2da
VZ
296 char *data;
297 if ( depth == 1 )
298 {
299 // we assume that it is in XBM format which is not quite the same as
300 // the format CreateBitmap() wants because the order of bytes in the
301 // line is inversed!
4d24ece7
VZ
302 const size_t bytesPerLine = (width + 7) / 8;
303 const size_t padding = bytesPerLine % 2;
304 const size_t len = height * ( padding + bytesPerLine );
5bd3a2da
VZ
305 data = (char *)malloc(len);
306 const char *src = bits;
307 char *dst = data;
308
309 for ( int rows = 0; rows < height; rows++ )
310 {
0765adca 311 for ( size_t cols = 0; cols < bytesPerLine; cols++ )
5bd3a2da 312 {
0765adca
VZ
313 unsigned char val = *src++;
314 unsigned char reversed = 0;
315
316 for ( int bits = 0; bits < 8; bits++)
317 {
318 reversed <<= 1;
319 reversed |= (val & 0x01);
320 val >>= 1;
321 }
322 *dst++ = reversed;
5bd3a2da
VZ
323 }
324
325 if ( padding )
326 *dst++ = 0;
5bd3a2da
VZ
327 }
328 }
329 else
330 {
331 // bits should already be in Windows standard format
332 data = (char *)bits; // const_cast is harmless
333 }
334
335 HBITMAP hbmp = ::CreateBitmap(width, height, 1, depth, data);
6d167489
VZ
336 if ( !hbmp )
337 {
f6bcfd97 338 wxLogLastError(wxT("CreateBitmap"));
6d167489 339 }
2bda0e17 340
5bd3a2da
VZ
341 if ( data != bits )
342 {
343 free(data);
344 }
345
6d167489 346 SetHBITMAP((WXHBITMAP)hbmp);
04ef50df 347#endif
2bda0e17
KB
348}
349
2fd284a4 350// Create from XPM data
4b7f2165 351bool wxBitmap::CreateFromXpm(const char **data)
2fd284a4 352{
66e23ad2 353#if wxUSE_IMAGE && wxUSE_XPM
4fe5383d
VZ
354 Init();
355
66e23ad2 356 wxCHECK_MSG( data != NULL, FALSE, wxT("invalid bitmap data") )
4d24ece7 357
66e23ad2
VS
358 wxXPMDecoder decoder;
359 wxImage img = decoder.ReadData(data);
360 wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid bitmap data") )
4d24ece7 361
c59b4b01 362 *this = wxBitmap(img);
66e23ad2
VS
363 return TRUE;
364#else
4d24ece7 365 return FALSE;
66e23ad2 366#endif
2fd284a4
JS
367}
368
debe6624 369wxBitmap::wxBitmap(int w, int h, int d)
2bda0e17 370{
4fe5383d 371 Init();
2bda0e17 372
4fe5383d 373 (void)Create(w, h, d);
2bda0e17
KB
374}
375
debe6624 376wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
2bda0e17 377{
4fe5383d 378 Init();
2bda0e17 379
6d167489 380 (void)Create(data, type, width, height, depth);
2bda0e17
KB
381}
382
2aeec9ec 383wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
2bda0e17 384{
4fe5383d 385 Init();
2bda0e17 386
4fe5383d 387 LoadFile(filename, (int)type);
2bda0e17
KB
388}
389
debe6624 390bool wxBitmap::Create(int w, int h, int d)
2bda0e17 391{
6d167489
VZ
392 UnRef();
393
394 m_refData = new wxBitmapRefData;
395
0becd470
VZ
396#if wxUSE_DIB_FOR_BITMAP
397 if ( w && h && d >= 16 )
6d167489 398 {
0becd470
VZ
399 if ( !CreateDIB(w, h, d) )
400 return FALSE;
6d167489
VZ
401 }
402 else
0becd470 403#endif // wxUSE_DIB_FOR_BITMAP
6d167489 404 {
0becd470
VZ
405 GetBitmapData()->m_width = w;
406 GetBitmapData()->m_height = h;
407 GetBitmapData()->m_depth = d;
408
409 HBITMAP hbmp;
410#ifndef __WXMICROWIN__
411 if ( d > 0 )
6d167489 412 {
0becd470
VZ
413 hbmp = ::CreateBitmap(w, h, 1, d, NULL);
414 if ( !hbmp )
415 {
416 wxLogLastError(wxT("CreateBitmap"));
417 }
6d167489 418 }
0becd470
VZ
419 else
420#endif // !__WXMICROWIN__
421 {
422 ScreenHDC dc;
423 hbmp = ::CreateCompatibleBitmap(dc, w, h);
424 if ( !hbmp )
425 {
426 wxLogLastError(wxT("CreateCompatibleBitmap"));
427 }
6d167489 428
0becd470
VZ
429 GetBitmapData()->m_depth = wxDisplayDepth();
430 }
2bda0e17 431
0becd470 432 SetHBITMAP((WXHBITMAP)hbmp);
2bda0e17 433
6d167489 434#if WXWIN_COMPATIBILITY_2
e30285ab 435 GetBitmapData()->m_ok = hbmp != 0;
6d167489 436#endif // WXWIN_COMPATIBILITY_2
e30285ab 437 }
0becd470 438
6d167489 439 return Ok();
2bda0e17
KB
440}
441
acf8e3d2 442#if wxUSE_IMAGE
0becd470 443
6d51f220 444// ----------------------------------------------------------------------------
acf8e3d2 445// wxImage to/from conversions for Microwin
6d51f220
VZ
446// ----------------------------------------------------------------------------
447
acf8e3d2
VZ
448// Microwin versions are so different from normal ones that it really doesn't
449// make sense to use #ifdefs inside the function bodies
450#ifdef __WXMICROWIN__
6d51f220 451
fec19ea9
VS
452bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
453{
acf8e3d2
VZ
454 // Set this to 1 to experiment with mask code,
455 // which currently doesn't work
456 #define USE_MASKS 0
62e1ba75 457
54a96d02 458 m_refData = new wxBitmapRefData();
e640f823
JS
459
460 // Initial attempt at a simple-minded implementation.
461 // The bitmap will always be created at the screen depth,
462 // so the 'depth' argument is ignored.
8e9ff815 463
e640f823
JS
464 HDC hScreenDC = ::GetDC(NULL);
465 int screenDepth = ::GetDeviceCaps(hScreenDC, BITSPIXEL);
466
467 HBITMAP hBitmap = ::CreateCompatibleBitmap(hScreenDC, image.GetWidth(), image.GetHeight());
62e1ba75
JS
468 HBITMAP hMaskBitmap = NULL;
469 HBITMAP hOldMaskBitmap = NULL;
470 HDC hMaskDC = NULL;
471 unsigned char maskR = 0;
472 unsigned char maskG = 0;
473 unsigned char maskB = 0;
474
54a96d02 475 // printf("Created bitmap %d\n", (int) hBitmap);
e640f823
JS
476 if (hBitmap == NULL)
477 {
478 ::ReleaseDC(NULL, hScreenDC);
8e9ff815 479 return FALSE;
e640f823
JS
480 }
481 HDC hMemDC = ::CreateCompatibleDC(hScreenDC);
e640f823
JS
482
483 HBITMAP hOldBitmap = ::SelectObject(hMemDC, hBitmap);
62e1ba75
JS
484 ::ReleaseDC(NULL, hScreenDC);
485
486 // created an mono-bitmap for the possible mask
487 bool hasMask = image.HasMask();
488
489 if ( hasMask )
490 {
491#if USE_MASKS
492 // FIXME: we should be able to pass bpp = 1, but
493 // GdBlit can't handle a different depth
494#if 0
495 hMaskBitmap = ::CreateBitmap( (WORD)image.GetWidth(), (WORD)image.GetHeight(), 1, 1, NULL );
496#else
497 hMaskBitmap = ::CreateCompatibleBitmap( hMemDC, (WORD)image.GetWidth(), (WORD)image.GetHeight());
498#endif
499 maskR = image.GetMaskRed();
500 maskG = image.GetMaskGreen();
501 maskB = image.GetMaskBlue();
502
503 if (!hMaskBitmap)
504 {
505 hasMask = FALSE;
8e9ff815 506 }
62e1ba75
JS
507 else
508 {
509 hScreenDC = ::GetDC(NULL);
510 hMaskDC = ::CreateCompatibleDC(hScreenDC);
511 ::ReleaseDC(NULL, hScreenDC);
512
513 hOldMaskBitmap = ::SelectObject( hMaskDC, hMaskBitmap);
8e9ff815 514 }
62e1ba75
JS
515#else
516 hasMask = FALSE;
517#endif
518 }
e640f823
JS
519
520 int i, j;
521 for (i = 0; i < image.GetWidth(); i++)
522 {
8e9ff815
VZ
523 for (j = 0; j < image.GetHeight(); j++)
524 {
525 unsigned char red = image.GetRed(i, j);
526 unsigned char green = image.GetGreen(i, j);
527 unsigned char blue = image.GetBlue(i, j);
e640f823 528
8e9ff815 529 ::SetPixel(hMemDC, i, j, PALETTERGB(red, green, blue));
62e1ba75
JS
530
531 if (hasMask)
532 {
533 // scan the bitmap for the transparent colour and set the corresponding
534 // pixels in the mask to BLACK and the rest to WHITE
535 if (maskR == red && maskG == green && maskB == blue)
536 ::SetPixel(hMaskDC, i, j, PALETTERGB(0, 0, 0));
537 else
538 ::SetPixel(hMaskDC, i, j, PALETTERGB(255, 255, 255));
8e9ff815
VZ
539 }
540 }
e640f823
JS
541 }
542
543 ::SelectObject(hMemDC, hOldBitmap);
544 ::DeleteDC(hMemDC);
62e1ba75
JS
545 if (hasMask)
546 {
547 ::SelectObject(hMaskDC, hOldMaskBitmap);
8e9ff815 548 ::DeleteDC(hMaskDC);
62e1ba75 549
8bbbae21 550 ((wxBitmapRefData*)m_refData)->SetMask(hMaskBitmap);
62e1ba75 551 }
8e9ff815 552
e640f823
JS
553 SetWidth(image.GetWidth());
554 SetHeight(image.GetHeight());
555 SetDepth(screenDepth);
556 SetHBITMAP( (WXHBITMAP) hBitmap );
8e9ff815 557
e640f823
JS
558#if wxUSE_PALETTE
559 // Copy the palette from the source image
560 SetPalette(image.GetPalette());
561#endif // wxUSE_PALETTE
562
54a96d02
JS
563#if WXWIN_COMPATIBILITY_2
564 // check the wxBitmap object
565 GetBitmapData()->SetOk();
566#endif // WXWIN_COMPATIBILITY_2
567
e640f823 568 return TRUE;
fec19ea9
VS
569}
570
571wxImage wxBitmap::ConvertToImage() const
572{
e640f823
JS
573 // Initial attempt at a simple-minded implementation.
574 // The bitmap will always be created at the screen depth,
575 // so the 'depth' argument is ignored.
576 // TODO: transparency (create a mask image)
577
578 if (!Ok())
579 {
580 wxFAIL_MSG( wxT("bitmap is invalid") );
8e9ff815 581 return wxNullImage;
e640f823
JS
582 }
583
584 wxImage image;
585
586 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
587
588 // create an wxImage object
589 int width = GetWidth();
590 int height = GetHeight();
591 image.Create( width, height );
592 unsigned char *data = image.GetData();
593 if( !data )
594 {
595 wxFAIL_MSG( wxT("could not allocate data for image") );
596 return wxNullImage;
597 }
8e9ff815 598
e640f823
JS
599 HDC hScreenDC = ::GetDC(NULL);
600
601 HDC hMemDC = ::CreateCompatibleDC(hScreenDC);
602 ::ReleaseDC(NULL, hScreenDC);
603
604 HBITMAP hBitmap = (HBITMAP) GetHBITMAP();
8e9ff815 605
e640f823
JS
606 HBITMAP hOldBitmap = ::SelectObject(hMemDC, hBitmap);
607
608 int i, j;
609 for (i = 0; i < GetWidth(); i++)
610 {
8e9ff815
VZ
611 for (j = 0; j < GetHeight(); j++)
612 {
613 COLORREF color = ::GetPixel(hMemDC, i, j);
614 unsigned char red = GetRValue(color);
615 unsigned char green = GetGValue(color);
616 unsigned char blue = GetBValue(color);
617
618 image.SetRGB(i, j, red, green, blue);
619 }
e640f823
JS
620 }
621
622 ::SelectObject(hMemDC, hOldBitmap);
623 ::DeleteDC(hMemDC);
8e9ff815 624
e640f823
JS
625#if wxUSE_PALETTE
626 // Copy the palette from the source image
627 if (GetPalette())
628 image.SetPalette(* GetPalette());
629#endif // wxUSE_PALETTE
630
631 return image;
acf8e3d2
VZ
632}
633
634#endif // __WXMICROWIN__
635
636// ----------------------------------------------------------------------------
637// wxImage to/from conversions
638// ----------------------------------------------------------------------------
639
640bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
641{
642 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") );
643
644 UnRef();
645
646 // first convert the image to DIB
647 const int h = image.GetHeight();
648 const int w = image.GetWidth();
649
650 wxDIB dib(image);
651 if ( !dib.IsOk() )
652 return FALSE;
653
654
655 // store the bitmap parameters
656 wxBitmapRefData *refData = new wxBitmapRefData;
657 refData->m_width = w;
658 refData->m_height = h;
659 refData->m_depth = dib.GetDepth();
660 refData->m_hasAlpha = image.HasAlpha();
661
662 m_refData = refData;
663
664
665 // next either store DIB as is or create a DDB from it
666 HBITMAP hbitmap;
667
668 // TODO: if we're ready to use DIB as is, we can just do this:
669 // if ( ... )
670 // hbitmap = dib.Detach();
671 // else
672 {
673 // create and set the device-dependent bitmap
674 //
675 // VZ: why don't we just use SetDIBits() instead? because of the
676 // palette or is there some other reason?
677 hbitmap = ::CreateCompatibleBitmap(ScreenHDC(), w, h);
678 if ( !hbitmap )
679 {
680 wxLogLastError(_T("CreateCompatibleBitmap()"));
681
682 return FALSE;
683 }
684
685 MemoryHDC hdcMem;
686 SelectInHDC select(hdcMem, hbitmap);
687 if ( !select )
688 {
689 wxLogLastError(_T("SelectObjct(hBitmap)"));
690 }
691
692#if wxUSE_PALETTE
693 const wxPalette& palette = image.GetPalette();
e640f823 694
acf8e3d2
VZ
695 HPALETTE hOldPalette;
696 if ( palette.Ok() )
697 {
698 SetPalette(palette);
699
700 hOldPalette = ::SelectPalette
701 (
702 hdcMem,
703 GetHpaletteOf(palette),
704 FALSE // ignored for hdcMem
705 );
706
707 if ( !hOldPalette )
708 {
709 wxLogLastError(_T("SelectPalette()"));
710 }
711
712 if ( ::RealizePalette(hdcMem) == GDI_ERROR )
713 {
714 wxLogLastError(_T("RealizePalette()"));
715 }
716 }
717 else // no valid palette
718 {
719 hOldPalette = 0;
720 }
721#endif // wxUSE_PALETTE
722
723 DIBSECTION ds;
724 if ( !::GetObject(dib.GetHandle(), sizeof(ds), &ds) )
725 {
726 wxLogLastError(_T("GetObject(hDIB)"));
727 }
728
729 if ( ::StretchDIBits(hdcMem,
730 0, 0, w, h,
731 0, 0, w, h,
732 dib.GetData(),
733 (BITMAPINFO *)&ds.dsBmih,
734 DIB_RGB_COLORS,
735 SRCCOPY) == GDI_ERROR )
736 {
737 wxLogLastError(_T("StretchDIBits()"));
738
739 return FALSE;
740 }
741
742#if wxUSE_PALETTE
743 if ( hOldPalette )
744 {
745 ::SelectPalette(hdcMem, hOldPalette, FALSE);
746 }
747#endif // wxUSE_PALETTE
748 }
749
750 // validate this object
751 SetHBITMAP((WXHBITMAP)hbitmap);
752
753#if WXWIN_COMPATIBILITY_2
754 m_refData->m_ok = TRUE;
755#endif // WXWIN_COMPATIBILITY_2
756
757 // finally also set the mask if we have one
758 if ( image.HasMask() )
759 {
760 SetMask(new wxMask(*this, wxColour(image.GetMaskRed(),
761 image.GetMaskGreen(),
762 image.GetMaskBlue())));
763 }
764
765 return TRUE;
766}
767
768wxImage wxBitmap::ConvertToImage() const
769{
fec19ea9 770 wxImage image;
6d51f220 771
fec19ea9
VS
772 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
773
774 // create an wxImage object
775 int width = GetWidth();
776 int height = GetHeight();
777 image.Create( width, height );
778 unsigned char *data = image.GetData();
779 if( !data )
780 {
781 wxFAIL_MSG( wxT("could not allocate data for image") );
782 return wxNullImage;
783 }
784
785 // calc the number of bytes per scanline and padding in the DIB
786 int bytePerLine = width*3;
787 int sizeDWORD = sizeof( DWORD );
788 int lineBoundary = bytePerLine % sizeDWORD;
789 int padding = 0;
790 if( lineBoundary > 0 )
791 {
792 padding = sizeDWORD - lineBoundary;
793 bytePerLine += padding;
794 }
795
796 // create a DIB header
797 int headersize = sizeof(BITMAPINFOHEADER);
798 BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize );
799 if( !lpDIBh )
800 {
801 wxFAIL_MSG( wxT("could not allocate data for DIB header") );
802 free( data );
803 return wxNullImage;
804 }
805 // Fill in the DIB header
806 lpDIBh->bmiHeader.biSize = headersize;
807 lpDIBh->bmiHeader.biWidth = width;
808 lpDIBh->bmiHeader.biHeight = -height;
809 lpDIBh->bmiHeader.biSizeImage = bytePerLine * height;
810 lpDIBh->bmiHeader.biPlanes = 1;
811 lpDIBh->bmiHeader.biBitCount = 24;
812 lpDIBh->bmiHeader.biCompression = BI_RGB;
813 lpDIBh->bmiHeader.biClrUsed = 0;
814 // These seem not really needed for our purpose here.
815 lpDIBh->bmiHeader.biClrImportant = 0;
816 lpDIBh->bmiHeader.biXPelsPerMeter = 0;
817 lpDIBh->bmiHeader.biYPelsPerMeter = 0;
818 // memory for DIB data
819 unsigned char *lpBits;
820 lpBits = (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
821 if( !lpBits )
822 {
823 wxFAIL_MSG( wxT("could not allocate data for DIB") );
824 free( data );
825 free( lpDIBh );
826 return wxNullImage;
827 }
828
829 // copy data from the device-dependent bitmap to the DIB
830 HDC hdc = ::GetDC(NULL);
831 HBITMAP hbitmap;
832 hbitmap = (HBITMAP) GetHBITMAP();
833 ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
834
835 // copy DIB data into the wxImage object
836 int i, j;
837 unsigned char *ptdata = data;
838 unsigned char *ptbits = lpBits;
839 for( i=0; i<height; i++ )
840 {
841 for( j=0; j<width; j++ )
842 {
843 *(ptdata++) = *(ptbits+2);
844 *(ptdata++) = *(ptbits+1);
845 *(ptdata++) = *(ptbits );
846 ptbits += 3;
847 }
848 ptbits += padding;
849 }
850
851 // similarly, set data according to the possible mask bitmap
852 if( GetMask() && GetMask()->GetMaskBitmap() )
853 {
854 hbitmap = (HBITMAP) GetMask()->GetMaskBitmap();
855 // memory DC created, color set, data copied, and memory DC deleted
856 HDC memdc = ::CreateCompatibleDC( hdc );
857 ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
858 ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
859 ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
860 ::DeleteDC( memdc );
861 // background color set to RGB(16,16,16) in consistent with wxGTK
862 unsigned char r=16, g=16, b=16;
863 ptdata = data;
864 ptbits = lpBits;
865 for( i=0; i<height; i++ )
866 {
867 for( j=0; j<width; j++ )
868 {
869 if( *ptbits != 0 )
870 ptdata += 3;
871 else
872 {
873 *(ptdata++) = r;
874 *(ptdata++) = g;
875 *(ptdata++) = b;
876 }
877 ptbits += 3;
878 }
879 ptbits += padding;
880 }
881 image.SetMaskColour( r, g, b );
882 image.SetMask( TRUE );
883 }
884 else
885 {
886 image.SetMask( FALSE );
887 }
888 // free allocated resources
889 ::ReleaseDC(NULL, hdc);
890 free(lpDIBh);
891 free(lpBits);
892
893 return image;
894}
895
6d51f220
VZ
896#endif // wxUSE_IMAGE
897
acf8e3d2
VZ
898// ----------------------------------------------------------------------------
899// loading and saving bitmaps
900// ----------------------------------------------------------------------------
901
debe6624 902bool wxBitmap::LoadFile(const wxString& filename, long type)
2bda0e17 903{
6d167489 904 UnRef();
2bda0e17 905
6d167489 906 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 907
6d167489
VZ
908 if ( handler )
909 {
910 m_refData = new wxBitmapRefData;
2bda0e17 911
6d167489
VZ
912 return handler->LoadFile(this, filename, type, -1, -1);
913 }
6d51f220 914#if wxUSE_IMAGE
6d167489 915 else
b75dd496 916 {
6d167489 917 wxImage image;
6d51f220
VZ
918 if ( image.LoadFile( filename, type ) && image.Ok() )
919 {
368d59f0 920 *this = wxBitmap(image);
6d167489 921
6d51f220
VZ
922 return TRUE;
923 }
b75dd496 924 }
6d51f220
VZ
925#endif // wxUSE_IMAGE
926
927 return FALSE;
2bda0e17
KB
928}
929
debe6624 930bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
2bda0e17 931{
6d167489 932 UnRef();
2bda0e17 933
6d167489 934 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 935
6d167489
VZ
936 if ( !handler )
937 {
9b601c24 938 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %ld defined."), type);
2bda0e17 939
6d167489
VZ
940 return FALSE;
941 }
1d792928 942
6d167489 943 m_refData = new wxBitmapRefData;
1d792928 944
6d167489 945 return handler->Create(this, data, type, width, height, depth);
2bda0e17
KB
946}
947
d275c7eb
VZ
948bool wxBitmap::SaveFile(const wxString& filename,
949 int type,
950 const wxPalette *palette)
2bda0e17 951{
6d167489 952 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 953
6d167489
VZ
954 if ( handler )
955 {
956 return handler->SaveFile(this, filename, type, palette);
957 }
6d51f220 958#if wxUSE_IMAGE
6d167489
VZ
959 else
960 {
961 // FIXME what about palette? shouldn't we use it?
368d59f0 962 wxImage image = ConvertToImage();
6d51f220
VZ
963 if ( image.Ok() )
964 {
965 return image.SaveFile(filename, type);
966 }
6d167489 967 }
6d51f220
VZ
968#endif // wxUSE_IMAGE
969
970 return FALSE;
2bda0e17
KB
971}
972
4b7f2165
VZ
973// ----------------------------------------------------------------------------
974// sub bitmap extraction
975// ----------------------------------------------------------------------------
976
977wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
978{
979 wxCHECK_MSG( Ok() &&
980 (rect.x >= 0) && (rect.y >= 0) &&
981 (rect.x+rect.width <= GetWidth()) &&
982 (rect.y+rect.height <= GetHeight()),
983 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
984
acf8e3d2 985 wxBitmap ret( rect.width, rect.height );
4b7f2165
VZ
986 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
987
8e9ff815 988#ifndef __WXMICROWIN__
acf8e3d2
VZ
989 // TODO: copy alpha channel data if any
990
4b7f2165 991 // copy bitmap data
acf8e3d2
VZ
992 MemoryHDC dcSrc,
993 dcDst;
8e9ff815
VZ
994
995 {
996 SelectInHDC selectSrc(dcSrc, GetHbitmap()),
997 selectDst(dcDst, GetHbitmapOf(ret));
998
acf8e3d2
VZ
999 if ( !selectSrc || !selectDst )
1000 {
1001 wxLogLastError(_T("SelectObjct(hBitmap)"));
1002 }
1003
8e9ff815
VZ
1004 if ( !::BitBlt(dcDst, 0, 0, rect.width, rect.height,
1005 dcSrc, rect.x, rect.y, SRCCOPY) )
1006 {
1007 wxLogLastError(_T("BitBlt"));
1008 }
1009 }
4b7f2165
VZ
1010
1011 // copy mask if there is one
8e9ff815 1012 if ( GetMask() )
4b7f2165
VZ
1013 {
1014 HBITMAP hbmpMask = ::CreateBitmap(rect.width, rect.height, 1, 1, 0);
1015
8e9ff815
VZ
1016 SelectInHDC selectSrc(dcSrc, (HBITMAP) GetMask()->GetMaskBitmap()),
1017 selectDst(dcDst, hbmpMask);
1018
1019 if ( !::BitBlt(dcDst, 0, 0, rect.width, rect.height,
1020 dcSrc, rect.x, rect.y, SRCCOPY) )
1021 {
1022 wxLogLastError(_T("BitBlt"));
1023 }
4b7f2165
VZ
1024
1025 wxMask *mask = new wxMask((WXHBITMAP) hbmpMask);
1026 ret.SetMask(mask);
1027 }
8e9ff815 1028#endif // !__WXMICROWIN__
4b7f2165
VZ
1029
1030 return ret;
1031}
1032
6d167489
VZ
1033// ----------------------------------------------------------------------------
1034// wxBitmap accessors
1035// ----------------------------------------------------------------------------
2bda0e17 1036
8bbbae21 1037wxPalette* wxBitmap::GetPalette() const
2bda0e17 1038{
8bbbae21
VZ
1039 return GetBitmapData() ? &GetBitmapData()->m_bitmapPalette
1040 : (wxPalette *) NULL;
1041}
1042
1043wxMask *wxBitmap::GetMask() const
1044{
1045 return GetBitmapData() ? GetBitmapData()->GetMask() : (wxMask *) NULL;
1046}
2bda0e17 1047
3ca22d5e
MB
1048#ifdef __WXDEBUG__
1049
8bbbae21
VZ
1050wxDC *wxBitmap::GetSelectedInto() const
1051{
1052 return GetBitmapData() ? GetBitmapData()->m_selectedInto : (wxDC *) NULL;
2bda0e17
KB
1053}
1054
3ca22d5e
MB
1055#endif
1056
8bbbae21
VZ
1057#if WXWIN_COMPATIBILITY_2_4
1058
1059int wxBitmap::GetQuality() const
1060{
1061 return 0;
1062}
1063
1064#endif // WXWIN_COMPATIBILITY_2_4
1065
acf8e3d2
VZ
1066bool wxBitmap::HasAlpha() const
1067{
1068 return GetBitmapData() && GetBitmapData()->m_hasAlpha;
1069}
1070
8bbbae21
VZ
1071// ----------------------------------------------------------------------------
1072// wxBitmap setters
1073// ----------------------------------------------------------------------------
1074
3ca22d5e
MB
1075#ifdef __WXDEBUG__
1076
8bbbae21
VZ
1077void wxBitmap::SetSelectedInto(wxDC *dc)
1078{
1079 if ( GetBitmapData() )
1080 GetBitmapData()->m_selectedInto = dc;
2bda0e17
KB
1081}
1082
3ca22d5e
MB
1083#endif
1084
d275c7eb
VZ
1085#if wxUSE_PALETTE
1086
2bda0e17
KB
1087void wxBitmap::SetPalette(const wxPalette& palette)
1088{
6d167489 1089 EnsureHasData();
2bda0e17 1090
6d167489 1091 GetBitmapData()->m_bitmapPalette = palette;
2bda0e17
KB
1092}
1093
d275c7eb
VZ
1094#endif // wxUSE_PALETTE
1095
2bda0e17
KB
1096void wxBitmap::SetMask(wxMask *mask)
1097{
6d167489 1098 EnsureHasData();
2bda0e17 1099
8bbbae21
VZ
1100 GetBitmapData()->SetMask(mask);
1101}
1102
1103#if WXWIN_COMPATIBILITY_2
1104
1105void wxBitmap::SetOk(bool isOk)
1106{
1107 EnsureHasData();
1108
1109 GetBitmapData()->m_ok = isOk;
1110}
1111
1112#endif // WXWIN_COMPATIBILITY_2
1113
1114#if WXWIN_COMPATIBILITY_2_4
1115
1116void wxBitmap::SetQuality(int WXUNUSED(quality))
1117{
2bda0e17
KB
1118}
1119
8bbbae21
VZ
1120#endif // WXWIN_COMPATIBILITY_2_4
1121
1122// ----------------------------------------------------------------------------
1123// TODO: to be replaced by something better
1124// ----------------------------------------------------------------------------
1125
7b46ecac
JS
1126// Creates a bitmap that matches the device context, from
1127// an arbitray bitmap. At present, the original bitmap must have an
1128// associated palette. TODO: use a default palette if no palette exists.
1129// Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
1130wxBitmap wxBitmap::GetBitmapForDC(wxDC& dc) const
1131{
04ef50df 1132#ifdef __WXMICROWIN__
54a96d02 1133 return *this;
04ef50df 1134#else
7b46ecac 1135 wxMemoryDC memDC;
4b7f2165 1136 wxBitmap tmpBitmap(GetWidth(), GetHeight(), dc.GetDepth());
57c208c5 1137 HPALETTE hPal = (HPALETTE) NULL;
7b46ecac 1138 LPBITMAPINFO lpDib;
57c208c5 1139 void *lpBits = (void*) NULL;
7b46ecac 1140
d275c7eb 1141#if wxUSE_PALETTE
6d167489 1142 if( GetPalette() && GetPalette()->Ok() )
a367b9b3 1143 {
6d167489 1144 tmpBitmap.SetPalette(*GetPalette());
a367b9b3 1145 memDC.SelectObject(tmpBitmap);
6d167489
VZ
1146 memDC.SetPalette(*GetPalette());
1147 hPal = (HPALETTE)GetPalette()->GetHPALETTE();
a367b9b3
JS
1148 }
1149 else
1150 {
1151 hPal = (HPALETTE) ::GetStockObject(DEFAULT_PALETTE);
1152 wxPalette palette;
1153 palette.SetHPALETTE( (WXHPALETTE)hPal );
1154 tmpBitmap.SetPalette( palette );
1155 memDC.SelectObject(tmpBitmap);
1156 memDC.SetPalette( palette );
1157 }
d275c7eb
VZ
1158#else // !wxUSE_PALETTE
1159 hPal = (HPALETTE) ::GetStockObject(DEFAULT_PALETTE);
1160#endif // wxUSE_PALETTE/!wxUSE_PALETTE
7b46ecac 1161
6d167489
VZ
1162 // set the height negative because in a DIB the order of the lines is
1163 // reversed
1164 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal, &lpDib) )
1165 {
1166 return wxNullBitmap;
1167 }
7b46ecac
JS
1168
1169 lpBits = malloc(lpDib->bmiHeader.biSizeImage);
1170
6d167489 1171 ::GetBitmapBits(GetHbitmap(), lpDib->bmiHeader.biSizeImage, lpBits);
7b46ecac 1172
6d167489
VZ
1173 ::SetDIBitsToDevice(GetHdcOf(memDC), 0, 0,
1174 GetWidth(), GetHeight(),
1175 0, 0, 0, GetHeight(),
1176 lpBits, lpDib, DIB_RGB_COLORS);
7b46ecac
JS
1177
1178 free(lpBits);
1179
6d167489
VZ
1180 wxFreeDIB(lpDib);
1181
1182 return tmpBitmap;
04ef50df 1183#endif
7b46ecac
JS
1184}
1185
6d167489
VZ
1186// ----------------------------------------------------------------------------
1187// wxMask
1188// ----------------------------------------------------------------------------
2bda0e17 1189
10fcf31a 1190wxMask::wxMask()
2bda0e17
KB
1191{
1192 m_maskBitmap = 0;
1193}
1194
1195// Construct a mask from a bitmap and a colour indicating
1196// the transparent area
1197wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
1198{
1199 m_maskBitmap = 0;
6d167489 1200 Create(bitmap, colour);
2bda0e17
KB
1201}
1202
1203// Construct a mask from a bitmap and a palette index indicating
1204// the transparent area
debe6624 1205wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
1206{
1207 m_maskBitmap = 0;
6d167489 1208 Create(bitmap, paletteIndex);
2bda0e17
KB
1209}
1210
1211// Construct a mask from a mono bitmap (copies the bitmap).
1212wxMask::wxMask(const wxBitmap& bitmap)
1213{
1214 m_maskBitmap = 0;
6d167489 1215 Create(bitmap);
2bda0e17
KB
1216}
1217
10fcf31a 1218wxMask::~wxMask()
2bda0e17
KB
1219{
1220 if ( m_maskBitmap )
1221 ::DeleteObject((HBITMAP) m_maskBitmap);
1222}
1223
1224// Create a mask from a mono bitmap (copies the bitmap).
1225bool wxMask::Create(const wxBitmap& bitmap)
1226{
04ef50df 1227#ifndef __WXMICROWIN__
a58a12e9
VZ
1228 wxCHECK_MSG( bitmap.Ok() && bitmap.GetDepth() == 1, FALSE,
1229 _T("can't create mask from invalid or not monochrome bitmap") );
1230
2bda0e17 1231 if ( m_maskBitmap )
6d167489
VZ
1232 {
1233 ::DeleteObject((HBITMAP) m_maskBitmap);
1234 m_maskBitmap = 0;
1235 }
a58a12e9 1236
6d167489
VZ
1237 m_maskBitmap = (WXHBITMAP) CreateBitmap(
1238 bitmap.GetWidth(),
1239 bitmap.GetHeight(),
1240 1, 1, 0
1241 );
1242 HDC srcDC = CreateCompatibleDC(0);
1243 SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
1244 HDC destDC = CreateCompatibleDC(0);
1245 SelectObject(destDC, (HBITMAP) m_maskBitmap);
1246 BitBlt(destDC, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), srcDC, 0, 0, SRCCOPY);
1247 SelectObject(srcDC, 0);
1248 DeleteDC(srcDC);
1249 SelectObject(destDC, 0);
1250 DeleteDC(destDC);
1251 return TRUE;
04ef50df
JS
1252#else
1253 return FALSE;
1254#endif
2bda0e17
KB
1255}
1256
1257// Create a mask from a bitmap and a palette index indicating
1258// the transparent area
debe6624 1259bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
1260{
1261 if ( m_maskBitmap )
1d792928 1262 {
6d167489
VZ
1263 ::DeleteObject((HBITMAP) m_maskBitmap);
1264 m_maskBitmap = 0;
1d792928 1265 }
d275c7eb
VZ
1266
1267#if wxUSE_PALETTE
6d167489
VZ
1268 if (bitmap.Ok() && bitmap.GetPalette()->Ok())
1269 {
1270 unsigned char red, green, blue;
1271 if (bitmap.GetPalette()->GetRGB(paletteIndex, &red, &green, &blue))
1272 {
1273 wxColour transparentColour(red, green, blue);
1274 return Create(bitmap, transparentColour);
1275 }
1276 }
d275c7eb
VZ
1277#endif // wxUSE_PALETTE
1278
6d167489 1279 return FALSE;
2bda0e17
KB
1280}
1281
1282// Create a mask from a bitmap and a colour indicating
1283// the transparent area
1284bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
1285{
04ef50df 1286#ifndef __WXMICROWIN__
4b7f2165
VZ
1287 wxCHECK_MSG( bitmap.Ok(), FALSE, _T("invalid bitmap in wxMask::Create") );
1288
2bda0e17 1289 if ( m_maskBitmap )
1d792928 1290 {
6d167489
VZ
1291 ::DeleteObject((HBITMAP) m_maskBitmap);
1292 m_maskBitmap = 0;
1293 }
4b7f2165
VZ
1294
1295 int width = bitmap.GetWidth(),
1296 height = bitmap.GetHeight();
1297
1298 // scan the bitmap for the transparent colour and set the corresponding
1299 // pixels in the mask to BLACK and the rest to WHITE
f423f4db 1300 COLORREF maskColour = wxColourToPalRGB(colour);
4b7f2165
VZ
1301 m_maskBitmap = (WXHBITMAP)::CreateBitmap(width, height, 1, 1, 0);
1302
1303 HDC srcDC = ::CreateCompatibleDC(NULL);
1304 HDC destDC = ::CreateCompatibleDC(NULL);
1305 if ( !srcDC || !destDC )
1306 {
f6bcfd97 1307 wxLogLastError(wxT("CreateCompatibleDC"));
4b7f2165
VZ
1308 }
1309
0bafad0c
VZ
1310 bool ok = TRUE;
1311
1e6feb95
VZ
1312 // SelectObject() will fail
1313 wxASSERT_MSG( !bitmap.GetSelectedInto(),
1314 _T("bitmap can't be selected in another DC") );
1315
0bafad0c
VZ
1316 HGDIOBJ hbmpSrcOld = ::SelectObject(srcDC, GetHbitmapOf(bitmap));
1317 if ( !hbmpSrcOld )
6d167489 1318 {
f6bcfd97 1319 wxLogLastError(wxT("SelectObject"));
0bafad0c
VZ
1320
1321 ok = FALSE;
4b7f2165 1322 }
0bafad0c
VZ
1323
1324 HGDIOBJ hbmpDstOld = ::SelectObject(destDC, (HBITMAP)m_maskBitmap);
1325 if ( !hbmpDstOld )
4b7f2165 1326 {
f6bcfd97 1327 wxLogLastError(wxT("SelectObject"));
0bafad0c
VZ
1328
1329 ok = FALSE;
1d792928 1330 }
2bda0e17 1331
59ff46cb 1332 if ( ok )
2bda0e17 1333 {
59ff46cb
VZ
1334 // this will create a monochrome bitmap with 0 points for the pixels
1335 // which have the same value as the background colour and 1 for the
1336 // others
1337 ::SetBkColor(srcDC, maskColour);
1338 ::BitBlt(destDC, 0, 0, width, height, srcDC, 0, 0, NOTSRCCOPY);
2bda0e17 1339 }
4b7f2165 1340
0bafad0c 1341 ::SelectObject(srcDC, hbmpSrcOld);
6d167489 1342 ::DeleteDC(srcDC);
0bafad0c 1343 ::SelectObject(destDC, hbmpDstOld);
6d167489 1344 ::DeleteDC(destDC);
4b7f2165 1345
0bafad0c 1346 return ok;
59ff46cb 1347#else // __WXMICROWIN__
04ef50df 1348 return FALSE;
59ff46cb 1349#endif // __WXMICROWIN__/!__WXMICROWIN__
6d167489
VZ
1350}
1351
1352// ----------------------------------------------------------------------------
1353// wxBitmapHandler
1354// ----------------------------------------------------------------------------
1d792928 1355
6d167489
VZ
1356bool wxBitmapHandler::Create(wxGDIImage *image,
1357 void *data,
1358 long flags,
1359 int width, int height, int depth)
1360{
1361 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
1d792928 1362
8c1375b9 1363 return bitmap ? Create(bitmap, data, flags, width, height, depth) : FALSE;
2bda0e17
KB
1364}
1365
6d167489
VZ
1366bool wxBitmapHandler::Load(wxGDIImage *image,
1367 const wxString& name,
1368 long flags,
1369 int width, int height)
2bda0e17 1370{
6d167489 1371 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
2bda0e17 1372
6d167489
VZ
1373 return bitmap ? LoadFile(bitmap, name, flags, width, height) : FALSE;
1374}
2bda0e17 1375
6d167489
VZ
1376bool wxBitmapHandler::Save(wxGDIImage *image,
1377 const wxString& name,
1378 int type)
2bda0e17 1379{
6d167489
VZ
1380 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
1381
1382 return bitmap ? SaveFile(bitmap, name, type) : FALSE;
2bda0e17
KB
1383}
1384
6d167489
VZ
1385bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap),
1386 void *WXUNUSED(data),
1387 long WXUNUSED(type),
1388 int WXUNUSED(width),
1389 int WXUNUSED(height),
1390 int WXUNUSED(depth))
2bda0e17 1391{
6d167489 1392 return FALSE;
2bda0e17
KB
1393}
1394
6d167489
VZ
1395bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap),
1396 const wxString& WXUNUSED(name),
1397 long WXUNUSED(type),
1398 int WXUNUSED(desiredWidth),
1399 int WXUNUSED(desiredHeight))
2bda0e17 1400{
6d167489 1401 return FALSE;
2bda0e17
KB
1402}
1403
6d167489
VZ
1404bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap),
1405 const wxString& WXUNUSED(name),
1406 int WXUNUSED(type),
1407 const wxPalette *WXUNUSED(palette))
2bda0e17 1408{
6d167489 1409 return FALSE;
7b46ecac
JS
1410}
1411
6d167489
VZ
1412// ----------------------------------------------------------------------------
1413// DIB functions
1414// ----------------------------------------------------------------------------
1415
04ef50df 1416#ifndef __WXMICROWIN__
6d167489
VZ
1417bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel,
1418 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader)
7b46ecac
JS
1419{
1420 unsigned long i, headerSize;
1421 LPBITMAPINFO lpDIBheader = NULL;
1422 LPPALETTEENTRY lpPe = NULL;
1423
1424
1425 // Allocate space for a DIB header
1426 headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY)));
1427 lpDIBheader = (BITMAPINFO *) malloc(headerSize);
1428 lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER));
1429
1430 GetPaletteEntries(hPal, 0, 256, lpPe);
1431
7b46ecac
JS
1432 memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER));
1433
7b46ecac
JS
1434 // Fill in the static parts of the DIB header
1435 lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1436 lpDIBheader->bmiHeader.biWidth = xSize;
1437 lpDIBheader->bmiHeader.biHeight = ySize;
1438 lpDIBheader->bmiHeader.biPlanes = 1;
1439
1440 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
1441 lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel);
1442 lpDIBheader->bmiHeader.biCompression = BI_RGB;
6d167489 1443 lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >> 3;
7b46ecac
JS
1444 lpDIBheader->bmiHeader.biClrUsed = 256;
1445
1446
1447 // Initialize the DIB palette
1448 for (i = 0; i < 256; i++) {
1449 lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags;
1450 lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed;
1451 lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen;
1452 lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue;
1453 }
1454
1455 *lpDIBHeader = lpDIBheader;
1456
6d167489 1457 return TRUE;
7b46ecac
JS
1458}
1459
6d167489 1460void wxFreeDIB(LPBITMAPINFO lpDIBHeader)
7b46ecac 1461{
6d167489 1462 free(lpDIBHeader);
7b46ecac 1463}
04ef50df 1464#endif
7b46ecac 1465
4b7f2165
VZ
1466// ----------------------------------------------------------------------------
1467// other helper functions
1468// ----------------------------------------------------------------------------
1469
1470extern HBITMAP wxInvertMask(HBITMAP hbmpMask, int w, int h)
1471{
04ef50df 1472#ifndef __WXMICROWIN__
4b7f2165
VZ
1473 wxCHECK_MSG( hbmpMask, 0, _T("invalid bitmap in wxInvertMask") );
1474
1475 // get width/height from the bitmap if not given
1476 if ( !w || !h )
1477 {
1478 BITMAP bm;
1479 ::GetObject(hbmpMask, sizeof(BITMAP), (LPVOID)&bm);
1480 w = bm.bmWidth;
1481 h = bm.bmHeight;
1482 }
1483
1484 HDC hdcSrc = ::CreateCompatibleDC(NULL);
1485 HDC hdcDst = ::CreateCompatibleDC(NULL);
1486 if ( !hdcSrc || !hdcDst )
1487 {
f6bcfd97 1488 wxLogLastError(wxT("CreateCompatibleDC"));
4b7f2165
VZ
1489 }
1490
1491 HBITMAP hbmpInvMask = ::CreateBitmap(w, h, 1, 1, 0);
1492 if ( !hbmpInvMask )
1493 {
f6bcfd97 1494 wxLogLastError(wxT("CreateBitmap"));
4b7f2165
VZ
1495 }
1496
1497 ::SelectObject(hdcSrc, hbmpMask);
1498 ::SelectObject(hdcDst, hbmpInvMask);
1499 if ( !::BitBlt(hdcDst, 0, 0, w, h,
1500 hdcSrc, 0, 0,
1501 NOTSRCCOPY) )
1502 {
f6bcfd97 1503 wxLogLastError(wxT("BitBlt"));
4b7f2165 1504 }
7b46ecac 1505
4b7f2165
VZ
1506 ::DeleteDC(hdcSrc);
1507 ::DeleteDC(hdcDst);
1508
1509 return hbmpInvMask;
04ef50df
JS
1510#else
1511 return 0;
1512#endif
4b7f2165 1513}