]> git.saurik.com Git - wxWidgets.git/blob - src/msw/bitmap.cpp
Made wxSocket compile using makefiles; #ifdefed out <<, >> operators in stream.cpp
[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 USE_XPM_IN_MSW
40 #define FOR_MSW 1
41 #include "../../contrib/wxxpm/libxpm.34b/lib/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 m_refData = NULL; // new wxBitmapRefData;
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 USE_XPM_IN_MSW
174 // Create from data
175 wxBitmap::wxBitmap(const 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 wxASSERT( this->GetPalette() && this->GetPalette()->Ok() && (this->GetPalette()->GetHPALETTE() != NULL) );
400
401 tmpBitmap.SetPalette(this->GetPalette());
402 memDC.SelectObject(tmpBitmap);
403 memDC.SetPalette(this->GetPalette());
404
405 hPal = (HPALETTE) this->GetPalette()->GetHPALETTE();
406
407 // set the height negative because in a DIB the order of the lines is reversed
408 createDIB(this->GetWidth(), -this->GetHeight(), this->GetDepth(), hPal, &lpDib);
409
410 lpBits = malloc(lpDib->bmiHeader.biSizeImage);
411
412 ::GetBitmapBits((HBITMAP)GetHBITMAP(), lpDib->bmiHeader.biSizeImage, lpBits);
413
414 ::SetDIBitsToDevice((HDC) memDC.GetHDC(), 0, 0, this->GetWidth(), this->GetHeight(),
415 0, 0, 0, this->GetHeight(), lpBits, lpDib, DIB_RGB_COLORS);
416
417 free(lpBits);
418
419 freeDIB(lpDib);
420 return (tmpBitmap);
421 }
422
423 /*
424 * wxMask
425 */
426
427 wxMask::wxMask(void)
428 {
429 m_maskBitmap = 0;
430 }
431
432 // Construct a mask from a bitmap and a colour indicating
433 // the transparent area
434 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
435 {
436 m_maskBitmap = 0;
437 Create(bitmap, colour);
438 }
439
440 // Construct a mask from a bitmap and a palette index indicating
441 // the transparent area
442 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
443 {
444 m_maskBitmap = 0;
445 Create(bitmap, paletteIndex);
446 }
447
448 // Construct a mask from a mono bitmap (copies the bitmap).
449 wxMask::wxMask(const wxBitmap& bitmap)
450 {
451 m_maskBitmap = 0;
452 Create(bitmap);
453 }
454
455 wxMask::~wxMask(void)
456 {
457 if ( m_maskBitmap )
458 ::DeleteObject((HBITMAP) m_maskBitmap);
459 }
460
461 // Create a mask from a mono bitmap (copies the bitmap).
462 bool wxMask::Create(const wxBitmap& bitmap)
463 {
464 if ( m_maskBitmap )
465 {
466 ::DeleteObject((HBITMAP) m_maskBitmap);
467 m_maskBitmap = 0;
468 }
469 if (!bitmap.Ok() || bitmap.GetDepth() != 1)
470 {
471 return FALSE;
472 }
473 m_maskBitmap = (WXHBITMAP) CreateBitmap(
474 bitmap.GetWidth(),
475 bitmap.GetHeight(),
476 1, 1, 0
477 );
478 HDC srcDC = CreateCompatibleDC(0);
479 SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
480 HDC destDC = CreateCompatibleDC(0);
481 SelectObject(destDC, (HBITMAP) m_maskBitmap);
482 BitBlt(destDC, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), srcDC, 0, 0, SRCCOPY);
483 SelectObject(srcDC, 0);
484 DeleteDC(srcDC);
485 SelectObject(destDC, 0);
486 DeleteDC(destDC);
487 return TRUE;
488 }
489
490 // Create a mask from a bitmap and a palette index indicating
491 // the transparent area
492 bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
493 {
494 if ( m_maskBitmap )
495 {
496 ::DeleteObject((HBITMAP) m_maskBitmap);
497 m_maskBitmap = 0;
498 }
499 if (bitmap.Ok() && bitmap.GetPalette()->Ok())
500 {
501 unsigned char red, green, blue;
502 if (bitmap.GetPalette()->GetRGB(paletteIndex, &red, &green, &blue))
503 {
504 wxColour transparentColour(red, green, blue);
505 return Create(bitmap, transparentColour);
506 }
507 }
508 return FALSE;
509 }
510
511 // Create a mask from a bitmap and a colour indicating
512 // the transparent area
513 bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
514 {
515 if ( m_maskBitmap )
516 {
517 ::DeleteObject((HBITMAP) m_maskBitmap);
518 m_maskBitmap = 0;
519 }
520 if (!bitmap.Ok())
521 {
522 return FALSE;
523 }
524
525 // scan the bitmap for the transparent colour and set
526 // the corresponding pixels in the mask to BLACK and
527 // the rest to WHITE
528 COLORREF maskColour = RGB(colour.Red(), colour.Green(), colour.Blue());
529 m_maskBitmap = (WXHBITMAP) ::CreateBitmap(
530 bitmap.GetWidth(),
531 bitmap.GetHeight(),
532 1, 1, 0
533 );
534 HDC srcDC = ::CreateCompatibleDC(0);
535 ::SelectObject(srcDC, (HBITMAP) bitmap.GetHBITMAP());
536 HDC destDC = ::CreateCompatibleDC(0);
537 ::SelectObject(destDC, (HBITMAP) m_maskBitmap);
538
539 // this is not very efficient, but I can't think
540 // of a better way of doing it
541 for (int w = 0; w < bitmap.GetWidth(); w++)
542 {
543 for (int h = 0; h < bitmap.GetHeight(); h++)
544 {
545 COLORREF col = GetPixel(srcDC, w, h);
546 if (col == maskColour)
547 {
548 ::SetPixel(destDC, w, h, RGB(0, 0, 0));
549 }
550 else
551 {
552 ::SetPixel(destDC, w, h, RGB(255, 255, 255));
553 }
554 }
555 }
556 ::SelectObject(srcDC, 0);
557 ::DeleteDC(srcDC);
558 ::SelectObject(destDC, 0);
559 ::DeleteDC(destDC);
560 return TRUE;
561 }
562
563 /*
564 * wxBitmapHandler
565 */
566
567 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
568
569 bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth)
570 {
571 return FALSE;
572 }
573
574 bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long type,
575 int desiredWidth, int desiredHeight)
576 {
577 return FALSE;
578 }
579
580 bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
581 {
582 return FALSE;
583 }
584
585 /*
586 * Standard handlers
587 */
588
589 class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
590 {
591 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
592 public:
593 inline wxBMPResourceHandler(void)
594 {
595 m_name = "Windows bitmap resource";
596 m_extension = "";
597 m_type = wxBITMAP_TYPE_BMP_RESOURCE;
598 };
599
600 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
601 int desiredWidth, int desiredHeight);
602 };
603 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
604
605 bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
606 int desiredWidth, int desiredHeight)
607 {
608 // TODO: load colourmap.
609 M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ::LoadBitmap(wxGetInstance(), name);
610 if (M_BITMAPHANDLERDATA->m_hBitmap)
611 {
612 M_BITMAPHANDLERDATA->m_ok = TRUE;
613 BITMAP bm;
614 GetObject((HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap, sizeof(BITMAP), (LPSTR) &bm);
615 M_BITMAPHANDLERDATA->m_width = bm.bmWidth;
616 M_BITMAPHANDLERDATA->m_height = bm.bmHeight;
617 M_BITMAPHANDLERDATA->m_depth = bm.bmBitsPixel;
618 return TRUE;
619 }
620
621 // it's probably not found
622 wxLogError("Can't load bitmap '%s' from resources! Check .rc file.", name.c_str());
623
624 return FALSE;
625 }
626
627 class WXDLLEXPORT wxBMPFileHandler: public wxBitmapHandler
628 {
629 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
630 public:
631 inline wxBMPFileHandler(void)
632 {
633 m_name = "Windows bitmap file";
634 m_extension = "bmp";
635 m_type = wxBITMAP_TYPE_BMP;
636 };
637
638 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
639 int desiredWidth, int desiredHeight);
640 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
641 };
642 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
643
644 bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
645 int desiredWidth, int desiredHeight)
646 {
647 #if USE_IMAGE_LOADING_IN_MSW
648 wxPalette *palette = NULL;
649 bool success = FALSE;
650 /*
651 if (type & wxBITMAP_DISCARD_COLOURMAP)
652 success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap);
653 else
654 */
655 success = (wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0);
656 if (!success && palette)
657 {
658 delete palette;
659 palette = NULL;
660 }
661 if (palette)
662 M_BITMAPHANDLERDATA->m_bitmapPalette = *palette;
663 return success;
664 #else
665 return FALSE;
666 #endif
667 }
668
669 bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *pal)
670 {
671 #if USE_IMAGE_LOADING_IN_MSW
672 wxPalette *actualPalette = (wxPalette *)pal;
673 if (!actualPalette && (!M_BITMAPHANDLERDATA->m_bitmapPalette.IsNull()))
674 actualPalette = & (M_BITMAPHANDLERDATA->m_bitmapPalette);
675 return (wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0);
676 #else
677 return FALSE;
678 #endif
679 }
680
681 class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
682 {
683 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
684 public:
685 inline wxXPMFileHandler(void)
686 {
687 m_name = "XPM bitmap file";
688 m_extension = "xpm";
689 m_type = wxBITMAP_TYPE_XPM;
690 };
691
692 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
693 int desiredWidth = -1, int desiredHeight = -1);
694 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
695 };
696 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
697
698 bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
699 int desiredWidth, int desiredHeight)
700 {
701 #if USE_XPM_IN_MSW
702 XImage *ximage;
703 XpmAttributes xpmAttr;
704 HDC dc;
705
706 M_BITMAPHANDLERDATA->m_ok = FALSE;
707 dc = CreateCompatibleDC(NULL);
708 if (dc)
709 {
710 xpmAttr.valuemask = XpmReturnPixels;
711 int errorStatus = XpmReadFileToImage(&dc, WXSTRINGCAST name, &ximage, (XImage **) NULL, &xpmAttr);
712 DeleteDC(dc);
713 if (errorStatus == XpmSuccess)
714 {
715 M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ximage->bitmap;
716
717 BITMAP bm;
718 GetObject((HBITMAP)M_BITMAPHANDLERDATA->m_hBitmap, sizeof(bm), (LPSTR) & bm);
719
720 M_BITMAPHANDLERDATA->m_width = (bm.bmWidth);
721 M_BITMAPHANDLERDATA->m_height = (bm.bmHeight);
722 M_BITMAPHANDLERDATA->m_depth = (bm.bmPlanes * bm.bmBitsPixel);
723 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
724 XpmFreeAttributes(&xpmAttr);
725 XImageFree(ximage);
726
727 M_BITMAPHANDLERDATA->m_ok = TRUE;
728 return TRUE;
729 }
730 else
731 {
732 M_BITMAPHANDLERDATA->m_ok = FALSE;
733 return FALSE;
734 }
735 }
736 #endif
737
738 return FALSE;
739 }
740
741 bool wxXPMFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
742 {
743 #if USE_XPM_IN_MSW
744 HDC dc = NULL;
745
746 Visual *visual = NULL;
747 XImage ximage;
748
749 dc = CreateCompatibleDC(NULL);
750 if (dc)
751 {
752 if (SelectObject(dc, (HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap))
753 { /* for following SetPixel */
754 /* fill the XImage struct 'by hand' */
755 ximage.width = M_BITMAPHANDLERDATA->m_width;
756 ximage.height = M_BITMAPHANDLERDATA->m_height;
757 ximage.depth = M_BITMAPHANDLERDATA->m_depth;
758 ximage.bitmap = (void *)M_BITMAPHANDLERDATA->m_hBitmap;
759 int errorStatus = XpmWriteFileFromImage(&dc, WXSTRINGCAST name,
760 &ximage, (XImage *) NULL, (XpmAttributes *) NULL);
761
762 if (dc)
763 DeleteDC(dc);
764
765 if (errorStatus == XpmSuccess)
766 return TRUE; /* no error */
767 else
768 return FALSE;
769 } else return FALSE;
770 } else return FALSE;
771 #else
772 return FALSE;
773 #endif
774 }
775
776 class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
777 {
778 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
779 public:
780 inline wxXPMDataHandler(void)
781 {
782 m_name = "XPM bitmap data";
783 m_extension = "xpm";
784 m_type = wxBITMAP_TYPE_XPM_DATA;
785 };
786
787 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
788 };
789 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
790
791 bool wxXPMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth)
792 {
793 #if USE_XPM_IN_MSW
794 XImage *ximage;
795 int ErrorStatus;
796 XpmAttributes xpmAttr;
797 HDC dc;
798
799 M_BITMAPHANDLERDATA->m_ok = FALSE;
800 M_BITMAPHANDLERDATA->m_numColors = 0;
801
802 dc = CreateCompatibleDC(NULL); /* memory DC */
803
804 if (dc)
805 {
806 xpmAttr.valuemask = XpmReturnInfos; /* get infos back */
807 ErrorStatus = XpmCreateImageFromData(&dc, (char **)data,
808 &ximage, (XImage **) NULL, &xpmAttr);
809
810 if (ErrorStatus == XpmSuccess)
811 {
812 /* ximage is malloced and contains bitmap and attributes */
813 M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ximage->bitmap;
814
815 BITMAP bm;
816 GetObject((HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap, sizeof(bm), (LPSTR) & bm);
817
818 M_BITMAPHANDLERDATA->m_width = (bm.bmWidth);
819 M_BITMAPHANDLERDATA->m_height = (bm.bmHeight);
820 M_BITMAPHANDLERDATA->m_depth = (bm.bmPlanes * bm.bmBitsPixel);
821 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
822 XpmFreeAttributes(&xpmAttr);
823
824 XImageFree(ximage); // releases the malloc, but does not detroy
825 // the bitmap
826 M_BITMAPHANDLERDATA->m_ok = TRUE;
827 DeleteDC(dc);
828
829 return TRUE;
830 }
831 else
832 {
833 M_BITMAPHANDLERDATA->m_ok = FALSE;
834 // XpmDebugError(ErrorStatus, NULL);
835 DeleteDC(dc);
836 return FALSE;
837 }
838 }
839 #endif
840
841 return FALSE;
842 }
843
844 void wxBitmap::CleanUpHandlers(void)
845 {
846 wxNode *node = sm_handlers.First();
847 while ( node )
848 {
849 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
850 wxNode *next = node->Next();
851 delete handler;
852 delete node;
853 node = next;
854 }
855 }
856
857 void wxBitmap::InitStandardHandlers(void)
858 {
859 AddHandler(new wxBMPResourceHandler);
860 AddHandler(new wxBMPFileHandler);
861 AddHandler(new wxXPMFileHandler);
862 AddHandler(new wxXPMDataHandler);
863 AddHandler(new wxICOResourceHandler);
864 AddHandler(new wxICOFileHandler);
865 }
866
867 static long createDIB(long xSize, long ySize, long bitsPerPixel,
868 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader)
869 {
870 unsigned long i, headerSize;
871 LPBITMAPINFO lpDIBheader = NULL;
872 LPPALETTEENTRY lpPe = NULL;
873
874
875 // Allocate space for a DIB header
876 headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY)));
877 lpDIBheader = (BITMAPINFO *) malloc(headerSize);
878 lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER));
879
880 GetPaletteEntries(hPal, 0, 256, lpPe);
881
882
883 memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER));
884
885
886 // Fill in the static parts of the DIB header
887 lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
888 lpDIBheader->bmiHeader.biWidth = xSize;
889 lpDIBheader->bmiHeader.biHeight = ySize;
890 lpDIBheader->bmiHeader.biPlanes = 1;
891
892 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
893 lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel);
894 lpDIBheader->bmiHeader.biCompression = BI_RGB;
895 lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >>
896 3;
897 lpDIBheader->bmiHeader.biClrUsed = 256;
898
899
900 // Initialize the DIB palette
901 for (i = 0; i < 256; i++) {
902 lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags;
903 lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed;
904 lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen;
905 lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue;
906 }
907
908 *lpDIBHeader = lpDIBheader;
909
910
911 return (0);
912
913 }
914
915
916
917 static long freeDIB(LPBITMAPINFO lpDIBHeader)
918 {
919
920 if (lpDIBHeader != NULL) {
921 free(lpDIBHeader);
922 }
923
924 return (0);
925 }
926
927