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