1 //////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "bitmap.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  37     #include "wx/palette.h" 
  38     #include "wx/dcmemory.h" 
  39     #include "wx/bitmap.h" 
  43 #include "wx/msw/private.h" 
  47 #include "wx/msw/dib.h" 
  51 #include "wx/xpmdecod.h" 
  53 #ifdef wxHAVE_RAW_BITMAP 
  54 #include "wx/rawbmp.h" 
  57 // missing from mingw32 header 
  59     #define CLR_INVALID ((COLORREF)-1) 
  60 #endif // no CLR_INVALID 
  62 // ---------------------------------------------------------------------------- 
  64 // ---------------------------------------------------------------------------- 
  66 class WXDLLEXPORT wxBitmapRefData 
: public wxGDIImageRefData
 
  70     virtual ~wxBitmapRefData() { Free(); } 
  74     // set the mask object to use as the mask, we take ownership of it 
  75     void SetMask(wxMask 
*mask
) 
  81     // set the HBITMAP to use as the mask 
  82     void SetMask(HBITMAP hbmpMask
) 
  84         SetMask(new wxMask((WXHBITMAP
)hbmpMask
)); 
  88     wxMask 
*GetMask() const { return m_bitmapMask
; } 
  92     wxPalette     m_bitmapPalette
; 
  93 #endif // wxUSE_PALETTE 
  99     // this field is solely for error checking: we detect selecting a bitmap 
 100     // into more than one DC at once or deleting a bitmap still selected into a 
 101     // DC (both are serious programming errors under Windows) 
 102     wxDC         
*m_selectedInto
; 
 103 #endif // __WXDEBUG__ 
 106     // when GetRawData() is called for a DDB we need to convert it to a DIB 
 107     // first to be able to provide direct access to it and we cache that DIB 
 108     // here and convert it back to DDB when UngetRawData() is called 
 112     // true if we have alpha transparency info and can be drawn using 
 116     // true if our HBITMAP is a DIB section, false if it is a DDB 
 120     // optional mask for transparent drawing 
 121     wxMask       
*m_bitmapMask
; 
 123     DECLARE_NO_COPY_CLASS(wxBitmapRefData
) 
 126 // ---------------------------------------------------------------------------- 
 128 // ---------------------------------------------------------------------------- 
 130 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
) 
 131 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
) 
 133 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
) 
 135 // ============================================================================ 
 137 // ============================================================================ 
 139 // ---------------------------------------------------------------------------- 
 141 // ---------------------------------------------------------------------------- 
 143 // decide whether we should create a DIB or a DDB for the given parameters 
 145 // NB: we always use DIBs under Windows CE as this is much simpler (even if 
 146 //     also less efficient...) and we obviously can't use them if there is no 
 147 //     DIB support compiled in at all 
 149     static inline bool wxShouldCreateDIB(int, int, int, WXHDC
) { return true; } 
 151     #define ALWAYS_USE_DIB 
 153     // no sense in defining wxShouldCreateDIB() as we can't compile code 
 154     // executed if it is true, so we have to use #if's anyhow 
 155     #define NEVER_USE_DIB 
 156 #else // wxUSE_WXDIB && !__WXWINCE__ 
 157     static inline bool wxShouldCreateDIB(int w
, int h
, int d
, WXHDC hdc
) 
 159         // here is the logic: 
 161         //  (a) if hdc is specified, the caller explicitly wants DDB 
 162         //  (b) otherwise, create a DIB if depth >= 24 (we don't support 16bpp 
 163         //      or less DIBs anyhow) 
 164         //  (c) finally, create DIBs under Win9x even if the depth hasn't been 
 165         //      explicitly specified but the current display depth is 24 or 
 166         //      more and the image is "big", i.e. > 16Mb which is the 
 167         //      theoretical limit for DDBs under Win9x 
 169         // consequences (all of which seem to make sense): 
 171         //  (i)     by default, DDBs are created (depth == -1 usually) 
 172         //  (ii)    DIBs can be created by explicitly specifying the depth 
 173         //  (iii)   using a DC always forces creating a DDB 
 177                         wxDIB::GetLineSize(w
, wxDisplayDepth())*h 
> 16*1024*1024)); 
 180     #define SOMETIMES_USE_DIB 
 181 #endif // different DIB usage scenarious 
 183 // ---------------------------------------------------------------------------- 
 185 // ---------------------------------------------------------------------------- 
 187 wxBitmapRefData::wxBitmapRefData() 
 190     m_selectedInto 
= NULL
; 
 194     m_hBitmap 
= (WXHBITMAP
) NULL
; 
 203 void wxBitmapRefData::Free() 
 205     wxASSERT_MSG( !m_selectedInto
, 
 206                   wxT("deleting bitmap still selected into wxMemoryDC") ); 
 209     wxASSERT_MSG( !m_dib
, _T("forgot to call wxBitmap::UngetRawData()!") ); 
 214         if ( !::DeleteObject((HBITMAP
)m_hBitmap
) ) 
 216             wxLogLastError(wxT("DeleteObject(hbitmap)")); 
 224 // ---------------------------------------------------------------------------- 
 226 // ---------------------------------------------------------------------------- 
 228 // this function should be called from all wxBitmap ctors 
 229 void wxBitmap::Init() 
 231     // m_refData = NULL; done in the base class ctor 
 234 wxGDIImageRefData 
*wxBitmap::CreateData() const 
 236     return new wxBitmapRefData
; 
 241 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage
& icon
) 
 243 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
 244     // it may be either HICON or HCURSOR 
 245     HICON hicon 
= (HICON
)icon
.GetHandle(); 
 248     if ( !::GetIconInfo(hicon
, &iconInfo
) ) 
 250         wxLogLastError(wxT("GetIconInfo")); 
 255     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 258     int w 
= icon
.GetWidth(), 
 259         h 
= icon
.GetHeight(); 
 261     refData
->m_width 
= w
; 
 262     refData
->m_height 
= h
; 
 263     refData
->m_depth 
= wxDisplayDepth(); 
 265     refData
->m_hBitmap 
= (WXHBITMAP
)iconInfo
.hbmColor
; 
 267     // the mask returned by GetIconInfo() is inversed compared to the usual 
 269     refData
->SetMask(wxInvertMask(iconInfo
.hbmMask
, w
, h
)); 
 272     // delete the old one now as we don't need it any more 
 273     ::DeleteObject(iconInfo
.hbmMask
); 
 283 bool wxBitmap::CopyFromCursor(const wxCursor
& cursor
) 
 290     return CopyFromIconOrCursor(cursor
); 
 293 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
) 
 300     return CopyFromIconOrCursor(icon
); 
 303 #ifndef NEVER_USE_DIB 
 305 bool wxBitmap::CopyFromDIB(const wxDIB
& dib
) 
 307     wxCHECK_MSG( dib
.IsOk(), FALSE
, _T("invalid DIB in CopyFromDIB") ); 
 309 #ifdef SOMETIMES_USE_DIB 
 310     HBITMAP hbitmap 
= dib
.CreateDDB(); 
 313 #else // ALWAYS_USE_DIB 
 314     HBITMAP hbitmap 
= ((wxDIB 
&)dib
).Detach();  // const_cast 
 315 #endif // SOMETIMES_USE_DIB/ALWAYS_USE_DIB 
 319     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 322     refData
->m_width 
= dib
.GetWidth(); 
 323     refData
->m_height 
= dib
.GetHeight(); 
 324     refData
->m_depth 
= dib
.GetDepth(); 
 326     refData
->m_hBitmap 
= (WXHBITMAP
)hbitmap
; 
 329     wxPalette 
*palette 
= dib
.CreatePalette(); 
 332         refData
->m_bitmapPalette 
= *palette
; 
 336 #endif // wxUSE_PALETTE 
 341 #endif // NEVER_USE_DIB 
 343 wxBitmap::~wxBitmap() 
 347 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
) 
 351 #ifndef __WXMICROWIN__ 
 352     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 355     refData
->m_width 
= width
; 
 356     refData
->m_height 
= height
; 
 357     refData
->m_depth 
= depth
; 
 362         // we assume that it is in XBM format which is not quite the same as 
 363         // the format CreateBitmap() wants because the order of bytes in the 
 365         const size_t bytesPerLine 
= (width 
+ 7) / 8; 
 366         const size_t padding 
= bytesPerLine 
% 2; 
 367         const size_t len 
= height 
* ( padding 
+ bytesPerLine 
); 
 368         data 
= (char *)malloc(len
); 
 369         const char *src 
= bits
; 
 372         for ( int rows 
= 0; rows 
< height
; rows
++ ) 
 374             for ( size_t cols 
= 0; cols 
< bytesPerLine
; cols
++ ) 
 376                 unsigned char val 
= *src
++; 
 377                 unsigned char reversed 
= 0; 
 379                 for ( int bits 
= 0; bits 
< 8; bits
++) 
 382                     reversed 
|= (val 
& 0x01); 
 394         // bits should already be in Windows standard format 
 395         data 
= (char *)bits
;    // const_cast is harmless 
 398     HBITMAP hbmp 
= ::CreateBitmap(width
, height
, 1, depth
, data
); 
 401         wxLogLastError(wxT("CreateBitmap")); 
 409     SetHBITMAP((WXHBITMAP
)hbmp
); 
 413 // Create from XPM data 
 414 #if wxUSE_IMAGE && wxUSE_XPM 
 415 bool wxBitmap::CreateFromXpm(const char **data
) 
 417 bool wxBitmap::CreateFromXpm(const char **WXUNUSED(data
)) 
 420 #if wxUSE_IMAGE && wxUSE_XPM 
 423     wxCHECK_MSG( data 
!= NULL
, FALSE
, wxT("invalid bitmap data") ) 
 425     wxXPMDecoder decoder
; 
 426     wxImage img 
= decoder
.ReadData(data
); 
 427     wxCHECK_MSG( img
.Ok(), FALSE
, wxT("invalid bitmap data") ) 
 429     *this = wxBitmap(img
); 
 436 wxBitmap::wxBitmap(int w
, int h
, int d
) 
 440     (void)Create(w
, h
, d
); 
 443 wxBitmap::wxBitmap(int w
, int h
, const wxDC
& dc
) 
 447     (void)Create(w
, h
, dc
); 
 450 wxBitmap::wxBitmap(void *data
, long type
, int width
, int height
, int depth
) 
 454     (void)Create(data
, type
, width
, height
, depth
); 
 457 wxBitmap::wxBitmap(const wxString
& filename
, wxBitmapType type
) 
 461     LoadFile(filename
, (int)type
); 
 464 bool wxBitmap::Create(int width
, int height
, int depth
) 
 466     return DoCreate(width
, height
, depth
, 0); 
 469 bool wxBitmap::Create(int width
, int height
, const wxDC
& dc
) 
 471     wxCHECK_MSG( dc
.Ok(), FALSE
, _T("invalid HDC in wxBitmap::Create()") ); 
 473     return DoCreate(width
, height
, -1, dc
.GetHDC()); 
 476 bool wxBitmap::DoCreate(int w
, int h
, int d
, WXHDC hdc
) 
 480     m_refData 
= new wxBitmapRefData
; 
 482     GetBitmapData()->m_width 
= w
; 
 483     GetBitmapData()->m_height 
= h
; 
 485     HBITMAP hbmp    
wxDUMMY_INITIALIZE(0); 
 487 #ifndef NEVER_USE_DIB 
 488     if ( wxShouldCreateDIB(w
, h
, d
, hdc
) ) 
 492             // create DIBs without alpha channel by default 
 500         // don't delete the DIB section in dib object dtor 
 503         GetBitmapData()->m_isDIB 
= TRUE
; 
 504         GetBitmapData()->m_depth 
= d
; 
 507 #endif // NEVER_USE_DIB 
 509 #ifndef ALWAYS_USE_DIB 
 510 #ifndef __WXMICROWIN__ 
 513             hbmp 
= ::CreateBitmap(w
, h
, 1, d
, NULL
); 
 516                 wxLogLastError(wxT("CreateBitmap")); 
 519             GetBitmapData()->m_depth 
= d
; 
 521         else // d == 0, create bitmap compatible with the screen 
 522 #endif // !__WXMICROWIN__ 
 525             hbmp 
= ::CreateCompatibleBitmap(dc
, w
, h
); 
 528                 wxLogLastError(wxT("CreateCompatibleBitmap")); 
 531             GetBitmapData()->m_depth 
= wxDisplayDepth(); 
 533 #endif // !ALWAYS_USE_DIB 
 536     SetHBITMAP((WXHBITMAP
)hbmp
); 
 543 // ---------------------------------------------------------------------------- 
 544 // wxImage to/from conversions for Microwin 
 545 // ---------------------------------------------------------------------------- 
 547 // Microwin versions are so different from normal ones that it really doesn't 
 548 // make sense to use #ifdefs inside the function bodies 
 549 #ifdef __WXMICROWIN__ 
 551 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
, const wxDC
& dc
) 
 553     // Set this to 1 to experiment with mask code, 
 554     // which currently doesn't work 
 557     m_refData 
= new wxBitmapRefData(); 
 559     // Initial attempt at a simple-minded implementation. 
 560     // The bitmap will always be created at the screen depth, 
 561     // so the 'depth' argument is ignored. 
 563     HDC hScreenDC 
= ::GetDC(NULL
); 
 564     int screenDepth 
= ::GetDeviceCaps(hScreenDC
, BITSPIXEL
); 
 566     HBITMAP hBitmap 
= ::CreateCompatibleBitmap(hScreenDC
, image
.GetWidth(), image
.GetHeight()); 
 567     HBITMAP hMaskBitmap 
= NULL
; 
 568     HBITMAP hOldMaskBitmap 
= NULL
; 
 570     unsigned char maskR 
= 0; 
 571     unsigned char maskG 
= 0; 
 572     unsigned char maskB 
= 0; 
 574     //    printf("Created bitmap %d\n", (int) hBitmap); 
 577         ::ReleaseDC(NULL
, hScreenDC
); 
 580     HDC hMemDC 
= ::CreateCompatibleDC(hScreenDC
); 
 582     HBITMAP hOldBitmap 
= ::SelectObject(hMemDC
, hBitmap
); 
 583     ::ReleaseDC(NULL
, hScreenDC
); 
 585     // created an mono-bitmap for the possible mask 
 586     bool hasMask 
= image
.HasMask(); 
 591         // FIXME: we should be able to pass bpp = 1, but 
 592         // GdBlit can't handle a different depth 
 594         hMaskBitmap 
= ::CreateBitmap( (WORD
)image
.GetWidth(), (WORD
)image
.GetHeight(), 1, 1, NULL 
); 
 596         hMaskBitmap 
= ::CreateCompatibleBitmap( hMemDC
, (WORD
)image
.GetWidth(), (WORD
)image
.GetHeight()); 
 598         maskR 
= image
.GetMaskRed(); 
 599         maskG 
= image
.GetMaskGreen(); 
 600         maskB 
= image
.GetMaskBlue(); 
 608             hScreenDC 
= ::GetDC(NULL
); 
 609             hMaskDC 
= ::CreateCompatibleDC(hScreenDC
); 
 610            ::ReleaseDC(NULL
, hScreenDC
); 
 612             hOldMaskBitmap 
= ::SelectObject( hMaskDC
, hMaskBitmap
); 
 620     for (i 
= 0; i 
< image
.GetWidth(); i
++) 
 622         for (j 
= 0; j 
< image
.GetHeight(); j
++) 
 624             unsigned char red 
= image
.GetRed(i
, j
); 
 625             unsigned char green 
= image
.GetGreen(i
, j
); 
 626             unsigned char blue 
= image
.GetBlue(i
, j
); 
 628             ::SetPixel(hMemDC
, i
, j
, PALETTERGB(red
, green
, blue
)); 
 632                 // scan the bitmap for the transparent colour and set the corresponding 
 633                 // pixels in the mask to BLACK and the rest to WHITE 
 634                 if (maskR 
== red 
&& maskG 
== green 
&& maskB 
== blue
) 
 635                     ::SetPixel(hMaskDC
, i
, j
, PALETTERGB(0, 0, 0)); 
 637                     ::SetPixel(hMaskDC
, i
, j
, PALETTERGB(255, 255, 255)); 
 642     ::SelectObject(hMemDC
, hOldBitmap
); 
 646         ::SelectObject(hMaskDC
, hOldMaskBitmap
); 
 649         ((wxBitmapRefData
*)m_refData
)->SetMask(hMaskBitmap
); 
 652     SetWidth(image
.GetWidth()); 
 653     SetHeight(image
.GetHeight()); 
 654     SetDepth(screenDepth
); 
 655     SetHBITMAP( (WXHBITMAP
) hBitmap 
); 
 658     // Copy the palette from the source image 
 659     SetPalette(image
.GetPalette()); 
 660 #endif // wxUSE_PALETTE 
 665 wxImage 
wxBitmap::ConvertToImage() const 
 667     // Initial attempt at a simple-minded implementation. 
 668     // The bitmap will always be created at the screen depth, 
 669     // so the 'depth' argument is ignored. 
 670     // TODO: transparency (create a mask image) 
 674         wxFAIL_MSG( wxT("bitmap is invalid") ); 
 680     wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") ); 
 682     // create an wxImage object 
 683     int width 
= GetWidth(); 
 684     int height 
= GetHeight(); 
 685     image
.Create( width
, height 
); 
 686     unsigned char *data 
= image
.GetData(); 
 689         wxFAIL_MSG( wxT("could not allocate data for image") ); 
 693     HDC hScreenDC 
= ::GetDC(NULL
); 
 695     HDC hMemDC 
= ::CreateCompatibleDC(hScreenDC
); 
 696     ::ReleaseDC(NULL
, hScreenDC
); 
 698     HBITMAP hBitmap 
= (HBITMAP
) GetHBITMAP(); 
 700     HBITMAP hOldBitmap 
= ::SelectObject(hMemDC
, hBitmap
); 
 703     for (i 
= 0; i 
< GetWidth(); i
++) 
 705         for (j 
= 0; j 
< GetHeight(); j
++) 
 707             COLORREF color 
= ::GetPixel(hMemDC
, i
, j
); 
 708             unsigned char red 
= GetRValue(color
); 
 709             unsigned char green 
= GetGValue(color
); 
 710             unsigned char blue 
= GetBValue(color
); 
 712             image
.SetRGB(i
, j
, red
, green
, blue
); 
 716     ::SelectObject(hMemDC
, hOldBitmap
); 
 720     // Copy the palette from the source image 
 722         image
.SetPalette(* GetPalette()); 
 723 #endif // wxUSE_PALETTE 
 728 #endif // __WXMICROWIN__ 
 730 // ---------------------------------------------------------------------------- 
 731 // wxImage to/from conversions 
 732 // ---------------------------------------------------------------------------- 
 736 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
) 
 738     return CreateFromImage(image
, depth
, 0); 
 741 bool wxBitmap::CreateFromImage(const wxImage
& image
, const wxDC
& dc
) 
 743     wxCHECK_MSG( dc
.Ok(), FALSE
, 
 744                     _T("invalid HDC in wxBitmap::CreateFromImage()") ); 
 746     return CreateFromImage(image
, -1, dc
.GetHDC()); 
 749 bool wxBitmap::CreateFromImage(const wxImage
& image
, int depth
, WXHDC hdc
) 
 751     wxCHECK_MSG( image
.Ok(), FALSE
, wxT("invalid image") ); 
 755     // first convert the image to DIB 
 756     const int h 
= image
.GetHeight(); 
 757     const int w 
= image
.GetWidth(); 
 764     // store the bitmap parameters 
 765     wxBitmapRefData 
*refData 
= new wxBitmapRefData
; 
 766     refData
->m_width 
= w
; 
 767     refData
->m_height 
= h
; 
 768     refData
->m_hasAlpha 
= image
.HasAlpha(); 
 773     // next either store DIB as is or create a DDB from it 
 774     HBITMAP hbitmap     
wxDUMMY_INITIALIZE(0); 
 776     // are we going to use DIB? 
 778     // NB: DDBs don't support alpha so if we have alpha channel we must use DIB 
 779     if ( image
.HasAlpha() || wxShouldCreateDIB(w
, h
, depth
, hdc
) ) 
 781         // don't delete the DIB section in dib object dtor 
 782         hbitmap 
= dib
.Detach(); 
 784         refData
->m_isDIB 
= TRUE
; 
 785         refData
->m_depth 
= dib
.GetDepth(); 
 787 #ifndef ALWAYS_USE_DIB 
 788     else // we need to convert DIB to DDB 
 790         hbitmap 
= dib
.CreateDDB((HDC
)hdc
); 
 792         refData
->m_depth 
= depth 
== -1 ? wxDisplayDepth() : depth
; 
 794 #endif // !ALWAYS_USE_DIB 
 796     // validate this object 
 797     SetHBITMAP((WXHBITMAP
)hbitmap
); 
 799     // finally also set the mask if we have one 
 800     if ( image
.HasMask() ) 
 802         SetMask(new wxMask(*this, wxColour(image
.GetMaskRed(), 
 803                                            image
.GetMaskGreen(), 
 804                                            image
.GetMaskBlue()))); 
 810 wxImage 
wxBitmap::ConvertToImage() const 
 817         image 
= dib
.ConvertToImage(); 
 827 #endif // wxUSE_WXDIB 
 829 #endif // wxUSE_IMAGE 
 831 // ---------------------------------------------------------------------------- 
 832 // loading and saving bitmaps 
 833 // ---------------------------------------------------------------------------- 
 835 bool wxBitmap::LoadFile(const wxString
& filename
, long type
) 
 839     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
 843         m_refData 
= new wxBitmapRefData
; 
 845         return handler
->LoadFile(this, filename
, type
, -1, -1); 
 848     else // no bitmap handler found 
 851         if ( image
.LoadFile( filename
, type 
) && image
.Ok() ) 
 853             *this = wxBitmap(image
); 
 858 #endif // wxUSE_IMAGE 
 863 bool wxBitmap::Create(void *data
, long type
, int width
, int height
, int depth
) 
 867     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
 871         wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %ld defined."), type
); 
 876     m_refData 
= new wxBitmapRefData
; 
 878     return handler
->Create(this, data
, type
, width
, height
, depth
); 
 881 bool wxBitmap::SaveFile(const wxString
& filename
, 
 883                         const wxPalette 
*palette
) 
 885     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
 889         return handler
->SaveFile(this, filename
, type
, palette
); 
 892     else // no bitmap handler found 
 894         // FIXME what about palette? shouldn't we use it? 
 895         wxImage image 
= ConvertToImage(); 
 898             return image
.SaveFile(filename
, type
); 
 901 #endif // wxUSE_IMAGE 
 906 // ---------------------------------------------------------------------------- 
 907 // sub bitmap extraction 
 908 // ---------------------------------------------------------------------------- 
 910 wxBitmap 
wxBitmap::GetSubBitmap( const wxRect
& rect
) const 
 913                  (rect
.x 
>= 0) && (rect
.y 
>= 0) && 
 914                  (rect
.x
+rect
.width 
<= GetWidth()) && 
 915                  (rect
.y
+rect
.height 
<= GetHeight()), 
 916                  wxNullBitmap
, wxT("Invalid bitmap or bitmap region") ); 
 918     wxBitmap 
ret( rect
.width
, rect
.height 
); 
 919     wxASSERT_MSG( ret
.Ok(), wxT("GetSubBitmap error") ); 
 921 #ifndef __WXMICROWIN__ 
 922     // TODO: copy alpha channel data if any 
 929         SelectInHDC 
selectSrc(dcSrc
, GetHbitmap()), 
 930                     selectDst(dcDst
, GetHbitmapOf(ret
)); 
 932         if ( !selectSrc 
|| !selectDst 
) 
 934             wxLogLastError(_T("SelectObjct(hBitmap)")); 
 937         if ( !::BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, 
 938                        dcSrc
, rect
.x
, rect
.y
, SRCCOPY
) ) 
 940             wxLogLastError(_T("BitBlt")); 
 944     // copy mask if there is one 
 947         HBITMAP hbmpMask 
= ::CreateBitmap(rect
.width
, rect
.height
, 1, 1, 0); 
 949         SelectInHDC 
selectSrc(dcSrc
, (HBITMAP
) GetMask()->GetMaskBitmap()), 
 950                     selectDst(dcDst
, hbmpMask
); 
 952         if ( !::BitBlt(dcDst
, 0, 0, rect
.width
, rect
.height
, 
 953                        dcSrc
, rect
.x
, rect
.y
, SRCCOPY
) ) 
 955             wxLogLastError(_T("BitBlt")); 
 958         wxMask 
*mask 
= new wxMask((WXHBITMAP
) hbmpMask
); 
 961 #endif // !__WXMICROWIN__ 
 966 // ---------------------------------------------------------------------------- 
 967 // wxBitmap accessors 
 968 // ---------------------------------------------------------------------------- 
 971 wxPalette
* wxBitmap::GetPalette() const 
 973     return GetBitmapData() ? &GetBitmapData()->m_bitmapPalette
 
 974                            : (wxPalette 
*) NULL
; 
 978 wxMask 
*wxBitmap::GetMask() const 
 980     return GetBitmapData() ? GetBitmapData()->GetMask() : (wxMask 
*) NULL
; 
 985 wxDC 
*wxBitmap::GetSelectedInto() const 
 987     return GetBitmapData() ? GetBitmapData()->m_selectedInto 
: (wxDC 
*) NULL
; 
 992 #if WXWIN_COMPATIBILITY_2_4 
 994 int wxBitmap::GetQuality() const 
 999 #endif // WXWIN_COMPATIBILITY_2_4 
1001 void wxBitmap::UseAlpha() 
1003     if ( GetBitmapData() ) 
1004         GetBitmapData()->m_hasAlpha 
= true; 
1007 bool wxBitmap::HasAlpha() const 
1009     return GetBitmapData() && GetBitmapData()->m_hasAlpha
; 
1012 // ---------------------------------------------------------------------------- 
1014 // ---------------------------------------------------------------------------- 
1018 void wxBitmap::SetSelectedInto(wxDC 
*dc
) 
1020     if ( GetBitmapData() ) 
1021         GetBitmapData()->m_selectedInto 
= dc
; 
1028 void wxBitmap::SetPalette(const wxPalette
& palette
) 
1032     GetBitmapData()->m_bitmapPalette 
= palette
; 
1035 #endif // wxUSE_PALETTE 
1037 void wxBitmap::SetMask(wxMask 
*mask
) 
1041     GetBitmapData()->SetMask(mask
); 
1044 #if WXWIN_COMPATIBILITY_2_4 
1046 void wxBitmap::SetQuality(int WXUNUSED(quality
)) 
1050 #endif // WXWIN_COMPATIBILITY_2_4 
1052 // ---------------------------------------------------------------------------- 
1053 // raw bitmap access support 
1054 // ---------------------------------------------------------------------------- 
1056 #ifdef wxHAVE_RAW_BITMAP 
1057 void *wxBitmap::GetRawData(wxPixelDataBase
& data
, int bpp
) 
1062         // no bitmap, no data (raw or otherwise) 
1066     // if we're already a DIB we can access our data directly, but if not we 
1067     // need to convert this DDB to a DIB section and use it for raw access and 
1068     // then convert it back 
1070     if ( !GetBitmapData()->m_isDIB 
) 
1072         wxCHECK_MSG( !GetBitmapData()->m_dib
, FALSE
, 
1073                         _T("GetRawData() may be called only once") ); 
1075         wxDIB 
*dib 
= new wxDIB(*this); 
1083         // we'll free it in UngetRawData() 
1084         GetBitmapData()->m_dib 
= dib
; 
1086         hDIB 
= dib
->GetHandle(); 
1090         hDIB 
= GetHbitmap(); 
1094     if ( ::GetObject(hDIB
, sizeof(ds
), &ds
) != sizeof(DIBSECTION
) ) 
1096         wxFAIL_MSG( _T("failed to get DIBSECTION from a DIB?") ); 
1101     // check that the bitmap is in correct format 
1102     if ( ds
.dsBm
.bmBitsPixel 
!= bpp 
) 
1104         wxFAIL_MSG( _T("incorrect bitmap type in wxBitmap::GetRawData()") ); 
1109     // ok, store the relevant info in wxPixelDataBase 
1110     const LONG h 
= ds
.dsBm
.bmHeight
; 
1112     data
.m_width 
= ds
.dsBm
.bmWidth
; 
1115     // remember that DIBs are stored in top to bottom order! 
1116     const LONG bytesPerRow 
= ds
.dsBm
.bmWidthBytes
; 
1117     data
.m_stride 
= -bytesPerRow
; 
1119     char *bits 
= (char *)ds
.dsBm
.bmBits
; 
1122         bits 
+= (h 
- 1)*bytesPerRow
; 
1131 void wxBitmap::UngetRawData(wxPixelDataBase
& dataBase
) 
1137     // the cast is ugly but we can't do without it and without making this 
1138     // function template (and hence inline) unfortunately 
1139     typedef wxPixelData
<wxBitmap
, wxAlphaPixelFormat
> PixelData
; 
1140     PixelData
& data 
= (PixelData 
&)dataBase
; 
1144         // invalid data, don't crash -- but don't assert neither as we're 
1145         // called automatically from wxPixelDataBase dtor and so there is no 
1146         // way to prevent this from happening 
1150     if ( GetBitmapData()->m_hasAlpha 
) 
1152         // AlphaBlend() wants to have premultiplied source alpha but 
1153         // wxRawBitmap API uses normal, not premultiplied, colours, so adjust 
1155         PixelData::Iterator 
p(data
); 
1157         const int w 
= data
.GetWidth(); 
1158         const int h 
= data
.GetHeight(); 
1160         for ( int y 
= 0; y 
< h
; y
++ ) 
1162             PixelData::Iterator rowStart 
= p
; 
1164             for ( int x 
= 0; x 
< w
; x
++ ) 
1166                 const unsigned alpha 
= p
.Alpha(); 
1168                 p
.Red() = (p
.Red() * alpha 
+ 127) / 255; 
1169                 p
.Blue() = (p
.Blue() * alpha 
+ 127) / 255; 
1170                 p
.Green() = (p
.Green() * alpha 
+ 127) / 255; 
1180     // if we're a DDB we need to convert DIB back to DDB now to make the 
1181     // changes made via raw bitmap access effective 
1182     if ( !GetBitmapData()->m_isDIB 
) 
1184         wxDIB 
*dib 
= GetBitmapData()->m_dib
; 
1185         GetBitmapData()->m_dib 
= NULL
; 
1191 #endif // wxUSE_WXDIB 
1193 #endif // #ifdef wxHAVE_RAW_BITMAP 
1195 // ---------------------------------------------------------------------------- 
1197 // ---------------------------------------------------------------------------- 
1204 // Construct a mask from a bitmap and a colour indicating 
1205 // the transparent area 
1206 wxMask::wxMask(const wxBitmap
& bitmap
, const wxColour
& colour
) 
1209     Create(bitmap
, colour
); 
1212 // Construct a mask from a bitmap and a palette index indicating 
1213 // the transparent area 
1214 wxMask::wxMask(const wxBitmap
& bitmap
, int paletteIndex
) 
1217     Create(bitmap
, paletteIndex
); 
1220 // Construct a mask from a mono bitmap (copies the bitmap). 
1221 wxMask::wxMask(const wxBitmap
& bitmap
) 
1230         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1233 // Create a mask from a mono bitmap (copies the bitmap). 
1234 bool wxMask::Create(const wxBitmap
& bitmap
) 
1236 #ifndef __WXMICROWIN__ 
1237     wxCHECK_MSG( bitmap
.Ok() && bitmap
.GetDepth() == 1, FALSE
, 
1238                  _T("can't create mask from invalid or not monochrome bitmap") ); 
1242         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1246     m_maskBitmap 
= (WXHBITMAP
) CreateBitmap( 
1251     HDC srcDC 
= CreateCompatibleDC(0); 
1252     SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP()); 
1253     HDC destDC 
= CreateCompatibleDC(0); 
1254     SelectObject(destDC
, (HBITMAP
) m_maskBitmap
); 
1255     BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
); 
1256     SelectObject(srcDC
, 0); 
1258     SelectObject(destDC
, 0); 
1266 // Create a mask from a bitmap and a palette index indicating 
1267 // the transparent area 
1268 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
) 
1272         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1277     if (bitmap
.Ok() && bitmap
.GetPalette()->Ok()) 
1279         unsigned char red
, green
, blue
; 
1280         if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
)) 
1282             wxColour 
transparentColour(red
, green
, blue
); 
1283             return Create(bitmap
, transparentColour
); 
1286 #endif // wxUSE_PALETTE 
1291 // Create a mask from a bitmap and a colour indicating 
1292 // the transparent area 
1293 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
) 
1295 #ifndef __WXMICROWIN__ 
1296     wxCHECK_MSG( bitmap
.Ok(), FALSE
, _T("invalid bitmap in wxMask::Create") ); 
1300         ::DeleteObject((HBITMAP
) m_maskBitmap
); 
1304     int width 
= bitmap
.GetWidth(), 
1305         height 
= bitmap
.GetHeight(); 
1307     // scan the bitmap for the transparent colour and set the corresponding 
1308     // pixels in the mask to BLACK and the rest to WHITE 
1309     COLORREF maskColour 
= wxColourToPalRGB(colour
); 
1310     m_maskBitmap 
= (WXHBITMAP
)::CreateBitmap(width
, height
, 1, 1, 0); 
1312     HDC srcDC 
= ::CreateCompatibleDC(NULL
); 
1313     HDC destDC 
= ::CreateCompatibleDC(NULL
); 
1314     if ( !srcDC 
|| !destDC 
) 
1316         wxLogLastError(wxT("CreateCompatibleDC")); 
1321     // SelectObject() will fail 
1322     wxASSERT_MSG( !bitmap
.GetSelectedInto(), 
1323                   _T("bitmap can't be selected in another DC") ); 
1325     HGDIOBJ hbmpSrcOld 
= ::SelectObject(srcDC
, GetHbitmapOf(bitmap
)); 
1328         wxLogLastError(wxT("SelectObject")); 
1333     HGDIOBJ hbmpDstOld 
= ::SelectObject(destDC
, (HBITMAP
)m_maskBitmap
); 
1336         wxLogLastError(wxT("SelectObject")); 
1343         // this will create a monochrome bitmap with 0 points for the pixels 
1344         // which have the same value as the background colour and 1 for the 
1346         ::SetBkColor(srcDC
, maskColour
); 
1347         ::BitBlt(destDC
, 0, 0, width
, height
, srcDC
, 0, 0, NOTSRCCOPY
); 
1350     ::SelectObject(srcDC
, hbmpSrcOld
); 
1352     ::SelectObject(destDC
, hbmpDstOld
); 
1356 #else // __WXMICROWIN__ 
1358 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
1361 // ---------------------------------------------------------------------------- 
1363 // ---------------------------------------------------------------------------- 
1365 bool wxBitmapHandler::Create(wxGDIImage 
*image
, 
1368                              int width
, int height
, int depth
) 
1370     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1372     return bitmap 
? Create(bitmap
, data
, flags
, width
, height
, depth
) : FALSE
; 
1375 bool wxBitmapHandler::Load(wxGDIImage 
*image
, 
1376                            const wxString
& name
, 
1378                            int width
, int height
) 
1380     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1382     return bitmap 
? LoadFile(bitmap
, name
, flags
, width
, height
) : FALSE
; 
1385 bool wxBitmapHandler::Save(wxGDIImage 
*image
, 
1386                            const wxString
& name
, 
1389     wxBitmap 
*bitmap 
= wxDynamicCast(image
, wxBitmap
); 
1391     return bitmap 
? SaveFile(bitmap
, name
, type
) : FALSE
; 
1394 bool wxBitmapHandler::Create(wxBitmap 
*WXUNUSED(bitmap
), 
1395                              void *WXUNUSED(data
), 
1396                              long WXUNUSED(type
), 
1397                              int WXUNUSED(width
), 
1398                              int WXUNUSED(height
), 
1399                              int WXUNUSED(depth
)) 
1404 bool wxBitmapHandler::LoadFile(wxBitmap 
*WXUNUSED(bitmap
), 
1405                                const wxString
& WXUNUSED(name
), 
1406                                long WXUNUSED(type
), 
1407                                int WXUNUSED(desiredWidth
), 
1408                                int WXUNUSED(desiredHeight
)) 
1413 bool wxBitmapHandler::SaveFile(wxBitmap 
*WXUNUSED(bitmap
), 
1414                                const wxString
& WXUNUSED(name
), 
1416                                const wxPalette 
*WXUNUSED(palette
)) 
1421 // ---------------------------------------------------------------------------- 
1423 // ---------------------------------------------------------------------------- 
1425 #ifndef __WXMICROWIN__ 
1426 bool wxCreateDIB(long xSize
, long ySize
, long bitsPerPixel
, 
1427                  HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
) 
1429    unsigned long   i
, headerSize
; 
1431    // Allocate space for a DIB header 
1432    headerSize 
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
))); 
1433    LPBITMAPINFO lpDIBheader 
= (BITMAPINFO 
*) malloc(headerSize
); 
1434    LPPALETTEENTRY lpPe 
= (PALETTEENTRY 
*)((BYTE
*)lpDIBheader 
+ sizeof(BITMAPINFOHEADER
)); 
1436    GetPaletteEntries(hPal
, 0, 256, lpPe
); 
1438    memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
)); 
1440    // Fill in the static parts of the DIB header 
1441    lpDIBheader
->bmiHeader
.biSize 
= sizeof(BITMAPINFOHEADER
); 
1442    lpDIBheader
->bmiHeader
.biWidth 
= xSize
; 
1443    lpDIBheader
->bmiHeader
.biHeight 
= ySize
; 
1444    lpDIBheader
->bmiHeader
.biPlanes 
= 1; 
1446    // this value must be 1, 4, 8 or 24 so PixelDepth can only be 
1447    lpDIBheader
->bmiHeader
.biBitCount 
= (WORD
)(bitsPerPixel
); 
1448    lpDIBheader
->bmiHeader
.biCompression 
= BI_RGB
; 
1449    lpDIBheader
->bmiHeader
.biSizeImage 
= xSize 
* abs(ySize
) * bitsPerPixel 
>> 3; 
1450    lpDIBheader
->bmiHeader
.biClrUsed 
= 256; 
1453    // Initialize the DIB palette 
1454    for (i 
= 0; i 
< 256; i
++) { 
1455       lpDIBheader
->bmiColors
[i
].rgbReserved 
= lpPe
[i
].peFlags
; 
1456       lpDIBheader
->bmiColors
[i
].rgbRed 
= lpPe
[i
].peRed
; 
1457       lpDIBheader
->bmiColors
[i
].rgbGreen 
= lpPe
[i
].peGreen
; 
1458       lpDIBheader
->bmiColors
[i
].rgbBlue 
= lpPe
[i
].peBlue
; 
1461    *lpDIBHeader 
= lpDIBheader
; 
1466 void wxFreeDIB(LPBITMAPINFO lpDIBHeader
) 
1472 // ---------------------------------------------------------------------------- 
1473 // global helper functions implemented here 
1474 // ---------------------------------------------------------------------------- 
1476 // helper of wxBitmapToHICON/HCURSOR 
1478 HICON 
wxBitmapToIconOrCursor(const wxBitmap
& bmp
, 
1485         // we can't create an icon/cursor form nothing 
1489     wxMask 
*mask 
= bmp
.GetMask(); 
1492         // we must have a mask for an icon, so even if it's probably incorrect, 
1493         // do create it (grey is the "standard" transparent colour) 
1494         mask 
= new wxMask(bmp
, *wxLIGHT_GREY
); 
1498     wxZeroMemory(iconInfo
); 
1499     iconInfo
.fIcon 
= iconWanted
;  // do we want an icon or a cursor? 
1502         iconInfo
.xHotspot 
= hotSpotX
; 
1503         iconInfo
.yHotspot 
= hotSpotY
; 
1506     iconInfo
.hbmMask 
= wxInvertMask((HBITMAP
)mask
->GetMaskBitmap()); 
1507     iconInfo
.hbmColor 
= GetHbitmapOf(bmp
); 
1509     // black out the transparent area to preserve background colour, because 
1510     // Windows blits the original bitmap using SRCINVERT (XOR) after applying 
1511     // the mask to the dest rect. 
1513         MemoryHDC dcSrc
, dcDst
; 
1514         SelectInHDC 
selectMask(dcSrc
, (HBITMAP
)mask
->GetMaskBitmap()), 
1515                     selectBitmap(dcDst
, iconInfo
.hbmColor
); 
1517         if ( !::BitBlt(dcDst
, 0, 0, bmp
.GetWidth(), bmp
.GetHeight(), 
1518                        dcSrc
, 0, 0, SRCAND
) ) 
1520             wxLogLastError(_T("BitBlt")); 
1524     HICON hicon 
= ::CreateIconIndirect(&iconInfo
); 
1526     if ( !bmp
.GetMask() ) 
1528         // we created the mask, now delete it 
1532     // delete the inverted mask bitmap we created as well 
1533     ::DeleteObject(iconInfo
.hbmMask
); 
1538 HICON 
wxBitmapToHICON(const wxBitmap
& bmp
) 
1540     return wxBitmapToIconOrCursor(bmp
, TRUE
, 0, 0); 
1543 HCURSOR 
wxBitmapToHCURSOR(const wxBitmap
& bmp
, int hotSpotX
, int hotSpotY
) 
1545     return (HCURSOR
)wxBitmapToIconOrCursor(bmp
, FALSE
, hotSpotX
, hotSpotY
); 
1548 HBITMAP 
wxInvertMask(HBITMAP hbmpMask
, int w
, int h
) 
1550 #ifndef __WXMICROWIN__ 
1551     wxCHECK_MSG( hbmpMask
, 0, _T("invalid bitmap in wxInvertMask") ); 
1553     // get width/height from the bitmap if not given 
1557         ::GetObject(hbmpMask
, sizeof(BITMAP
), (LPVOID
)&bm
); 
1562     HDC hdcSrc 
= ::CreateCompatibleDC(NULL
); 
1563     HDC hdcDst 
= ::CreateCompatibleDC(NULL
); 
1564     if ( !hdcSrc 
|| !hdcDst 
) 
1566         wxLogLastError(wxT("CreateCompatibleDC")); 
1569     HBITMAP hbmpInvMask 
= ::CreateBitmap(w
, h
, 1, 1, 0); 
1572         wxLogLastError(wxT("CreateBitmap")); 
1575     HGDIOBJ srcTmp 
= ::SelectObject(hdcSrc
, hbmpMask
); 
1576     HGDIOBJ dstTmp 
= ::SelectObject(hdcDst
, hbmpInvMask
); 
1577     if ( !::BitBlt(hdcDst
, 0, 0, w
, h
, 
1581         wxLogLastError(wxT("BitBlt")); 
1585     SelectObject(hdcSrc
,srcTmp
); 
1586     SelectObject(hdcDst
,dstTmp
);