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