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