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