]> git.saurik.com Git - wxWidgets.git/blob - src/msw/bitmap.cpp
drawing optimization fix
[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 wxASSERT( this->GetPalette() && this->GetPalette()->Ok() && (this->GetPalette()->GetHPALETTE() != 0) );
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
421 /*
422 * wxMask
423 */
424
425 wxMask::wxMask(void)
426 {
427 m_maskBitmap = 0;
428 }
429
430 // Construct a mask from a bitmap and a colour indicating
431 // the transparent area
432 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
433 {
434 m_maskBitmap = 0;
435 Create(bitmap, colour);
436 }
437
438 // Construct a mask from a bitmap and a palette index indicating
439 // the transparent area
440 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
441 {
442 m_maskBitmap = 0;
443 Create(bitmap, paletteIndex);
444 }
445
446 // Construct a mask from a mono bitmap (copies the bitmap).
447 wxMask::wxMask(const wxBitmap& bitmap)
448 {
449 m_maskBitmap = 0;
450 Create(bitmap);
451 }
452
453 wxMask::~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).
460 bool wxMask::Create(const wxBitmap& bitmap)
461 {
462 if ( m_maskBitmap )
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;
486 }
487
488 // Create a mask from a bitmap and a palette index indicating
489 // the transparent area
490 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
491 {
492 if ( m_maskBitmap )
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;
507 }
508
509 // Create a mask from a bitmap and a colour indicating
510 // the transparent area
511 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
512 {
513 if ( m_maskBitmap )
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;
559 }
560
561 /*
562 * wxBitmapHandler
563 */
564
565 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
566
567 bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth)
568 {
569 return FALSE;
570 }
571
572 bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long type,
573 int desiredWidth, int desiredHeight)
574 {
575 return FALSE;
576 }
577
578 bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
579 {
580 return FALSE;
581 }
582
583 /*
584 * Standard handlers
585 */
586
587 class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
588 {
589 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
590 public:
591 inline wxBMPResourceHandler(void)
592 {
593 m_name = "Windows bitmap resource";
594 m_extension = "";
595 m_type = wxBITMAP_TYPE_BMP_RESOURCE;
596 };
597
598 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
599 int desiredWidth, int desiredHeight);
600 };
601 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
602
603 bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
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;
615 M_BITMAPHANDLERDATA->m_depth = bm.bmBitsPixel;
616 return TRUE;
617 }
618
619 // it's probably not found
620 wxLogError("Can't load bitmap '%s' from resources! Check .rc file.", name.c_str());
621
622 return FALSE;
623 }
624
625 class WXDLLEXPORT wxBMPFileHandler: public wxBitmapHandler
626 {
627 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
628 public:
629 inline wxBMPFileHandler(void)
630 {
631 m_name = "Windows bitmap file";
632 m_extension = "bmp";
633 m_type = wxBITMAP_TYPE_BMP;
634 };
635
636 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
637 int desiredWidth, int desiredHeight);
638 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
639 };
640 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
641
642 bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
643 int desiredWidth, int desiredHeight)
644 {
645 #if wxUSE_IMAGE_LOADING_IN_MSW
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
663 return FALSE;
664 #endif
665 }
666
667 bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *pal)
668 {
669 #if wxUSE_IMAGE_LOADING_IN_MSW
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
675 return FALSE;
676 #endif
677 }
678
679 class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
680 {
681 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
682 public:
683 inline wxXPMFileHandler(void)
684 {
685 m_name = "XPM bitmap file";
686 m_extension = "xpm";
687 m_type = wxBITMAP_TYPE_XPM;
688 };
689
690 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
691 int desiredWidth = -1, int desiredHeight = -1);
692 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
693 };
694 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
695
696 bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
697 int desiredWidth, int desiredHeight)
698 {
699 #if wxUSE_XPM_IN_MSW
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 {
713 M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ximage->bitmap;
714
715 BITMAP bm;
716 GetObject((HBITMAP)M_BITMAPHANDLERDATA->m_hBitmap, sizeof(bm), (LPSTR) & bm);
717
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;
722 XpmFreeAttributes(&xpmAttr);
723 XImageFree(ximage);
724
725 M_BITMAPHANDLERDATA->m_ok = TRUE;
726 return TRUE;
727 }
728 else
729 {
730 M_BITMAPHANDLERDATA->m_ok = FALSE;
731 return FALSE;
732 }
733 }
734 #endif
735
736 return FALSE;
737 }
738
739 bool wxXPMFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
740 {
741 #if wxUSE_XPM_IN_MSW
742 HDC dc = NULL;
743
744 XImage ximage;
745
746 dc = CreateCompatibleDC(NULL);
747 if (dc)
748 {
749 if (SelectObject(dc, (HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap))
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;
767 } else return FALSE;
768 } else return FALSE;
769 #else
770 return FALSE;
771 #endif
772 }
773
774 class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
775 {
776 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
777 public:
778 inline wxXPMDataHandler(void)
779 {
780 m_name = "XPM bitmap data";
781 m_extension = "xpm";
782 m_type = wxBITMAP_TYPE_XPM_DATA;
783 };
784
785 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
786 };
787 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
788
789 bool wxXPMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth)
790 {
791 #if wxUSE_XPM_IN_MSW
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
800 dc = CreateCompatibleDC(NULL); /* memory DC */
801
802 if (dc)
803 {
804 xpmAttr.valuemask = XpmReturnInfos; /* get infos back */
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
822 XImageFree(ximage); // releases the malloc, but does not detroy
823 // the bitmap
824 M_BITMAPHANDLERDATA->m_ok = TRUE;
825 DeleteDC(dc);
826
827 return TRUE;
828 }
829 else
830 {
831 M_BITMAPHANDLERDATA->m_ok = FALSE;
832 // XpmDebugError(ErrorStatus, NULL);
833 DeleteDC(dc);
834 return FALSE;
835 }
836 }
837 #endif
838
839 return FALSE;
840 }
841
842 void wxBitmap::CleanUpHandlers(void)
843 {
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 }
853 }
854
855 void wxBitmap::InitStandardHandlers(void)
856 {
857 AddHandler(new wxBMPResourceHandler);
858 AddHandler(new wxBMPFileHandler);
859 AddHandler(new wxXPMFileHandler);
860 AddHandler(new wxXPMDataHandler);
861 AddHandler(new wxICOResourceHandler);
862 AddHandler(new wxICOFileHandler);
863 }
864
865 static 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 >>
894 3;
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
915 static long freeDIB(LPBITMAPINFO lpDIBHeader)
916 {
917
918 if (lpDIBHeader != NULL) {
919 free(lpDIBHeader);
920 }
921
922 return (0);
923 }
924
925