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