]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bitmap.cpp
better update rect calculation
[wxWidgets.git] / src / msw / bitmap.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: bitmap.cpp
3// Purpose: wxBitmap
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
1d792928 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "bitmap.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include <stdio.h>
25#include "wx/setup.h"
26#include "wx/list.h"
27#include "wx/utils.h"
28#include "wx/app.h"
29#include "wx/palette.h"
2432b92d 30#include "wx/dcmemory.h"
2bda0e17
KB
31#include "wx/bitmap.h"
32#include "wx/icon.h"
33#endif
34
35#include "wx/msw/private.h"
1d792928
VZ
36#include "wx/log.h"
37
2bda0e17
KB
38#include "assert.h"
39
2bda0e17
KB
40#include "wx/msw/dib.h"
41
42#if !USE_SHARED_LIBRARIES
43IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
44IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
45#endif
46
47wxBitmapRefData::wxBitmapRefData(void)
48{
49 m_ok = FALSE;
50 m_width = 0;
51 m_height = 0;
52 m_depth = 0;
53 m_quality = 0;
54 m_hBitmap = 0 ;
55 m_selectedInto = NULL;
56 m_numColors = 0;
57 m_bitmapMask = NULL;
58}
59
60wxBitmapRefData::~wxBitmapRefData(void)
61{
62 if (m_selectedInto)
63 {
837e5743
OK
64 wxChar buf[200];
65 wxSprintf(buf, _T("Bitmap was deleted without selecting out of wxMemoryDC %X."), (unsigned int) m_selectedInto);
2bda0e17
KB
66 wxFatalError(buf);
67 }
68 if (m_hBitmap)
69 {
70 DeleteObject((HBITMAP) m_hBitmap);
71 }
72 m_hBitmap = 0 ;
73
74 if (m_bitmapMask)
c9f8e0e2 75 delete m_bitmapMask;
2bda0e17 76 m_bitmapMask = NULL;
e7003166 77
2bda0e17
KB
78}
79
80wxList wxBitmap::sm_handlers;
81
82wxBitmap::wxBitmap(void)
83{
2bda0e17
KB
84 if ( wxTheBitmapList )
85 wxTheBitmapList->AddBitmap(this);
86}
87
88wxBitmap::~wxBitmap(void)
89{
90 if (wxTheBitmapList)
91 wxTheBitmapList->DeleteObject(this);
92}
93
57c208c5 94bool wxBitmap::FreeResource(bool WXUNUSED(force))
2bda0e17
KB
95{
96 if ( !M_BITMAPDATA )
1d792928 97 return FALSE;
2bda0e17
KB
98
99 if (M_BITMAPDATA->m_selectedInto)
100 {
837e5743
OK
101 wxChar buf[200];
102 wxSprintf(buf, _T("Bitmap %X was deleted without selecting out of wxMemoryDC %X."), (unsigned int) this, (unsigned int) M_BITMAPDATA->m_selectedInto);
2bda0e17
KB
103 wxFatalError(buf);
104 }
105 if (M_BITMAPDATA->m_hBitmap)
106 {
107 DeleteObject((HBITMAP) M_BITMAPDATA->m_hBitmap);
108 }
109 M_BITMAPDATA->m_hBitmap = 0 ;
110
111/*
112 if (M_BITMAPDATA->m_bitmapPalette)
113 delete M_BITMAPDATA->m_bitmapPalette;
114
115 M_BITMAPDATA->m_bitmapPalette = NULL ;
116*/
117
118 return TRUE;
119}
120
121
debe6624 122wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
2bda0e17
KB
123{
124 m_refData = new wxBitmapRefData;
125
126 M_BITMAPDATA->m_width = the_width ;
127 M_BITMAPDATA->m_height = the_height ;
128 M_BITMAPDATA->m_depth = no_bits ;
129 M_BITMAPDATA->m_numColors = 0;
130
4c444f19 131 M_BITMAPDATA->m_hBitmap = (WXHBITMAP) CreateBitmap(the_width, the_height, 1, no_bits, bits);
2bda0e17
KB
132
133 if (M_BITMAPDATA->m_hBitmap)
134 M_BITMAPDATA->m_ok = TRUE;
135 else
136 M_BITMAPDATA->m_ok = FALSE;
137
138 M_BITMAPDATA->m_selectedInto = NULL;
139
140 if ( wxTheBitmapList )
141 wxTheBitmapList->AddBitmap(this);
142}
143
2fd284a4 144// Create from XPM data
03ab016d 145wxBitmap::wxBitmap(char **data, wxControl *WXUNUSED(anItem))
2fd284a4
JS
146{
147 (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
148}
149
debe6624 150wxBitmap::wxBitmap(int w, int h, int d)
2bda0e17
KB
151{
152 (void)Create(w, h, d);
153
154 if ( wxTheBitmapList )
155 wxTheBitmapList->AddBitmap(this);
156}
157
debe6624 158wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
2bda0e17
KB
159{
160 (void) Create(data, type, width, height, depth);
161
162 if ( wxTheBitmapList )
163 wxTheBitmapList->AddBitmap(this);
164}
165
debe6624 166wxBitmap::wxBitmap(const wxString& filename, long type)
2bda0e17
KB
167{
168 LoadFile(filename, (int)type);
169
170 if ( wxTheBitmapList )
171 wxTheBitmapList->AddBitmap(this);
172}
173
debe6624 174bool wxBitmap::Create(int w, int h, int d)
2bda0e17
KB
175{
176 UnRef();
177
178 m_refData = new wxBitmapRefData;
179
180 M_BITMAPDATA->m_width = w;
181 M_BITMAPDATA->m_height = h;
182 M_BITMAPDATA->m_depth = d;
183
184 if (d > 0)
185 {
4c444f19 186 M_BITMAPDATA->m_hBitmap = (WXHBITMAP) CreateBitmap(w, h, 1, d, NULL);
2bda0e17
KB
187 }
188 else
189 {
57c208c5 190 HDC dc = GetDC((HWND) NULL);
2bda0e17 191 M_BITMAPDATA->m_hBitmap = (WXHBITMAP) CreateCompatibleBitmap(dc, w, h);
57c208c5 192 ReleaseDC((HWND) NULL, dc);
2bda0e17
KB
193 M_BITMAPDATA->m_depth = wxDisplayDepth();
194 }
195 if (M_BITMAPDATA->m_hBitmap)
196 M_BITMAPDATA->m_ok = TRUE;
197 else
198 M_BITMAPDATA->m_ok = FALSE;
199 return M_BITMAPDATA->m_ok;
200}
201
debe6624 202bool wxBitmap::LoadFile(const wxString& filename, long type)
2bda0e17
KB
203{
204 UnRef();
205
206 m_refData = new wxBitmapRefData;
207
208 wxBitmapHandler *handler = FindHandler(type);
209
1d792928 210 if ( handler == NULL ) {
837e5743 211 wxLogWarning(_T("no bitmap handler for type %d defined."), type);
1d792928
VZ
212
213 return FALSE;
214 }
215
216 return handler->LoadFile(this, filename, type, -1, -1);
2bda0e17
KB
217}
218
debe6624 219bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
2bda0e17
KB
220{
221 UnRef();
222
223 m_refData = new wxBitmapRefData;
224
225 wxBitmapHandler *handler = FindHandler(type);
226
1d792928 227 if ( handler == NULL ) {
837e5743 228 wxLogWarning(_T("no bitmap handler for type %d defined."), type);
1d792928
VZ
229
230 return FALSE;
231 }
232
233 return handler->Create(this, data, type, width, height, depth);
2bda0e17
KB
234}
235
debe6624 236bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
2bda0e17
KB
237{
238 wxBitmapHandler *handler = FindHandler(type);
239
1d792928 240 if ( handler == NULL ) {
837e5743 241 wxLogWarning(_T("no bitmap handler for type %d defined."), type);
1d792928
VZ
242
243 return FALSE;
244 }
245
246 return handler->SaveFile(this, filename, type, palette);
2bda0e17
KB
247}
248
249void wxBitmap::SetWidth(int w)
250{
251 if (!M_BITMAPDATA)
b823f5a1 252 m_refData = new wxBitmapRefData;
2bda0e17
KB
253
254 M_BITMAPDATA->m_width = w;
255}
256
257void wxBitmap::SetHeight(int h)
258{
259 if (!M_BITMAPDATA)
1d792928 260 m_refData = new wxBitmapRefData;
2bda0e17
KB
261
262 M_BITMAPDATA->m_height = h;
263}
264
265void wxBitmap::SetDepth(int d)
266{
267 if (!M_BITMAPDATA)
1d792928 268 m_refData = new wxBitmapRefData;
2bda0e17
KB
269
270 M_BITMAPDATA->m_depth = d;
271}
272
273void wxBitmap::SetQuality(int q)
274{
275 if (!M_BITMAPDATA)
1d792928 276 m_refData = new wxBitmapRefData;
2bda0e17
KB
277
278 M_BITMAPDATA->m_quality = q;
279}
280
281void wxBitmap::SetOk(bool isOk)
282{
283 if (!M_BITMAPDATA)
1d792928 284 m_refData = new wxBitmapRefData;
2bda0e17
KB
285
286 M_BITMAPDATA->m_ok = isOk;
287}
288
289void wxBitmap::SetPalette(const wxPalette& palette)
290{
291 if (!M_BITMAPDATA)
1d792928 292 m_refData = new wxBitmapRefData;
2bda0e17
KB
293
294 M_BITMAPDATA->m_bitmapPalette = palette ;
295}
296
297void wxBitmap::SetMask(wxMask *mask)
298{
299 if (!M_BITMAPDATA)
1d792928 300 m_refData = new wxBitmapRefData;
2bda0e17
KB
301
302 M_BITMAPDATA->m_bitmapMask = mask ;
303}
304
305void wxBitmap::SetHBITMAP(WXHBITMAP bmp)
306{
307 if (!M_BITMAPDATA)
1d792928 308 m_refData = new wxBitmapRefData;
2bda0e17
KB
309
310 M_BITMAPDATA->m_hBitmap = bmp;
311}
312
313void wxBitmap::AddHandler(wxBitmapHandler *handler)
314{
1d792928 315 sm_handlers.Append(handler);
2bda0e17
KB
316}
317
318void wxBitmap::InsertHandler(wxBitmapHandler *handler)
319{
1d792928 320 sm_handlers.Insert(handler);
2bda0e17
KB
321}
322
323bool wxBitmap::RemoveHandler(const wxString& name)
324{
1d792928
VZ
325 wxBitmapHandler *handler = FindHandler(name);
326 if ( handler )
327 {
328 sm_handlers.DeleteObject(handler);
329 return TRUE;
330 }
331 else
332 return FALSE;
2bda0e17
KB
333}
334
335wxBitmapHandler *wxBitmap::FindHandler(const wxString& name)
336{
1d792928
VZ
337 wxNode *node = sm_handlers.First();
338 while ( node )
339 {
340 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
ce3ed50d 341 if ( (handler->GetName().Cmp(name) == 0) )
1d792928
VZ
342 return handler;
343 node = node->Next();
344 }
345 return NULL;
2bda0e17
KB
346}
347
348wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, long bitmapType)
349{
1d792928
VZ
350 wxNode *node = sm_handlers.First();
351 while ( node )
352 {
353 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
ce3ed50d
JS
354 if ( (handler->GetExtension().Cmp(extension) == 0) &&
355 (bitmapType == -1 || (handler->GetType() == bitmapType)) )
1d792928
VZ
356 return handler;
357 node = node->Next();
358 }
359 return NULL;
2bda0e17
KB
360}
361
362wxBitmapHandler *wxBitmap::FindHandler(long bitmapType)
363{
1d792928
VZ
364 wxNode *node = sm_handlers.First();
365 while ( node )
366 {
367 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
368 if (handler->GetType() == bitmapType)
369 return handler;
370 node = node->Next();
371 }
372 return NULL;
2bda0e17
KB
373}
374
7b46ecac
JS
375// New Create/FreeDIB functions since ones in dibutils.cpp are confusing
376static long createDIB(long xSize, long ySize, long bitsPerPixel,
377 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader);
378static long freeDIB(LPBITMAPINFO lpDIBHeader);
379
380// Creates a bitmap that matches the device context, from
381// an arbitray bitmap. At present, the original bitmap must have an
382// associated palette. TODO: use a default palette if no palette exists.
383// Contributed by Frederic Villeneuve <frederic.villeneuve@natinst.com>
384wxBitmap wxBitmap::GetBitmapForDC(wxDC& dc) const
385{
386 wxMemoryDC memDC;
387 wxBitmap tmpBitmap(this->GetWidth(), this->GetHeight(), dc.GetDepth());
57c208c5 388 HPALETTE hPal = (HPALETTE) NULL;
7b46ecac 389 LPBITMAPINFO lpDib;
57c208c5 390 void *lpBits = (void*) NULL;
7b46ecac 391
a367b9b3 392/*
27529614 393 wxASSERT( this->GetPalette() && this->GetPalette()->Ok() && (this->GetPalette()->GetHPALETTE() != 0) );
7b46ecac
JS
394
395 tmpBitmap.SetPalette(this->GetPalette());
396 memDC.SelectObject(tmpBitmap);
397 memDC.SetPalette(this->GetPalette());
398
399 hPal = (HPALETTE) this->GetPalette()->GetHPALETTE();
a367b9b3
JS
400*/
401 if( this->GetPalette() && this->GetPalette()->Ok() && (this->GetPalette()->GetHPALETTE() != 0) )
402 {
c0ed460c 403 tmpBitmap.SetPalette(* this->GetPalette());
a367b9b3 404 memDC.SelectObject(tmpBitmap);
c0ed460c 405 memDC.SetPalette(* this->GetPalette());
a367b9b3
JS
406 hPal = (HPALETTE) this->GetPalette()->GetHPALETTE();
407 }
408 else
409 {
410 hPal = (HPALETTE) ::GetStockObject(DEFAULT_PALETTE);
411 wxPalette palette;
412 palette.SetHPALETTE( (WXHPALETTE)hPal );
413 tmpBitmap.SetPalette( palette );
414 memDC.SelectObject(tmpBitmap);
415 memDC.SetPalette( palette );
416 }
7b46ecac
JS
417
418 // set the height negative because in a DIB the order of the lines is reversed
419 createDIB(this->GetWidth(), -this->GetHeight(), this->GetDepth(), hPal, &lpDib);
420
421 lpBits = malloc(lpDib->bmiHeader.biSizeImage);
422
423 ::GetBitmapBits((HBITMAP)GetHBITMAP(), lpDib->bmiHeader.biSizeImage, lpBits);
424
425 ::SetDIBitsToDevice((HDC) memDC.GetHDC(), 0, 0, this->GetWidth(), this->GetHeight(),
426 0, 0, 0, this->GetHeight(), lpBits, lpDib, DIB_RGB_COLORS);
427
428 free(lpBits);
429
430 freeDIB(lpDib);
431 return (tmpBitmap);
432}
433
2bda0e17
KB
434/*
435 * wxMask
436 */
437
438wxMask::wxMask(void)
439{
440 m_maskBitmap = 0;
441}
442
443// Construct a mask from a bitmap and a colour indicating
444// the transparent area
445wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
446{
447 m_maskBitmap = 0;
1d792928 448 Create(bitmap, colour);
2bda0e17
KB
449}
450
451// Construct a mask from a bitmap and a palette index indicating
452// the transparent area
debe6624 453wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
454{
455 m_maskBitmap = 0;
1d792928 456 Create(bitmap, paletteIndex);
2bda0e17
KB
457}
458
459// Construct a mask from a mono bitmap (copies the bitmap).
460wxMask::wxMask(const wxBitmap& bitmap)
461{
462 m_maskBitmap = 0;
1d792928 463 Create(bitmap);
2bda0e17
KB
464}
465
466wxMask::~wxMask(void)
467{
468 if ( m_maskBitmap )
469 ::DeleteObject((HBITMAP) m_maskBitmap);
470}
471
472// Create a mask from a mono bitmap (copies the bitmap).
473bool wxMask::Create(const wxBitmap& bitmap)
474{
475 if ( m_maskBitmap )
1d792928
VZ
476 {
477 ::DeleteObject((HBITMAP) m_maskBitmap);
478 m_maskBitmap = 0;
479 }
480 if (!bitmap.Ok() || bitmap.GetDepth() != 1)
481 {
482 return FALSE;
483 }
484 m_maskBitmap = (WXHBITMAP) CreateBitmap(
485 bitmap.GetWidth(),
486 bitmap.GetHeight(),
487 1, 1, 0
488 );
489 HDC srcDC = CreateCompatibleDC(0);
490 SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
491 HDC destDC = CreateCompatibleDC(0);
492 SelectObject(destDC, (HBITMAP) m_maskBitmap);
493 BitBlt(destDC, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), srcDC, 0, 0, SRCCOPY);
494 SelectObject(srcDC, 0);
495 DeleteDC(srcDC);
496 SelectObject(destDC, 0);
497 DeleteDC(destDC);
498 return TRUE;
2bda0e17
KB
499}
500
501// Create a mask from a bitmap and a palette index indicating
502// the transparent area
debe6624 503bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
504{
505 if ( m_maskBitmap )
1d792928
VZ
506 {
507 ::DeleteObject((HBITMAP) m_maskBitmap);
508 m_maskBitmap = 0;
509 }
510 if (bitmap.Ok() && bitmap.GetPalette()->Ok())
511 {
512 unsigned char red, green, blue;
513 if (bitmap.GetPalette()->GetRGB(paletteIndex, &red, &green, &blue))
514 {
515 wxColour transparentColour(red, green, blue);
516 return Create(bitmap, transparentColour);
517 }
518 }
519 return FALSE;
2bda0e17
KB
520}
521
522// Create a mask from a bitmap and a colour indicating
523// the transparent area
524bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
525{
526 if ( m_maskBitmap )
1d792928
VZ
527 {
528 ::DeleteObject((HBITMAP) m_maskBitmap);
529 m_maskBitmap = 0;
530 }
531 if (!bitmap.Ok())
532 {
533 return FALSE;
534 }
535
536 // scan the bitmap for the transparent colour and set
537 // the corresponding pixels in the mask to BLACK and
538 // the rest to WHITE
539 COLORREF maskColour = RGB(colour.Red(), colour.Green(), colour.Blue());
540 m_maskBitmap = (WXHBITMAP) ::CreateBitmap(
541 bitmap.GetWidth(),
542 bitmap.GetHeight(),
543 1, 1, 0
544 );
545 HDC srcDC = ::CreateCompatibleDC(0);
546 ::SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
547 HDC destDC = ::CreateCompatibleDC(0);
548 ::SelectObject(destDC, (HBITMAP) m_maskBitmap);
549
550 // this is not very efficient, but I can't think
551 // of a better way of doing it
552 for (int w = 0; w < bitmap.GetWidth(); w++)
553 {
554 for (int h = 0; h < bitmap.GetHeight(); h++)
555 {
556 COLORREF col = GetPixel(srcDC, w, h);
557 if (col == maskColour)
558 {
559 ::SetPixel(destDC, w, h, RGB(0, 0, 0));
560 }
561 else
562 {
563 ::SetPixel(destDC, w, h, RGB(255, 255, 255));
564 }
565 }
566 }
567 ::SelectObject(srcDC, 0);
568 ::DeleteDC(srcDC);
569 ::SelectObject(destDC, 0);
570 ::DeleteDC(destDC);
571 return TRUE;
2bda0e17
KB
572}
573
574/*
575 * wxBitmapHandler
576 */
577
578IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
579
57c208c5 580bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), void *WXUNUSED(data), long WXUNUSED(type), int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth))
2bda0e17 581{
1d792928 582 return FALSE;
2bda0e17
KB
583}
584
57c208c5
JS
585bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), long WXUNUSED(type),
586 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
2bda0e17 587{
1d792928 588 return FALSE;
2bda0e17
KB
589}
590
57c208c5 591bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), int WXUNUSED(type), const wxPalette *WXUNUSED(palette))
2bda0e17 592{
1d792928 593 return FALSE;
2bda0e17
KB
594}
595
596/*
597 * Standard handlers
598 */
599
600class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
601{
602 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
603public:
604 inline wxBMPResourceHandler(void)
605 {
1d792928
VZ
606 m_name = "Windows bitmap resource";
607 m_extension = "";
608 m_type = wxBITMAP_TYPE_BMP_RESOURCE;
2bda0e17
KB
609 };
610
debe6624 611 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2bda0e17
KB
612 int desiredWidth, int desiredHeight);
613};
614IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
615
57c208c5
JS
616bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
617 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
2bda0e17
KB
618{
619 // TODO: load colourmap.
620 M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ::LoadBitmap(wxGetInstance(), name);
621 if (M_BITMAPHANDLERDATA->m_hBitmap)
622 {
c793fa87
VZ
623 M_BITMAPHANDLERDATA->m_ok = TRUE;
624 BITMAP bm;
625 GetObject((HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap, sizeof(BITMAP), (LPSTR) &bm);
626 M_BITMAPHANDLERDATA->m_width = bm.bmWidth;
627 M_BITMAPHANDLERDATA->m_height = bm.bmHeight;
628 M_BITMAPHANDLERDATA->m_depth = bm.bmBitsPixel;
629
630 if ( bitmap->IsKindOf(CLASSINFO(wxIcon)) )
631 {
632 }
633
634 return TRUE;
2bda0e17 635 }
1d792928
VZ
636
637 // it's probably not found
837e5743 638 wxLogError(_T("Can't load bitmap '%s' from resources! Check .rc file."), name.c_str());
1d792928
VZ
639
640 return FALSE;
2bda0e17
KB
641}
642
643class WXDLLEXPORT wxBMPFileHandler: public wxBitmapHandler
644{
645 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
646public:
647 inline wxBMPFileHandler(void)
648 {
1d792928
VZ
649 m_name = "Windows bitmap file";
650 m_extension = "bmp";
651 m_type = wxBITMAP_TYPE_BMP;
2bda0e17
KB
652 };
653
debe6624 654 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2bda0e17 655 int desiredWidth, int desiredHeight);
debe6624 656 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
2bda0e17
KB
657};
658IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
659
57c208c5
JS
660bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
661 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
2bda0e17 662{
47d67540 663#if wxUSE_IMAGE_LOADING_IN_MSW
2bda0e17
KB
664 wxPalette *palette = NULL;
665 bool success = FALSE;
666/*
667 if (type & wxBITMAP_DISCARD_COLOURMAP)
668 success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap);
669 else
670*/
671 success = (wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0);
672 if (!success && palette)
673 {
674 delete palette;
675 palette = NULL;
676 }
677 if (palette)
26ac4020
JS
678 {
679 M_BITMAPHANDLERDATA->m_bitmapPalette = *palette;
680 delete palette;
681 }
2bda0e17
KB
682 return success;
683#else
1d792928 684 return FALSE;
2bda0e17
KB
685#endif
686}
687
57c208c5 688bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int WXUNUSED(type), const wxPalette *pal)
2bda0e17 689{
47d67540 690#if wxUSE_IMAGE_LOADING_IN_MSW
2bda0e17
KB
691 wxPalette *actualPalette = (wxPalette *)pal;
692 if (!actualPalette && (!M_BITMAPHANDLERDATA->m_bitmapPalette.IsNull()))
693 actualPalette = & (M_BITMAPHANDLERDATA->m_bitmapPalette);
694 return (wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0);
695#else
1d792928 696 return FALSE;
2bda0e17
KB
697#endif
698}
699
2bda0e17
KB
700void wxBitmap::CleanUpHandlers(void)
701{
1d792928
VZ
702 wxNode *node = sm_handlers.First();
703 while ( node )
704 {
705 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
706 wxNode *next = node->Next();
707 delete handler;
708 delete node;
709 node = next;
710 }
2bda0e17
KB
711}
712
713void wxBitmap::InitStandardHandlers(void)
714{
1d792928
VZ
715 AddHandler(new wxBMPResourceHandler);
716 AddHandler(new wxBMPFileHandler);
2fd284a4
JS
717
718 // Not added by default: include xpmhand.h in your app
719 // and call these in your wxApp::OnInit.
720// AddHandler(new wxXPMFileHandler);
721// AddHandler(new wxXPMDataHandler);
722
1d792928
VZ
723 AddHandler(new wxICOResourceHandler);
724 AddHandler(new wxICOFileHandler);
7b46ecac
JS
725}
726
727static long createDIB(long xSize, long ySize, long bitsPerPixel,
728 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader)
729{
730 unsigned long i, headerSize;
731 LPBITMAPINFO lpDIBheader = NULL;
732 LPPALETTEENTRY lpPe = NULL;
733
734
735 // Allocate space for a DIB header
736 headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY)));
737 lpDIBheader = (BITMAPINFO *) malloc(headerSize);
738 lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER));
739
740 GetPaletteEntries(hPal, 0, 256, lpPe);
741
742
743 memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER));
744
745
746 // Fill in the static parts of the DIB header
747 lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
748 lpDIBheader->bmiHeader.biWidth = xSize;
749 lpDIBheader->bmiHeader.biHeight = ySize;
750 lpDIBheader->bmiHeader.biPlanes = 1;
751
752 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
753 lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel);
754 lpDIBheader->bmiHeader.biCompression = BI_RGB;
755 lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >>
7563;
757 lpDIBheader->bmiHeader.biClrUsed = 256;
758
759
760 // Initialize the DIB palette
761 for (i = 0; i < 256; i++) {
762 lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags;
763 lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed;
764 lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen;
765 lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue;
766 }
767
768 *lpDIBHeader = lpDIBheader;
769
770
771 return (0);
772
773}
774
775
776
777static long freeDIB(LPBITMAPINFO lpDIBHeader)
778{
779
780 if (lpDIBHeader != NULL) {
781 free(lpDIBHeader);
782 }
783
784 return (0);
785}
786
787