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