]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bitmap.cpp
Removed some bugs
[wxWidgets.git] / src / msw / bitmap.cpp
CommitLineData
2bda0e17
KB
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
1d792928 9// Licence: wxWindows license
2bda0e17
KB
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"
1d792928
VZ
35#include "wx/log.h"
36
2bda0e17
KB
37#include "assert.h"
38
39#if USE_XPM_IN_MSW
40#define FOR_MSW 1
1d792928 41#include "../../contrib/wxxpm/libxpm.34b/lib/xpm34.h"
2bda0e17
KB
42#endif
43
44#include "wx/msw/dib.h"
45
46#if !USE_SHARED_LIBRARIES
47IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
48IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
49#endif
50
51wxBitmapRefData::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
64wxBitmapRefData::~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
83wxList wxBitmap::sm_handlers;
84
85wxBitmap::wxBitmap(void)
86{
87 m_refData = NULL; // new wxBitmapRefData;
88
89 if ( wxTheBitmapList )
90 wxTheBitmapList->AddBitmap(this);
91}
92
93wxBitmap::~wxBitmap(void)
94{
95 if (wxTheBitmapList)
96 wxTheBitmapList->DeleteObject(this);
97}
98
99bool wxBitmap::FreeResource(bool force)
100{
101 if ( !M_BITMAPDATA )
1d792928 102 return FALSE;
2bda0e17
KB
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
debe6624 127wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
2bda0e17
KB
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
4c444f19 136 M_BITMAPDATA->m_hBitmap = (WXHBITMAP) CreateBitmap(the_width, the_height, 1, no_bits, bits);
2bda0e17
KB
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
debe6624 149wxBitmap::wxBitmap(int w, int h, int d)
2bda0e17
KB
150{
151 (void)Create(w, h, d);
152
153 if ( wxTheBitmapList )
154 wxTheBitmapList->AddBitmap(this);
155}
156
debe6624 157wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
2bda0e17
KB
158{
159 (void) Create(data, type, width, height, depth);
160
161 if ( wxTheBitmapList )
162 wxTheBitmapList->AddBitmap(this);
163}
164
debe6624 165wxBitmap::wxBitmap(const wxString& filename, long type)
2bda0e17
KB
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
175wxBitmap::wxBitmap(const char **data, wxItem *WXUNUSED(anItem))
176{
1d792928 177 (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
2bda0e17
KB
178}
179#endif
180
debe6624 181bool wxBitmap::Create(int w, int h, int d)
2bda0e17
KB
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 {
4c444f19 193 M_BITMAPDATA->m_hBitmap = (WXHBITMAP) CreateBitmap(w, h, 1, d, NULL);
2bda0e17
KB
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
debe6624 209bool wxBitmap::LoadFile(const wxString& filename, long type)
2bda0e17
KB
210{
211 UnRef();
212
213 m_refData = new wxBitmapRefData;
214
215 wxBitmapHandler *handler = FindHandler(type);
216
1d792928
VZ
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);
2bda0e17
KB
224}
225
debe6624 226bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
2bda0e17
KB
227{
228 UnRef();
229
230 m_refData = new wxBitmapRefData;
231
232 wxBitmapHandler *handler = FindHandler(type);
233
1d792928
VZ
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);
2bda0e17
KB
241}
242
debe6624 243bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
2bda0e17
KB
244{
245 wxBitmapHandler *handler = FindHandler(type);
246
1d792928
VZ
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);
2bda0e17
KB
254}
255
256void wxBitmap::SetWidth(int w)
257{
258 if (!M_BITMAPDATA)
b823f5a1 259 m_refData = new wxBitmapRefData;
2bda0e17
KB
260
261 M_BITMAPDATA->m_width = w;
262}
263
264void wxBitmap::SetHeight(int h)
265{
266 if (!M_BITMAPDATA)
1d792928 267 m_refData = new wxBitmapRefData;
2bda0e17
KB
268
269 M_BITMAPDATA->m_height = h;
270}
271
272void wxBitmap::SetDepth(int d)
273{
274 if (!M_BITMAPDATA)
1d792928 275 m_refData = new wxBitmapRefData;
2bda0e17
KB
276
277 M_BITMAPDATA->m_depth = d;
278}
279
280void wxBitmap::SetQuality(int q)
281{
282 if (!M_BITMAPDATA)
1d792928 283 m_refData = new wxBitmapRefData;
2bda0e17
KB
284
285 M_BITMAPDATA->m_quality = q;
286}
287
288void wxBitmap::SetOk(bool isOk)
289{
290 if (!M_BITMAPDATA)
1d792928 291 m_refData = new wxBitmapRefData;
2bda0e17
KB
292
293 M_BITMAPDATA->m_ok = isOk;
294}
295
296void wxBitmap::SetPalette(const wxPalette& palette)
297{
298 if (!M_BITMAPDATA)
1d792928 299 m_refData = new wxBitmapRefData;
2bda0e17
KB
300
301 M_BITMAPDATA->m_bitmapPalette = palette ;
302}
303
304void wxBitmap::SetMask(wxMask *mask)
305{
306 if (!M_BITMAPDATA)
1d792928 307 m_refData = new wxBitmapRefData;
2bda0e17
KB
308
309 M_BITMAPDATA->m_bitmapMask = mask ;
310}
311
312void wxBitmap::SetHBITMAP(WXHBITMAP bmp)
313{
314 if (!M_BITMAPDATA)
1d792928 315 m_refData = new wxBitmapRefData;
2bda0e17
KB
316
317 M_BITMAPDATA->m_hBitmap = bmp;
318}
319
320void wxBitmap::AddHandler(wxBitmapHandler *handler)
321{
1d792928 322 sm_handlers.Append(handler);
2bda0e17
KB
323}
324
325void wxBitmap::InsertHandler(wxBitmapHandler *handler)
326{
1d792928 327 sm_handlers.Insert(handler);
2bda0e17
KB
328}
329
330bool wxBitmap::RemoveHandler(const wxString& name)
331{
1d792928
VZ
332 wxBitmapHandler *handler = FindHandler(name);
333 if ( handler )
334 {
335 sm_handlers.DeleteObject(handler);
336 return TRUE;
337 }
338 else
339 return FALSE;
2bda0e17
KB
340}
341
342wxBitmapHandler *wxBitmap::FindHandler(const wxString& name)
343{
1d792928
VZ
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;
2bda0e17
KB
353}
354
355wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, long bitmapType)
356{
1d792928
VZ
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;
2bda0e17
KB
367}
368
369wxBitmapHandler *wxBitmap::FindHandler(long bitmapType)
370{
1d792928
VZ
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;
2bda0e17
KB
380}
381
7b46ecac
JS
382// New Create/FreeDIB functions since ones in dibutils.cpp are confusing
383static long createDIB(long xSize, long ySize, long bitsPerPixel,
384 HPALETTE hPal, LPBITMAPINFO* lpDIBHeader);
385static 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>
391wxBitmap 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
2bda0e17
KB
423/*
424 * wxMask
425 */
426
427wxMask::wxMask(void)
428{
429 m_maskBitmap = 0;
430}
431
432// Construct a mask from a bitmap and a colour indicating
433// the transparent area
434wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
435{
436 m_maskBitmap = 0;
1d792928 437 Create(bitmap, colour);
2bda0e17
KB
438}
439
440// Construct a mask from a bitmap and a palette index indicating
441// the transparent area
debe6624 442wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
443{
444 m_maskBitmap = 0;
1d792928 445 Create(bitmap, paletteIndex);
2bda0e17
KB
446}
447
448// Construct a mask from a mono bitmap (copies the bitmap).
449wxMask::wxMask(const wxBitmap& bitmap)
450{
451 m_maskBitmap = 0;
1d792928 452 Create(bitmap);
2bda0e17
KB
453}
454
455wxMask::~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).
462bool wxMask::Create(const wxBitmap& bitmap)
463{
464 if ( m_maskBitmap )
1d792928
VZ
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;
2bda0e17
KB
488}
489
490// Create a mask from a bitmap and a palette index indicating
491// the transparent area
debe6624 492bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
2bda0e17
KB
493{
494 if ( m_maskBitmap )
1d792928
VZ
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;
2bda0e17
KB
509}
510
511// Create a mask from a bitmap and a colour indicating
512// the transparent area
513bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
514{
515 if ( m_maskBitmap )
1d792928
VZ
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;
2bda0e17
KB
561}
562
563/*
564 * wxBitmapHandler
565 */
566
567IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
568
debe6624 569bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth)
2bda0e17 570{
1d792928 571 return FALSE;
2bda0e17
KB
572}
573
debe6624 574bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long type,
2bda0e17
KB
575 int desiredWidth, int desiredHeight)
576{
1d792928 577 return FALSE;
2bda0e17
KB
578}
579
debe6624 580bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
2bda0e17 581{
1d792928 582 return FALSE;
2bda0e17
KB
583}
584
585/*
586 * Standard handlers
587 */
588
589class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
590{
591 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
592public:
593 inline wxBMPResourceHandler(void)
594 {
1d792928
VZ
595 m_name = "Windows bitmap resource";
596 m_extension = "";
597 m_type = wxBITMAP_TYPE_BMP_RESOURCE;
2bda0e17
KB
598 };
599
debe6624 600 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2bda0e17
KB
601 int desiredWidth, int desiredHeight);
602};
603IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
604
debe6624 605bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2bda0e17
KB
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;
7b46ecac 617 M_BITMAPHANDLERDATA->m_depth = bm.bmBitsPixel;
2bda0e17
KB
618 return TRUE;
619 }
1d792928
VZ
620
621 // it's probably not found
dabeb021 622 wxLogError("Can't load bitmap '%s' from resources! Check .rc file.", name.c_str());
1d792928
VZ
623
624 return FALSE;
2bda0e17
KB
625}
626
627class WXDLLEXPORT wxBMPFileHandler: public wxBitmapHandler
628{
629 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
630public:
631 inline wxBMPFileHandler(void)
632 {
1d792928
VZ
633 m_name = "Windows bitmap file";
634 m_extension = "bmp";
635 m_type = wxBITMAP_TYPE_BMP;
2bda0e17
KB
636 };
637
debe6624 638 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2bda0e17 639 int desiredWidth, int desiredHeight);
debe6624 640 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
2bda0e17
KB
641};
642IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
643
debe6624 644bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2bda0e17
KB
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
1d792928 665 return FALSE;
2bda0e17
KB
666#endif
667}
668
debe6624 669bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *pal)
2bda0e17
KB
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
1d792928 677 return FALSE;
2bda0e17
KB
678#endif
679}
680
681class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
682{
683 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
684public:
685 inline wxXPMFileHandler(void)
686 {
1d792928
VZ
687 m_name = "XPM bitmap file";
688 m_extension = "xpm";
689 m_type = wxBITMAP_TYPE_XPM;
2bda0e17
KB
690 };
691
debe6624 692 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2bda0e17 693 int desiredWidth = -1, int desiredHeight = -1);
debe6624 694 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
2bda0e17
KB
695};
696IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
697
debe6624 698bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2bda0e17
KB
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 {
1d792928 715 M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ximage->bitmap;
2bda0e17 716
1d792928
VZ
717 BITMAP bm;
718 GetObject((HBITMAP)M_BITMAPHANDLERDATA->m_hBitmap, sizeof(bm), (LPSTR) & bm);
2bda0e17 719
1d792928
VZ
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;
2bda0e17 724 XpmFreeAttributes(&xpmAttr);
1d792928
VZ
725 XImageFree(ximage);
726
727 M_BITMAPHANDLERDATA->m_ok = TRUE;
728 return TRUE;
2bda0e17
KB
729 }
730 else
731 {
732 M_BITMAPHANDLERDATA->m_ok = FALSE;
733 return FALSE;
734 }
735 }
2bda0e17 736#endif
1d792928
VZ
737
738 return FALSE;
2bda0e17
KB
739}
740
debe6624 741bool wxXPMFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette)
2bda0e17
KB
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' */
1d792928
VZ
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);
2bda0e17
KB
761
762 if (dc)
1d792928 763 DeleteDC(dc);
2bda0e17 764
1d792928
VZ
765 if (errorStatus == XpmSuccess)
766 return TRUE; /* no error */
767 else
768 return FALSE;
2bda0e17
KB
769 } else return FALSE;
770 } else return FALSE;
771#else
1d792928 772 return FALSE;
2bda0e17
KB
773#endif
774}
775
776class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
777{
778 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
779public:
780 inline wxXPMDataHandler(void)
781 {
1d792928
VZ
782 m_name = "XPM bitmap data";
783 m_extension = "xpm";
784 m_type = wxBITMAP_TYPE_XPM_DATA;
2bda0e17
KB
785 };
786
debe6624 787 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
2bda0e17
KB
788};
789IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
790
debe6624 791bool wxXPMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth)
2bda0e17
KB
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
1d792928 802 dc = CreateCompatibleDC(NULL); /* memory DC */
2bda0e17
KB
803
804 if (dc)
805 {
1d792928 806 xpmAttr.valuemask = XpmReturnInfos; /* get infos back */
2bda0e17
KB
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
1d792928
VZ
824 XImageFree(ximage); // releases the malloc, but does not detroy
825 // the bitmap
2bda0e17
KB
826 M_BITMAPHANDLERDATA->m_ok = TRUE;
827 DeleteDC(dc);
828
1d792928
VZ
829 return TRUE;
830 }
831 else
2bda0e17
KB
832 {
833 M_BITMAPHANDLERDATA->m_ok = FALSE;
834// XpmDebugError(ErrorStatus, NULL);
835 DeleteDC(dc);
1d792928 836 return FALSE;
2bda0e17
KB
837 }
838 }
2bda0e17 839#endif
1d792928
VZ
840
841 return FALSE;
2bda0e17
KB
842}
843
844void wxBitmap::CleanUpHandlers(void)
845{
1d792928
VZ
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 }
2bda0e17
KB
855}
856
857void wxBitmap::InitStandardHandlers(void)
858{
1d792928
VZ
859 AddHandler(new wxBMPResourceHandler);
860 AddHandler(new wxBMPFileHandler);
861 AddHandler(new wxXPMFileHandler);
862 AddHandler(new wxXPMDataHandler);
863 AddHandler(new wxICOResourceHandler);
864 AddHandler(new wxICOFileHandler);
7b46ecac
JS
865}
866
867static 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 >>
8963;
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
917static long freeDIB(LPBITMAPINFO lpDIBHeader)
918{
919
920 if (lpDIBHeader != NULL) {
921 free(lpDIBHeader);
922 }
923
924 return (0);
925}
926
927