]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bitmap.cpp
fix from Robert for extra refreshes
[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
2bda0e17 46#include "wx/msw/dib.h"
b75dd496 47#include "wx/image.h"
2bda0e17 48
3c1a88d8
VZ
49// missing from mingw32 header
50#ifndef CLR_INVALID
51 #define CLR_INVALID ((COLORREF)-1)
52#endif // no CLR_INVALID
53
10fcf31a
VZ
54// ----------------------------------------------------------------------------
55// macros
56// ----------------------------------------------------------------------------
57
4b7f2165
VZ
58IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
59IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
6d167489 60
4b7f2165 61IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
2bda0e17 62
10fcf31a
VZ
63// ============================================================================
64// implementation
65// ============================================================================
66
67// ----------------------------------------------------------------------------
68// wxBitmapRefData
69// ----------------------------------------------------------------------------
70
71wxBitmapRefData::wxBitmapRefData()
2bda0e17 72{
6d167489
VZ
73 m_quality = 0;
74 m_selectedInto = NULL;
75 m_numColors = 0;
76 m_bitmapMask = NULL;
340196c0 77 m_hBitmap = (WXHBITMAP) NULL;
2bda0e17
KB
78}
79
6d167489 80void wxBitmapRefData::Free()
2bda0e17 81{
d59ceba5
VZ
82 wxASSERT_MSG( !m_selectedInto,
83 wxT("deleting bitmap still selected into wxMemoryDC") );
2bda0e17 84
d59ceba5 85 if ( m_hBitmap)
6d167489
VZ
86 {
87 if ( !::DeleteObject((HBITMAP)m_hBitmap) )
88 {
f6bcfd97 89 wxLogLastError(wxT("DeleteObject(hbitmap)"));
6d167489
VZ
90 }
91 }
e7003166 92
6d167489
VZ
93 delete m_bitmapMask;
94 m_bitmapMask = NULL;
2bda0e17
KB
95}
96
10fcf31a 97// ----------------------------------------------------------------------------
6d167489 98// wxBitmap creation
10fcf31a
VZ
99// ----------------------------------------------------------------------------
100
4fe5383d
VZ
101// this function should be called from all wxBitmap ctors
102void wxBitmap::Init()
2bda0e17 103{
4fe5383d 104 // m_refData = NULL; done in the base class ctor
2bda0e17 105
07cf98cb
VZ
106 if ( wxTheBitmapList )
107 wxTheBitmapList->AddBitmap(this);
4fe5383d
VZ
108}
109
6d167489
VZ
110#ifdef __WIN32__
111
112bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon)
113{
114 // it may be either HICON or HCURSOR
115 HICON hicon = (HICON)icon.GetHandle();
116
117 ICONINFO iconInfo;
118 if ( !::GetIconInfo(hicon, &iconInfo) )
119 {
f6bcfd97 120 wxLogLastError(wxT("GetIconInfo"));
6d167489
VZ
121
122 return FALSE;
123 }
124
125 wxBitmapRefData *refData = new wxBitmapRefData;
126 m_refData = refData;
127
d9c8e68e
VZ
128 int w = icon.GetWidth(),
129 h = icon.GetHeight();
130
131 refData->m_width = w;
132 refData->m_height = h;
6d167489
VZ
133 refData->m_depth = wxDisplayDepth();
134
135 refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor;
d9c8e68e
VZ
136
137 // the mask returned by GetIconInfo() is inversed compared to the usual
138 // wxWin convention
4b7f2165
VZ
139 refData->m_bitmapMask = new wxMask((WXHBITMAP)
140 wxInvertMask(iconInfo.hbmMask, w, h));
6d167489
VZ
141
142#if WXWIN_COMPATIBILITY_2
143 refData->m_ok = TRUE;
144#endif // WXWIN_COMPATIBILITY_2
145
146 return TRUE;
147}
148
149#endif // Win32
150
151bool wxBitmap::CopyFromCursor(const wxCursor& cursor)
4fe5383d
VZ
152{
153 UnRef();
07cf98cb 154
6d167489 155 if ( !cursor.Ok() )
4fe5383d 156 return FALSE;
07cf98cb 157
6d167489
VZ
158#ifdef __WIN16__
159 wxFAIL_MSG( _T("don't know how to convert cursor to bitmap") );
160
161 return FALSE;
8f177c8e 162#else
6d167489 163 return CopyFromIconOrCursor(cursor);
8f177c8e 164#endif // Win16
6d167489
VZ
165}
166
167bool wxBitmap::CopyFromIcon(const wxIcon& icon)
168{
169 UnRef();
07cf98cb 170
6d167489
VZ
171 if ( !icon.Ok() )
172 return FALSE;
4fe5383d
VZ
173
174 // GetIconInfo() doesn't exist under Win16 and I don't know any other way
175 // to create a bitmap from icon there - but using this way we won't have
176 // the mask (FIXME)
177#ifdef __WIN16__
6d167489
VZ
178 int width = icon.GetWidth(),
179 height = icon.GetHeight();
180
4fe5383d 181 // copy the icon to the bitmap
6d167489 182 ScreenHDC hdcScreen;
4fe5383d
VZ
183 HDC hdc = ::CreateCompatibleDC(hdcScreen);
184 HBITMAP hbitmap = ::CreateCompatibleBitmap(hdcScreen, width, height);
07cf98cb
VZ
185 HBITMAP hbmpOld = (HBITMAP)::SelectObject(hdc, hbitmap);
186
6d167489 187 ::DrawIcon(hdc, 0, 0, GetHiconOf(icon));
07cf98cb
VZ
188
189 ::SelectObject(hdc, hbmpOld);
190 ::DeleteDC(hdc);
4fe5383d 191
6d167489
VZ
192 wxBitmapRefData *refData = new wxBitmapRefData;
193 m_refData = refData;
4fe5383d 194
6d167489
VZ
195 refData->m_width = width;
196 refData->m_height = height;
197 refData->m_depth = wxDisplayDepth();
07cf98cb 198
6d167489 199 refData->m_hBitmap = (WXHBITMAP)hbitmap;
07cf98cb 200
6d167489
VZ
201#if WXWIN_COMPATIBILITY_2
202 refData->m_ok = TRUE;
203#endif // WXWIN_COMPATIBILITY_2
222594ea 204
4fe5383d 205 return TRUE;
6d167489
VZ
206#else // Win32
207 return CopyFromIconOrCursor(icon);
208#endif // Win16/Win32
10fcf31a
VZ
209}
210
211wxBitmap::~wxBitmap()
2bda0e17
KB
212{
213 if (wxTheBitmapList)
214 wxTheBitmapList->DeleteObject(this);
215}
216
5bd3a2da 217wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
2bda0e17 218{
4fe5383d 219 Init();
2bda0e17 220
6d167489
VZ
221 wxBitmapRefData *refData = new wxBitmapRefData;
222 m_refData = refData;
2bda0e17 223
5bd3a2da
VZ
224 refData->m_width = width;
225 refData->m_height = height;
226 refData->m_depth = depth;
6d167489
VZ
227 refData->m_numColors = 0;
228 refData->m_selectedInto = NULL;
2bda0e17 229
5bd3a2da
VZ
230 char *data;
231 if ( depth == 1 )
232 {
233 // we assume that it is in XBM format which is not quite the same as
234 // the format CreateBitmap() wants because the order of bytes in the
235 // line is inversed!
236 static const size_t bytesPerLine = (width + 7) / 8;
237 static const size_t padding = bytesPerLine % 2;
238 static const size_t len = height * ( padding + bytesPerLine );
239 data = (char *)malloc(len);
240 const char *src = bits;
241 char *dst = data;
242
243 for ( int rows = 0; rows < height; rows++ )
244 {
0765adca 245 for ( size_t cols = 0; cols < bytesPerLine; cols++ )
5bd3a2da 246 {
0765adca
VZ
247 unsigned char val = *src++;
248 unsigned char reversed = 0;
249
250 for ( int bits = 0; bits < 8; bits++)
251 {
252 reversed <<= 1;
253 reversed |= (val & 0x01);
254 val >>= 1;
255 }
256 *dst++ = reversed;
5bd3a2da
VZ
257 }
258
259 if ( padding )
260 *dst++ = 0;
5bd3a2da
VZ
261 }
262 }
263 else
264 {
265 // bits should already be in Windows standard format
266 data = (char *)bits; // const_cast is harmless
267 }
268
269 HBITMAP hbmp = ::CreateBitmap(width, height, 1, depth, data);
6d167489
VZ
270 if ( !hbmp )
271 {
f6bcfd97 272 wxLogLastError(wxT("CreateBitmap"));
6d167489 273 }
2bda0e17 274
5bd3a2da
VZ
275 if ( data != bits )
276 {
277 free(data);
278 }
279
6d167489 280 SetHBITMAP((WXHBITMAP)hbmp);
2bda0e17
KB
281}
282
2fd284a4 283// Create from XPM data
4b7f2165 284bool wxBitmap::CreateFromXpm(const char **data)
2fd284a4 285{
4fe5383d
VZ
286 Init();
287
4b7f2165 288 return Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
2fd284a4
JS
289}
290
debe6624 291wxBitmap::wxBitmap(int w, int h, int d)
2bda0e17 292{
4fe5383d 293 Init();
2bda0e17 294
4fe5383d 295 (void)Create(w, h, d);
2bda0e17
KB
296}
297
debe6624 298wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
2bda0e17 299{
4fe5383d 300 Init();
2bda0e17 301
6d167489 302 (void)Create(data, type, width, height, depth);
2bda0e17
KB
303}
304
debe6624 305wxBitmap::wxBitmap(const wxString& filename, long type)
2bda0e17 306{
4fe5383d 307 Init();
2bda0e17 308
4fe5383d 309 LoadFile(filename, (int)type);
2bda0e17
KB
310}
311
debe6624 312bool wxBitmap::Create(int w, int h, int d)
2bda0e17 313{
6d167489
VZ
314 UnRef();
315
316 m_refData = new wxBitmapRefData;
317
318 GetBitmapData()->m_width = w;
319 GetBitmapData()->m_height = h;
320 GetBitmapData()->m_depth = d;
321
322 HBITMAP hbmp;
323
324 if ( d > 0 )
325 {
326 hbmp = ::CreateBitmap(w, h, 1, d, NULL);
327 if ( !hbmp )
328 {
f6bcfd97 329 wxLogLastError(wxT("CreateBitmap"));
6d167489
VZ
330 }
331 }
332 else
333 {
334 ScreenHDC dc;
335 hbmp = ::CreateCompatibleBitmap(dc, w, h);
336 if ( !hbmp )
337 {
f6bcfd97 338 wxLogLastError(wxT("CreateCompatibleBitmap"));
6d167489
VZ
339 }
340
341 GetBitmapData()->m_depth = wxDisplayDepth();
342 }
2bda0e17 343
6d167489 344 SetHBITMAP((WXHBITMAP)hbmp);
2bda0e17 345
6d167489
VZ
346#if WXWIN_COMPATIBILITY_2
347 GetBitmapData()->m_ok = hbmp != 0;
348#endif // WXWIN_COMPATIBILITY_2
2bda0e17 349
6d167489 350 return Ok();
2bda0e17
KB
351}
352
debe6624 353bool wxBitmap::LoadFile(const wxString& filename, long type)
2bda0e17 354{
6d167489 355 UnRef();
2bda0e17 356
6d167489 357 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 358
6d167489
VZ
359 if ( handler )
360 {
361 m_refData = new wxBitmapRefData;
2bda0e17 362
6d167489
VZ
363 return handler->LoadFile(this, filename, type, -1, -1);
364 }
365 else
b75dd496 366 {
6d167489
VZ
367 wxImage image;
368 if ( !image.LoadFile( filename, type ) || !image.Ok() )
369 return FALSE;
370
b75dd496 371 *this = image.ConvertToBitmap();
6d167489 372
b75dd496
VS
373 return TRUE;
374 }
2bda0e17
KB
375}
376
debe6624 377bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
2bda0e17 378{
6d167489 379 UnRef();
2bda0e17 380
6d167489 381 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 382
6d167489
VZ
383 if ( !handler )
384 {
f6bcfd97 385 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %d defined."), type);
2bda0e17 386
6d167489
VZ
387 return FALSE;
388 }
1d792928 389
6d167489 390 m_refData = new wxBitmapRefData;
1d792928 391
6d167489 392 return handler->Create(this, data, type, width, height, depth);
2bda0e17
KB
393}
394
debe6624 395bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
2bda0e17 396{
6d167489 397 wxBitmapHandler *handler = wxDynamicCast(FindHandler(type), wxBitmapHandler);
2bda0e17 398
6d167489
VZ
399 if ( handler )
400 {
401 return handler->SaveFile(this, filename, type, palette);
402 }
403 else
404 {
405 // FIXME what about palette? shouldn't we use it?
406 wxImage image( *this );
407 if (!image.Ok())
408 return FALSE;
2bda0e17 409
6d167489
VZ
410 return image.SaveFile( filename, type );
411 }
2bda0e17
KB
412}
413
4b7f2165
VZ
414// ----------------------------------------------------------------------------
415// sub bitmap extraction
416// ----------------------------------------------------------------------------
417
418wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
419{
420 wxCHECK_MSG( Ok() &&
421 (rect.x >= 0) && (rect.y >= 0) &&
422 (rect.x+rect.width <= GetWidth()) &&
423 (rect.y+rect.height <= GetHeight()),
424 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
425
426 wxBitmap ret( rect.width, rect.height, GetDepth() );
427 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
428
429 // copy bitmap data
430 HDC dcSrc = ::CreateCompatibleDC(NULL);
431 HDC dcDst = ::CreateCompatibleDC(NULL);
432 SelectObject(dcSrc, (HBITMAP) GetHBITMAP());
433 SelectObject(dcDst, (HBITMAP) ret.GetHBITMAP());
434 BitBlt(dcDst, 0, 0, rect.width, rect.height, dcSrc, rect.x, rect.y, SRCCOPY);
435
436 // copy mask if there is one
437 if (GetMask())
438 {
439 HBITMAP hbmpMask = ::CreateBitmap(rect.width, rect.height, 1, 1, 0);
440
441 SelectObject(dcSrc, (HBITMAP) GetMask()->GetMaskBitmap());
442 SelectObject(dcDst, (HBITMAP) hbmpMask);
443 BitBlt(dcDst, 0, 0, rect.width, rect.height, dcSrc, rect.x, rect.y, SRCCOPY);
444
445 wxMask *mask = new wxMask((WXHBITMAP) hbmpMask);
446 ret.SetMask(mask);
447 }
448
449 SelectObject(dcDst, NULL);
450 SelectObject(dcSrc, NULL);
451 DeleteDC(dcDst);
452 DeleteDC(dcSrc);
453
454 return ret;
455}
456
6d167489
VZ
457// ----------------------------------------------------------------------------
458// wxBitmap accessors
459// ----------------------------------------------------------------------------
2bda0e17
KB
460
461void wxBitmap::SetQuality(int q)
462{
6d167489 463 EnsureHasData();
2bda0e17 464
6d167489 465 GetBitmapData()->m_quality = q;
2bda0e17
KB
466}
467
6d167489 468#if WXWIN_COMPATIBILITY_2
2bda0e17
KB
469void wxBitmap::SetOk(bool isOk)
470{
6d167489 471 EnsureHasData();
2bda0e17 472
6d167489 473 GetBitmapData()->m_ok = isOk;
2bda0e17 474}
6d167489 475#endif // WXWIN_COMPATIBILITY_2
2bda0e17
KB
476
477void wxBitmap::SetPalette(const wxPalette& palette)
478{
6d167489 479 EnsureHasData();
2bda0e17 480
6d167489 481 GetBitmapData()->m_bitmapPalette = palette;
2bda0e17
KB
482}
483
484void wxBitmap::SetMask(wxMask *mask)
485{
6d167489 486 EnsureHasData();
2bda0e17 487
6d167489 488 GetBitmapData()->m_bitmapMask = mask;
2bda0e17
KB
489}
490
7b46ecac
JS
491// Creates a bitmap that matches the device context, from
492// an arbitray bitmap. At present, the original bitmap must have an
493// associated palette. TODO: use a default palette if no palette exists.
494// Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
495wxBitmap wxBitmap::GetBitmapForDC(wxDC& dc) const
496{
497 wxMemoryDC memDC;
4b7f2165 498 wxBitmap tmpBitmap(GetWidth(), GetHeight(), dc.GetDepth());
57c208c5 499 HPALETTE hPal = (HPALETTE) NULL;
7b46ecac 500 LPBITMAPINFO lpDib;
57c208c5 501 void *lpBits = (void*) NULL;
7b46ecac 502
6d167489 503 if( GetPalette() && GetPalette()->Ok() )
a367b9b3 504 {
6d167489 505 tmpBitmap.SetPalette(*GetPalette());
a367b9b3 506 memDC.SelectObject(tmpBitmap);
6d167489
VZ
507 memDC.SetPalette(*GetPalette());
508 hPal = (HPALETTE)GetPalette()->GetHPALETTE();
a367b9b3
JS
509 }
510 else
511 {
512 hPal = (HPALETTE) ::GetStockObject(DEFAULT_PALETTE);
513 wxPalette palette;
514 palette.SetHPALETTE( (WXHPALETTE)hPal );
515 tmpBitmap.SetPalette( palette );
516 memDC.SelectObject(tmpBitmap);
517 memDC.SetPalette( palette );
518 }
7b46ecac 519
6d167489
VZ
520 // set the height negative because in a DIB the order of the lines is
521 // reversed
522 if ( !wxCreateDIB(GetWidth(), -GetHeight(), GetDepth(), hPal, &lpDib) )
523 {
524 return wxNullBitmap;
525 }
7b46ecac
JS
526
527 lpBits = malloc(lpDib->bmiHeader.biSizeImage);
528
6d167489 529 ::GetBitmapBits(GetHbitmap(), lpDib->bmiHeader.biSizeImage, lpBits);
7b46ecac 530
6d167489
VZ
531 ::SetDIBitsToDevice(GetHdcOf(memDC), 0, 0,
532 GetWidth(), GetHeight(),
533 0, 0, 0, GetHeight(),
534 lpBits, lpDib, DIB_RGB_COLORS);
7b46ecac
JS
535
536 free(lpBits);
537
6d167489
VZ
538 wxFreeDIB(lpDib);
539
540 return tmpBitmap;
7b46ecac
JS
541}
542
6d167489
VZ
543// ----------------------------------------------------------------------------
544// wxMask
545// ----------------------------------------------------------------------------
2bda0e17 546
10fcf31a 547wxMask::wxMask()
2bda0e17
KB
548{
549 m_maskBitmap = 0;
550}
551
552// Construct a mask from a bitmap and a colour indicating
553// the transparent area
554wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
555{
556 m_maskBitmap = 0;
6d167489 557 Create(bitmap, colour);
2bda0e17
KB
558}
559
560// Construct a mask from a bitmap and a palette index indicating
561// the transparent area
debe6624 562wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
563{
564 m_maskBitmap = 0;
6d167489 565 Create(bitmap, paletteIndex);
2bda0e17
KB
566}
567
568// Construct a mask from a mono bitmap (copies the bitmap).
569wxMask::wxMask(const wxBitmap& bitmap)
570{
571 m_maskBitmap = 0;
6d167489 572 Create(bitmap);
2bda0e17
KB
573}
574
10fcf31a 575wxMask::~wxMask()
2bda0e17
KB
576{
577 if ( m_maskBitmap )
578 ::DeleteObject((HBITMAP) m_maskBitmap);
579}
580
581// Create a mask from a mono bitmap (copies the bitmap).
582bool wxMask::Create(const wxBitmap& bitmap)
583{
a58a12e9
VZ
584 wxCHECK_MSG( bitmap.Ok() && bitmap.GetDepth() == 1, FALSE,
585 _T("can't create mask from invalid or not monochrome bitmap") );
586
2bda0e17 587 if ( m_maskBitmap )
6d167489
VZ
588 {
589 ::DeleteObject((HBITMAP) m_maskBitmap);
590 m_maskBitmap = 0;
591 }
a58a12e9 592
6d167489
VZ
593 m_maskBitmap = (WXHBITMAP) CreateBitmap(
594 bitmap.GetWidth(),
595 bitmap.GetHeight(),
596 1, 1, 0
597 );
598 HDC srcDC = CreateCompatibleDC(0);
599 SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
600 HDC destDC = CreateCompatibleDC(0);
601 SelectObject(destDC, (HBITMAP) m_maskBitmap);
602 BitBlt(destDC, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), srcDC, 0, 0, SRCCOPY);
603 SelectObject(srcDC, 0);
604 DeleteDC(srcDC);
605 SelectObject(destDC, 0);
606 DeleteDC(destDC);
607 return TRUE;
2bda0e17
KB
608}
609
610// Create a mask from a bitmap and a palette index indicating
611// the transparent area
debe6624 612bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
613{
614 if ( m_maskBitmap )
1d792928 615 {
6d167489
VZ
616 ::DeleteObject((HBITMAP) m_maskBitmap);
617 m_maskBitmap = 0;
1d792928 618 }
6d167489
VZ
619 if (bitmap.Ok() && bitmap.GetPalette()->Ok())
620 {
621 unsigned char red, green, blue;
622 if (bitmap.GetPalette()->GetRGB(paletteIndex, &red, &green, &blue))
623 {
624 wxColour transparentColour(red, green, blue);
625 return Create(bitmap, transparentColour);
626 }
627 }
628 return FALSE;
2bda0e17
KB
629}
630
631// Create a mask from a bitmap and a colour indicating
632// the transparent area
633bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
634{
4b7f2165
VZ
635 wxCHECK_MSG( bitmap.Ok(), FALSE, _T("invalid bitmap in wxMask::Create") );
636
2bda0e17 637 if ( m_maskBitmap )
1d792928 638 {
6d167489
VZ
639 ::DeleteObject((HBITMAP) m_maskBitmap);
640 m_maskBitmap = 0;
641 }
4b7f2165
VZ
642
643 int width = bitmap.GetWidth(),
644 height = bitmap.GetHeight();
645
646 // scan the bitmap for the transparent colour and set the corresponding
647 // pixels in the mask to BLACK and the rest to WHITE
648 COLORREF maskColour = wxColourToRGB(colour);
649 m_maskBitmap = (WXHBITMAP)::CreateBitmap(width, height, 1, 1, 0);
650
651 HDC srcDC = ::CreateCompatibleDC(NULL);
652 HDC destDC = ::CreateCompatibleDC(NULL);
653 if ( !srcDC || !destDC )
654 {
f6bcfd97 655 wxLogLastError(wxT("CreateCompatibleDC"));
4b7f2165
VZ
656 }
657
0bafad0c
VZ
658 bool ok = TRUE;
659
660 HGDIOBJ hbmpSrcOld = ::SelectObject(srcDC, GetHbitmapOf(bitmap));
661 if ( !hbmpSrcOld )
6d167489 662 {
f6bcfd97 663 wxLogLastError(wxT("SelectObject"));
0bafad0c
VZ
664
665 ok = FALSE;
4b7f2165 666 }
0bafad0c
VZ
667
668 HGDIOBJ hbmpDstOld = ::SelectObject(destDC, (HBITMAP)m_maskBitmap);
669 if ( !hbmpDstOld )
4b7f2165 670 {
f6bcfd97 671 wxLogLastError(wxT("SelectObject"));
0bafad0c
VZ
672
673 ok = FALSE;
1d792928 674 }
2bda0e17 675
4b7f2165
VZ
676 // this is not very efficient, but I can't think of a better way of doing
677 // it
0bafad0c 678 for ( int w = 0; ok && (w < width); w++ )
2bda0e17 679 {
0bafad0c 680 for ( int h = 0; ok && (h < height); h++ )
c793fa87 681 {
6d167489 682 COLORREF col = GetPixel(srcDC, w, h);
4b7f2165
VZ
683 if ( col == CLR_INVALID )
684 {
f6bcfd97 685 wxLogLastError(wxT("GetPixel"));
4b7f2165
VZ
686
687 // doesn't make sense to continue
0bafad0c 688 ok = FALSE;
4b7f2165 689
0bafad0c 690 break;
4b7f2165
VZ
691 }
692
693 if ( col == maskColour )
6d167489
VZ
694 {
695 ::SetPixel(destDC, w, h, RGB(0, 0, 0));
696 }
697 else
698 {
699 ::SetPixel(destDC, w, h, RGB(255, 255, 255));
700 }
c793fa87 701 }
2bda0e17 702 }
4b7f2165 703
0bafad0c 704 ::SelectObject(srcDC, hbmpSrcOld);
6d167489 705 ::DeleteDC(srcDC);
0bafad0c 706 ::SelectObject(destDC, hbmpDstOld);
6d167489 707 ::DeleteDC(destDC);
4b7f2165 708
0bafad0c 709 return ok;
6d167489
VZ
710}
711
712// ----------------------------------------------------------------------------
713// wxBitmapHandler
714// ----------------------------------------------------------------------------
1d792928 715
6d167489
VZ
716bool wxBitmapHandler::Create(wxGDIImage *image,
717 void *data,
718 long flags,
719 int width, int height, int depth)
720{
721 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
1d792928 722
6d167489 723 return bitmap ? Create(bitmap, data, width, height, depth) : FALSE;
2bda0e17
KB
724}
725
6d167489
VZ
726bool wxBitmapHandler::Load(wxGDIImage *image,
727 const wxString& name,
728 long flags,
729 int width, int height)
2bda0e17 730{
6d167489 731 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
2bda0e17 732
6d167489
VZ
733 return bitmap ? LoadFile(bitmap, name, flags, width, height) : FALSE;
734}
2bda0e17 735
6d167489
VZ
736bool wxBitmapHandler::Save(wxGDIImage *image,
737 const wxString& name,
738 int type)
2bda0e17 739{
6d167489
VZ
740 wxBitmap *bitmap = wxDynamicCast(image, wxBitmap);
741
742 return bitmap ? SaveFile(bitmap, name, type) : FALSE;
2bda0e17
KB
743}
744
6d167489
VZ
745bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap),
746 void *WXUNUSED(data),
747 long WXUNUSED(type),
748 int WXUNUSED(width),
749 int WXUNUSED(height),
750 int WXUNUSED(depth))
2bda0e17 751{
6d167489 752 return FALSE;
2bda0e17
KB
753}
754
6d167489
VZ
755bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap),
756 const wxString& WXUNUSED(name),
757 long WXUNUSED(type),
758 int WXUNUSED(desiredWidth),
759 int WXUNUSED(desiredHeight))
2bda0e17 760{
6d167489 761 return FALSE;
2bda0e17
KB
762}
763
6d167489
VZ
764bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap),
765 const wxString& WXUNUSED(name),
766 int WXUNUSED(type),
767 const wxPalette *WXUNUSED(palette))
2bda0e17 768{
6d167489 769 return FALSE;
7b46ecac
JS
770}
771
6d167489
VZ
772// ----------------------------------------------------------------------------
773// DIB functions
774// ----------------------------------------------------------------------------
775
776bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel,
777 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader)
7b46ecac
JS
778{
779 unsigned long i, headerSize;
780 LPBITMAPINFO lpDIBheader = NULL;
781 LPPALETTEENTRY lpPe = NULL;
782
783
784 // Allocate space for a DIB header
785 headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY)));
786 lpDIBheader = (BITMAPINFO *) malloc(headerSize);
787 lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER));
788
789 GetPaletteEntries(hPal, 0, 256, lpPe);
790
7b46ecac
JS
791 memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER));
792
7b46ecac
JS
793 // Fill in the static parts of the DIB header
794 lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
795 lpDIBheader->bmiHeader.biWidth = xSize;
796 lpDIBheader->bmiHeader.biHeight = ySize;
797 lpDIBheader->bmiHeader.biPlanes = 1;
798
799 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
800 lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel);
801 lpDIBheader->bmiHeader.biCompression = BI_RGB;
6d167489 802 lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >> 3;
7b46ecac
JS
803 lpDIBheader->bmiHeader.biClrUsed = 256;
804
805
806 // Initialize the DIB palette
807 for (i = 0; i < 256; i++) {
808 lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags;
809 lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed;
810 lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen;
811 lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue;
812 }
813
814 *lpDIBHeader = lpDIBheader;
815
6d167489 816 return TRUE;
7b46ecac
JS
817}
818
6d167489 819void wxFreeDIB(LPBITMAPINFO lpDIBHeader)
7b46ecac 820{
6d167489 821 free(lpDIBHeader);
7b46ecac
JS
822}
823
4b7f2165
VZ
824// ----------------------------------------------------------------------------
825// other helper functions
826// ----------------------------------------------------------------------------
827
828extern HBITMAP wxInvertMask(HBITMAP hbmpMask, int w, int h)
829{
830 wxCHECK_MSG( hbmpMask, 0, _T("invalid bitmap in wxInvertMask") );
831
832 // get width/height from the bitmap if not given
833 if ( !w || !h )
834 {
835 BITMAP bm;
836 ::GetObject(hbmpMask, sizeof(BITMAP), (LPVOID)&bm);
837 w = bm.bmWidth;
838 h = bm.bmHeight;
839 }
840
841 HDC hdcSrc = ::CreateCompatibleDC(NULL);
842 HDC hdcDst = ::CreateCompatibleDC(NULL);
843 if ( !hdcSrc || !hdcDst )
844 {
f6bcfd97 845 wxLogLastError(wxT("CreateCompatibleDC"));
4b7f2165
VZ
846 }
847
848 HBITMAP hbmpInvMask = ::CreateBitmap(w, h, 1, 1, 0);
849 if ( !hbmpInvMask )
850 {
f6bcfd97 851 wxLogLastError(wxT("CreateBitmap"));
4b7f2165
VZ
852 }
853
854 ::SelectObject(hdcSrc, hbmpMask);
855 ::SelectObject(hdcDst, hbmpInvMask);
856 if ( !::BitBlt(hdcDst, 0, 0, w, h,
857 hdcSrc, 0, 0,
858 NOTSRCCOPY) )
859 {
f6bcfd97 860 wxLogLastError(wxT("BitBlt"));
4b7f2165 861 }
7b46ecac 862
4b7f2165
VZ
863 ::DeleteDC(hdcSrc);
864 ::DeleteDC(hdcDst);
865
866 return hbmpInvMask;
867}