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