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