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