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