1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "bitmap.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
29 #include "wx/palette.h"
30 #include "wx/bitmap.h"
34 #include "wx/msw/private.h"
41 #include "../../contrib/wxxpm/libxpm.34b/lib/xpm34.h"
44 #include "wx/msw/dib.h"
46 #if !USE_SHARED_LIBRARIES
47 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
48 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
51 wxBitmapRefData::wxBitmapRefData(void)
59 m_selectedInto
= NULL
;
64 wxBitmapRefData::~wxBitmapRefData(void)
69 sprintf(buf
, "Bitmap was deleted without selecting out of wxMemoryDC %X.", (unsigned int) m_selectedInto
);
74 DeleteObject((HBITMAP
) m_hBitmap
);
83 wxList
wxBitmap::sm_handlers
;
85 wxBitmap::wxBitmap(void)
87 m_refData
= NULL
; // new wxBitmapRefData;
89 if ( wxTheBitmapList
)
90 wxTheBitmapList
->AddBitmap(this);
93 wxBitmap::~wxBitmap(void)
96 wxTheBitmapList
->DeleteObject(this);
99 bool wxBitmap::FreeResource(bool force
)
104 if (M_BITMAPDATA
->m_selectedInto
)
107 sprintf(buf
, "Bitmap %X was deleted without selecting out of wxMemoryDC %X.", (unsigned int) this, (unsigned int) M_BITMAPDATA
->m_selectedInto
);
110 if (M_BITMAPDATA
->m_hBitmap
)
112 DeleteObject((HBITMAP
) M_BITMAPDATA
->m_hBitmap
);
114 M_BITMAPDATA
->m_hBitmap
= 0 ;
117 if (M_BITMAPDATA->m_bitmapPalette)
118 delete M_BITMAPDATA->m_bitmapPalette;
120 M_BITMAPDATA->m_bitmapPalette = NULL ;
127 wxBitmap::wxBitmap(const char bits
[], int the_width
, int the_height
, int no_bits
)
129 m_refData
= new wxBitmapRefData
;
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;
136 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateBitmap(the_width
, the_height
, no_bits
, 1, bits
);
138 if (M_BITMAPDATA
->m_hBitmap
)
139 M_BITMAPDATA
->m_ok
= TRUE
;
141 M_BITMAPDATA
->m_ok
= FALSE
;
143 M_BITMAPDATA
->m_selectedInto
= NULL
;
145 if ( wxTheBitmapList
)
146 wxTheBitmapList
->AddBitmap(this);
149 wxBitmap::wxBitmap(int w
, int h
, int d
)
151 (void)Create(w
, h
, d
);
153 if ( wxTheBitmapList
)
154 wxTheBitmapList
->AddBitmap(this);
157 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
)
159 (void) Create(data
, type
, width
, height
, depth
);
161 if ( wxTheBitmapList
)
162 wxTheBitmapList
->AddBitmap(this);
165 wxBitmap::wxBitmap(const wxString
& filename
, long type
)
167 LoadFile(filename
, (int)type
);
169 if ( wxTheBitmapList
)
170 wxTheBitmapList
->AddBitmap(this);
175 wxBitmap::wxBitmap(const char **data
, wxItem
*WXUNUSED(anItem
))
177 (void) Create((void *)data
, wxBITMAP_TYPE_XPM_DATA
, 0, 0, 0);
181 bool wxBitmap::Create(int w
, int h
, int d
)
185 m_refData
= new wxBitmapRefData
;
187 M_BITMAPDATA
->m_width
= w
;
188 M_BITMAPDATA
->m_height
= h
;
189 M_BITMAPDATA
->m_depth
= d
;
193 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateBitmap(w
, h
, d
, 1, NULL
);
197 HDC dc
= GetDC(NULL
);
198 M_BITMAPDATA
->m_hBitmap
= (WXHBITMAP
) CreateCompatibleBitmap(dc
, w
, h
);
200 M_BITMAPDATA
->m_depth
= wxDisplayDepth();
202 if (M_BITMAPDATA
->m_hBitmap
)
203 M_BITMAPDATA
->m_ok
= TRUE
;
205 M_BITMAPDATA
->m_ok
= FALSE
;
206 return M_BITMAPDATA
->m_ok
;
209 bool wxBitmap::LoadFile(const wxString
& filename
, long type
)
213 m_refData
= new wxBitmapRefData
;
215 wxBitmapHandler
*handler
= FindHandler(type
);
217 if ( handler
== NULL
) {
218 wxLogWarning("no bitmap handler for type %d defined.", type
);
223 return handler
->LoadFile(this, filename
, type
, -1, -1);
226 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
)
230 m_refData
= new wxBitmapRefData
;
232 wxBitmapHandler
*handler
= FindHandler(type
);
234 if ( handler
== NULL
) {
235 wxLogWarning("no bitmap handler for type %d defined.", type
);
240 return handler
->Create(this, data
, type
, width
, height
, depth
);
243 bool wxBitmap::SaveFile(const wxString
& filename
, int type
, const wxPalette
*palette
)
245 wxBitmapHandler
*handler
= FindHandler(type
);
247 if ( handler
== NULL
) {
248 wxLogWarning("no bitmap handler for type %d defined.", type
);
253 return handler
->SaveFile(this, filename
, type
, palette
);
256 void wxBitmap::SetWidth(int w
)
259 m_refData
= new wxBitmapRefData
;
261 M_BITMAPDATA
->m_width
= w
;
264 void wxBitmap::SetHeight(int h
)
267 m_refData
= new wxBitmapRefData
;
269 M_BITMAPDATA
->m_height
= h
;
272 void wxBitmap::SetDepth(int d
)
275 m_refData
= new wxBitmapRefData
;
277 M_BITMAPDATA
->m_depth
= d
;
280 void wxBitmap::SetQuality(int q
)
283 m_refData
= new wxBitmapRefData
;
285 M_BITMAPDATA
->m_quality
= q
;
288 void wxBitmap::SetOk(bool isOk
)
291 m_refData
= new wxBitmapRefData
;
293 M_BITMAPDATA
->m_ok
= isOk
;
296 void wxBitmap::SetPalette(const wxPalette
& palette
)
299 m_refData
= new wxBitmapRefData
;
301 M_BITMAPDATA
->m_bitmapPalette
= palette
;
304 void wxBitmap::SetMask(wxMask
*mask
)
307 m_refData
= new wxBitmapRefData
;
309 M_BITMAPDATA
->m_bitmapMask
= mask
;
312 void wxBitmap::SetHBITMAP(WXHBITMAP bmp
)
315 m_refData
= new wxBitmapRefData
;
317 M_BITMAPDATA
->m_hBitmap
= bmp
;
320 void wxBitmap::AddHandler(wxBitmapHandler
*handler
)
322 sm_handlers
.Append(handler
);
325 void wxBitmap::InsertHandler(wxBitmapHandler
*handler
)
327 sm_handlers
.Insert(handler
);
330 bool wxBitmap::RemoveHandler(const wxString
& name
)
332 wxBitmapHandler
*handler
= FindHandler(name
);
335 sm_handlers
.DeleteObject(handler
);
342 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& name
)
344 wxNode
*node
= sm_handlers
.First();
347 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
348 if ( handler
->GetName() == name
)
355 wxBitmapHandler
*wxBitmap::FindHandler(const wxString
& extension
, long bitmapType
)
357 wxNode
*node
= sm_handlers
.First();
360 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
361 if ( handler
->GetExtension() == extension
&&
362 (bitmapType
== -1 || handler
->GetType() == bitmapType
) )
369 wxBitmapHandler
*wxBitmap::FindHandler(long bitmapType
)
371 wxNode
*node
= sm_handlers
.First();
374 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
375 if (handler
->GetType() == bitmapType
)
391 // Construct a mask from a bitmap and a colour indicating
392 // the transparent area
393 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
)
396 Create(bitmap
, colour
);
399 // Construct a mask from a bitmap and a palette index indicating
400 // the transparent area
401 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
)
404 Create(bitmap
, paletteIndex
);
407 // Construct a mask from a mono bitmap (copies the bitmap).
408 wxMask::wxMask(const wxBitmap
& bitmap
)
414 wxMask::~wxMask(void)
417 ::DeleteObject((HBITMAP
) m_maskBitmap
);
420 // Create a mask from a mono bitmap (copies the bitmap).
421 bool wxMask::Create(const wxBitmap
& bitmap
)
425 ::DeleteObject((HBITMAP
) m_maskBitmap
);
428 if (!bitmap
.Ok() || bitmap
.GetDepth() != 1)
432 m_maskBitmap
= (WXHBITMAP
) CreateBitmap(
437 HDC srcDC
= CreateCompatibleDC(0);
438 SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
439 HDC destDC
= CreateCompatibleDC(0);
440 SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
441 BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
);
442 SelectObject(srcDC
, 0);
444 SelectObject(destDC
, 0);
449 // Create a mask from a bitmap and a palette index indicating
450 // the transparent area
451 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
)
455 ::DeleteObject((HBITMAP
) m_maskBitmap
);
458 if (bitmap
.Ok() && bitmap
.GetPalette()->Ok())
460 unsigned char red
, green
, blue
;
461 if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
))
463 wxColour
transparentColour(red
, green
, blue
);
464 return Create(bitmap
, transparentColour
);
470 // Create a mask from a bitmap and a colour indicating
471 // the transparent area
472 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
476 ::DeleteObject((HBITMAP
) m_maskBitmap
);
484 // scan the bitmap for the transparent colour and set
485 // the corresponding pixels in the mask to BLACK and
487 COLORREF maskColour
= RGB(colour
.Red(), colour
.Green(), colour
.Blue());
488 m_maskBitmap
= (WXHBITMAP
) ::CreateBitmap(
493 HDC srcDC
= ::CreateCompatibleDC(0);
494 ::SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
495 HDC destDC
= ::CreateCompatibleDC(0);
496 ::SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
498 // this is not very efficient, but I can't think
499 // of a better way of doing it
500 for (int w
= 0; w
< bitmap
.GetWidth(); w
++)
502 for (int h
= 0; h
< bitmap
.GetHeight(); h
++)
504 COLORREF col
= GetPixel(srcDC
, w
, h
);
505 if (col
== maskColour
)
507 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0));
511 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255));
515 ::SelectObject(srcDC
, 0);
517 ::SelectObject(destDC
, 0);
526 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
528 bool wxBitmapHandler::Create(wxBitmap
*bitmap
, void *data
, long type
, int width
, int height
, int depth
)
533 bool wxBitmapHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long type
,
534 int desiredWidth
, int desiredHeight
)
539 bool wxBitmapHandler::SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*palette
)
548 class WXDLLEXPORT wxBMPResourceHandler
: public wxBitmapHandler
550 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler
)
552 inline wxBMPResourceHandler(void)
554 m_name
= "Windows bitmap resource";
556 m_type
= wxBITMAP_TYPE_BMP_RESOURCE
;
559 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
560 int desiredWidth
, int desiredHeight
);
562 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler
, wxBitmapHandler
)
564 bool wxBMPResourceHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
565 int desiredWidth
, int desiredHeight
)
567 // TODO: load colourmap.
568 M_BITMAPHANDLERDATA
->m_hBitmap
= (WXHBITMAP
) ::LoadBitmap(wxGetInstance(), name
);
569 if (M_BITMAPHANDLERDATA
->m_hBitmap
)
571 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
573 GetObject((HBITMAP
) M_BITMAPHANDLERDATA
->m_hBitmap
, sizeof(BITMAP
), (LPSTR
) &bm
);
574 M_BITMAPHANDLERDATA
->m_width
= bm
.bmWidth
;
575 M_BITMAPHANDLERDATA
->m_height
= bm
.bmHeight
;
576 M_BITMAPHANDLERDATA
->m_depth
= bm
.bmPlanes
;
580 // it's probably not found
581 wxLogError("Can't load bitmap '%s' from resources! Check .rc file.", name
.c_str());
586 class WXDLLEXPORT wxBMPFileHandler
: public wxBitmapHandler
588 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler
)
590 inline wxBMPFileHandler(void)
592 m_name
= "Windows bitmap file";
594 m_type
= wxBITMAP_TYPE_BMP
;
597 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
598 int desiredWidth
, int desiredHeight
);
599 virtual bool SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*palette
= NULL
);
601 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler
, wxBitmapHandler
)
603 bool wxBMPFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
604 int desiredWidth
, int desiredHeight
)
606 #if USE_IMAGE_LOADING_IN_MSW
607 wxPalette
*palette
= NULL
;
608 bool success
= FALSE
;
610 if (type & wxBITMAP_DISCARD_COLOURMAP)
611 success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap);
614 success
= (wxLoadIntoBitmap(WXSTRINGCAST name
, bitmap
, &palette
) != 0);
615 if (!success
&& palette
)
621 M_BITMAPHANDLERDATA
->m_bitmapPalette
= *palette
;
628 bool wxBMPFileHandler::SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*pal
)
630 #if USE_IMAGE_LOADING_IN_MSW
631 wxPalette
*actualPalette
= (wxPalette
*)pal
;
632 if (!actualPalette
&& (!M_BITMAPHANDLERDATA
->m_bitmapPalette
.IsNull()))
633 actualPalette
= & (M_BITMAPHANDLERDATA
->m_bitmapPalette
);
634 return (wxSaveBitmap(WXSTRINGCAST name
, bitmap
, actualPalette
) != 0);
640 class WXDLLEXPORT wxXPMFileHandler
: public wxBitmapHandler
642 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler
)
644 inline wxXPMFileHandler(void)
646 m_name
= "XPM bitmap file";
648 m_type
= wxBITMAP_TYPE_XPM
;
651 virtual bool LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
652 int desiredWidth
= -1, int desiredHeight
= -1);
653 virtual bool SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*palette
= NULL
);
655 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler
, wxBitmapHandler
)
657 bool wxXPMFileHandler::LoadFile(wxBitmap
*bitmap
, const wxString
& name
, long flags
,
658 int desiredWidth
, int desiredHeight
)
662 XpmAttributes xpmAttr
;
665 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
666 dc
= CreateCompatibleDC(NULL
);
669 xpmAttr
.valuemask
= XpmReturnPixels
;
670 int errorStatus
= XpmReadFileToImage(&dc
, WXSTRINGCAST name
, &ximage
, (XImage
**) NULL
, &xpmAttr
);
672 if (errorStatus
== XpmSuccess
)
674 M_BITMAPHANDLERDATA
->m_hBitmap
= (WXHBITMAP
) ximage
->bitmap
;
677 GetObject((HBITMAP
)M_BITMAPHANDLERDATA
->m_hBitmap
, sizeof(bm
), (LPSTR
) & bm
);
679 M_BITMAPHANDLERDATA
->m_width
= (bm
.bmWidth
);
680 M_BITMAPHANDLERDATA
->m_height
= (bm
.bmHeight
);
681 M_BITMAPHANDLERDATA
->m_depth
= (bm
.bmPlanes
* bm
.bmBitsPixel
);
682 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
683 XpmFreeAttributes(&xpmAttr
);
686 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
691 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
700 bool wxXPMFileHandler::SaveFile(wxBitmap
*bitmap
, const wxString
& name
, int type
, const wxPalette
*palette
)
705 Visual
*visual
= NULL
;
708 dc
= CreateCompatibleDC(NULL
);
711 if (SelectObject(dc
, (HBITMAP
) M_BITMAPHANDLERDATA
->m_hBitmap
))
712 { /* for following SetPixel */
713 /* fill the XImage struct 'by hand' */
714 ximage
.width
= M_BITMAPHANDLERDATA
->m_width
;
715 ximage
.height
= M_BITMAPHANDLERDATA
->m_height
;
716 ximage
.depth
= M_BITMAPHANDLERDATA
->m_depth
;
717 ximage
.bitmap
= (void *)M_BITMAPHANDLERDATA
->m_hBitmap
;
718 int errorStatus
= XpmWriteFileFromImage(&dc
, WXSTRINGCAST name
,
719 &ximage
, (XImage
*) NULL
, (XpmAttributes
*) NULL
);
724 if (errorStatus
== XpmSuccess
)
725 return TRUE
; /* no error */
735 class WXDLLEXPORT wxXPMDataHandler
: public wxBitmapHandler
737 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler
)
739 inline wxXPMDataHandler(void)
741 m_name
= "XPM bitmap data";
743 m_type
= wxBITMAP_TYPE_XPM_DATA
;
746 virtual bool Create(wxBitmap
*bitmap
, void *data
, long flags
, int width
, int height
, int depth
= 1);
748 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler
, wxBitmapHandler
)
750 bool wxXPMDataHandler::Create(wxBitmap
*bitmap
, void *data
, long flags
, int width
, int height
, int depth
)
755 XpmAttributes xpmAttr
;
758 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
759 M_BITMAPHANDLERDATA
->m_numColors
= 0;
761 dc
= CreateCompatibleDC(NULL
); /* memory DC */
765 xpmAttr
.valuemask
= XpmReturnInfos
; /* get infos back */
766 ErrorStatus
= XpmCreateImageFromData(&dc
, (char **)data
,
767 &ximage
, (XImage
**) NULL
, &xpmAttr
);
769 if (ErrorStatus
== XpmSuccess
)
771 /* ximage is malloced and contains bitmap and attributes */
772 M_BITMAPHANDLERDATA
->m_hBitmap
= (WXHBITMAP
) ximage
->bitmap
;
775 GetObject((HBITMAP
) M_BITMAPHANDLERDATA
->m_hBitmap
, sizeof(bm
), (LPSTR
) & bm
);
777 M_BITMAPHANDLERDATA
->m_width
= (bm
.bmWidth
);
778 M_BITMAPHANDLERDATA
->m_height
= (bm
.bmHeight
);
779 M_BITMAPHANDLERDATA
->m_depth
= (bm
.bmPlanes
* bm
.bmBitsPixel
);
780 M_BITMAPHANDLERDATA
->m_numColors
= xpmAttr
.npixels
;
781 XpmFreeAttributes(&xpmAttr
);
783 XImageFree(ximage
); // releases the malloc, but does not detroy
785 M_BITMAPHANDLERDATA
->m_ok
= TRUE
;
792 M_BITMAPHANDLERDATA
->m_ok
= FALSE
;
793 // XpmDebugError(ErrorStatus, NULL);
803 void wxBitmap::CleanUpHandlers(void)
805 wxNode
*node
= sm_handlers
.First();
808 wxBitmapHandler
*handler
= (wxBitmapHandler
*)node
->Data();
809 wxNode
*next
= node
->Next();
816 void wxBitmap::InitStandardHandlers(void)
818 AddHandler(new wxBMPResourceHandler
);
819 AddHandler(new wxBMPFileHandler
);
820 AddHandler(new wxXPMFileHandler
);
821 AddHandler(new wxXPMDataHandler
);
822 AddHandler(new wxICOResourceHandler
);
823 AddHandler(new wxICOFileHandler
);