1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/bitmap.cpp 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  15 #include "wx/bitmap.h" 
  23     #include "wx/palette.h" 
  24     #include "wx/dcmemory.h" 
  30 #include "wx/os2/dc.h" 
  31 #include "wx/os2/private.h" 
  33 #include "wx/xpmdecod.h" 
  35 // ---------------------------------------------------------------------------- 
  37 // ---------------------------------------------------------------------------- 
  39 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
) 
  40 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
) 
  42 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
) 
  44 // ============================================================================ 
  46 // ============================================================================ 
  48 // ---------------------------------------------------------------------------- 
  50 // ---------------------------------------------------------------------------- 
  52 wxBitmapRefData::wxBitmapRefData() 
  55     m_pSelectedInto 
= NULL
; 
  58     m_hBitmap       
= (WXHBITMAP
) NULL
; 
  59 } // end of wxBitmapRefData::wxBitmapRefData 
  61 wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData 
&tocopy
) 
  63     m_nQuality 
= tocopy
.m_nQuality
; 
  64     m_pSelectedInto 
= NULL
;     // don't copy this 
  65     m_nNumColors    
= tocopy
.m_nNumColors
; 
  68     if (tocopy
.m_pBitmapMask
) 
  69         m_pBitmapMask 
= new wxMask(*tocopy
.m_pBitmapMask
); 
  71     m_hBitmap 
= wxCopyBmp(tocopy
.m_hBitmap
); 
  74 void wxBitmapRefData::Free() 
  76     if ( m_pSelectedInto 
) 
  78         wxLogLastError(wxT("GpiDeleteBitmap(hbitmap)")); 
  82         if (!::GpiDeleteBitmap((HBITMAP
)m_hBitmap
)) 
  84             wxLogLastError(wxT("GpiDeleteBitmap(hbitmap)")); 
  92 } // end of wxBitmapRefData::Free 
  94 // ---------------------------------------------------------------------------- 
  96 // ---------------------------------------------------------------------------- 
  98 wxGDIRefData
* wxBitmap::CloneGDIRefData(const wxGDIRefData
* data
) const 
 100     return new wxBitmapRefData(*static_cast<const wxBitmapRefData 
*>(data
)); 
 103 // this function should be called from all wxBitmap ctors 
 104 void wxBitmap::Init() 
 108     // True for all bitmaps created from bits, wxImages, Xpms 
 110 } // end of wxBitmap::Init 
 112 bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage
& rIcon
) 
 114     HPOINTER                        hIcon 
= (HPOINTER
)rIcon
.GetHandle(); 
 115     POINTERINFO                     SIconInfo
; 
 117     if (!::WinQueryPointerInfo(hIcon
, &SIconInfo
)) 
 119         wxLogLastError(wxT("WinQueryPointerInfo")); 
 122     wxBitmapRefData
*                pRefData 
= new wxBitmapRefData
; 
 124     m_refData 
= pRefData
; 
 126     int                             nWidth 
= rIcon
.GetWidth(); 
 127     int                             nHeight 
= rIcon
.GetHeight(); 
 129     pRefData
->m_nWidth  
= nWidth
; 
 130     pRefData
->m_nHeight 
= nHeight
; 
 131     pRefData
->m_nDepth  
= wxDisplayDepth(); 
 133     pRefData
->m_hBitmap 
= (WXHBITMAP
)SIconInfo
.hbmColor
; 
 135     wxMask
*                         pMask 
= new wxMask(SIconInfo
.hbmPointer
); 
 137     pMask
->SetMaskBitmap(GetHBITMAP()); 
 141 } // end of wxBitmap::CopyFromIconOrCursor 
 143 bool wxBitmap::CopyFromCursor( 
 144   const wxCursor
&                   rCursor
 
 151     return(CopyFromIconOrCursor(rCursor
)); 
 152 } // end of wxBitmap::CopyFromCursor 
 154 bool wxBitmap::CopyFromIcon( 
 163     return CopyFromIconOrCursor(rIcon
); 
 164 } // end of wxBitmap::CopyFromIcon 
 166 wxBitmap::~wxBitmap() 
 168 } // end of wxBitmap::~wxBitmap 
 179     wxBitmapRefData
*                pRefData 
= new wxBitmapRefData
; 
 180     BITMAPINFOHEADER2               vHeader
; 
 184     DEVOPENSTRUC                    vDop 
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL 
}; 
 185     SIZEL                           vSize 
= {0, 0}; 
 188     wxASSERT(vHabmain 
!= NULL
); 
 190     m_refData 
= pRefData
; 
 192     pRefData
->m_nWidth        
= nWidth
; 
 193     pRefData
->m_nHeight       
= nHeight
; 
 194     pRefData
->m_nDepth        
= nDepth
; 
 195     pRefData
->m_nNumColors    
= 0; 
 196     pRefData
->m_pSelectedInto 
= NULL
; 
 198     hDc   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
 199     hPs 
= ::GpiCreatePS(vHabmain
, hDc
, &vSize
, GPIA_ASSOC 
| PU_PELS
); 
 202         wxLogLastError(wxT("GpiCreatePS Failure")); 
 208         // We assume that it is in XBM format which is not quite the same as 
 209         // the format CreateBitmap() wants because the order of bytes in the 
 212         const size_t                nBytesPerLine 
= (nWidth 
+ 7) / 8; 
 213         const size_t                nPadding 
= nBytesPerLine 
% 2; 
 214         const size_t                nLen 
= nHeight 
* (nPadding 
+ nBytesPerLine
); 
 215         const char*                 pzSrc 
= zBits
; 
 219         pzData 
= (char *)malloc(nLen
); 
 221         char*                       pzDst 
= pzData
; 
 223         for (nRows 
= 0; nRows 
< nHeight
; nRows
++) 
 225             for (nCols 
= 0; nCols 
< nBytesPerLine
; nCols
++) 
 227                 unsigned char ucVal 
= *pzSrc
++; 
 228                 unsigned char ucReversed 
= 0; 
 231                 for (nBits 
= 0; nBits 
< 8; nBits
++) 
 234                     ucReversed 
= (unsigned char)(ucReversed 
| (ucVal 
& 0x01)); 
 237                 *pzDst
++ = ucReversed
; 
 246         // Bits should already be in Windows standard format 
 248         pzData 
= (char *)zBits
;    // const_cast is harmless 
 252         nDepth 
= 24; // MAX supported in PM 
 253     memset(&vHeader
, '\0', 16); 
 255     vHeader
.cx              
= (USHORT
)nWidth
; 
 256     vHeader
.cy              
= (USHORT
)nHeight
; 
 257     vHeader
.cPlanes         
= 1L; 
 258     vHeader
.cBitCount       
= (USHORT
)nDepth
; 
 259     vHeader
.usReserved      
= 0; 
 261     memset(&vInfo
, '\0', 16); 
 263     vInfo
.cx              
= (USHORT
)nWidth
; 
 264     vInfo
.cy              
= (USHORT
)nHeight
; 
 266     vInfo
.cBitCount       
= (USHORT
)nDepth
; 
 268     HBITMAP                         hBmp 
= ::GpiCreateBitmap(hPs
, &vHeader
, CBM_INIT
, (PBYTE
)pzData
, &vInfo
); 
 272         wxLogLastError(wxT("CreateBitmap")); 
 276     SetHBITMAP((WXHBITMAP
)hBmp
); 
 277 } // end of wxBitmap::wxBitmap 
 290 } // end of wxBitmap::wxBitmap 
 308 } // end of wxBitmap::wxBitmap 
 320 } // end of wxBitmap::wxBitmap 
 322 bool wxBitmap::Create( 
 329     BITMAPINFOHEADER2               vHeader
; 
 331     wxASSERT(vHabmain 
!= NULL
); 
 333     m_refData 
= new wxBitmapRefData
; 
 334     GetBitmapData()->m_nWidth 
= nW
; 
 335     GetBitmapData()->m_nHeight 
= nH
; 
 336     GetBitmapData()->m_nDepth 
= nD
; 
 339     // Xpms and bitmaps from other images can also be mono's, but only 
 340     // mono's need help changing their colors with MemDC changes 
 344         DEVOPENSTRUC                vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 345         SIZEL                       vSize 
= {0, 0}; 
 346         HDC                         hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
 347         HPS                         hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
 351         memset(&vHeader
, '\0', 16); 
 356         vHeader
.cBitCount 
= 24; //nD; 
 358         hBmp 
= ::GpiCreateBitmap( hPS
 
 373         hPSScreen 
= ::WinGetScreenPS(HWND_DESKTOP
); 
 374         hDCScreen 
= ::GpiQueryDevice(hPSScreen
); 
 375         ::DevQueryCaps(hDCScreen
, CAPS_COLOR_BITCOUNT
, 1L, &lBitCount
); 
 380         memset(&vHeader
, '\0', 16); 
 385         vHeader
.cBitCount 
= (USHORT
)lBitCount
; 
 387         hBmp 
= ::GpiCreateBitmap( hPSScreen
 
 394         GetBitmapData()->m_nDepth 
= wxDisplayDepth(); 
 395         ::WinReleasePS(hPSScreen
); 
 397     SetHBITMAP((WXHBITMAP
)hBmp
); 
 400 } // end of wxBitmap::Create 
 402 bool wxBitmap::LoadFile(const wxString
& filename
, wxBitmapType type
) 
 406     wxBitmapHandler 
*handler 
= wxDynamicCast(FindHandler(type
), wxBitmapHandler
); 
 410         m_refData 
= new wxBitmapRefData
; 
 412         return handler
->LoadFile(this, filename
, type
, -1, -1); 
 415     else // no bitmap handler found 
 418         if ( image
.LoadFile( filename
, type 
) && image
.Ok() ) 
 420             *this = wxBitmap(image
); 
 425 #endif // wxUSE_IMAGE 
 430 bool wxBitmap::LoadFile( 
 437     wxBitmapHandler
*                pHandler 
= wxDynamicCast( FindHandler(lType
) 
 443         m_refData 
= new wxBitmapRefData
; 
 445         return(pHandler
->LoadFile( this 
 456 } // end of wxBitmap::LoadFile 
 458 bool wxBitmap::Create( 
 468     wxBitmapHandler
*                pHandler 
= wxDynamicCast( FindHandler(lType
) 
 474         wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for type %ld defined."), lType
); 
 479     m_refData 
= new wxBitmapRefData
; 
 481     return(pHandler
->Create( this 
 488 } // end of wxBitmap::Create 
 490 bool wxBitmap::SaveFile( 
 491   const wxString
&                   rFilename
 
 493 , const wxPalette
*                  pPalette
 
 496     wxBitmapHandler
*                pHandler 
= wxDynamicCast( FindHandler(lType
) 
 502         return pHandler
->SaveFile( this 
 510         // FIXME what about palette? shouldn't we use it? 
 511         wxImage                     vImage 
= ConvertToImage(); 
 516         return(vImage
.SaveFile( rFilename
 
 520 } // end of wxBitmap::SaveFile 
 523 // ---------------------------------------------------------------------------- 
 524 // wxImage-wxBitmap conversion 
 525 // ---------------------------------------------------------------------------- 
 527 bool wxBitmap::CreateFromImage ( 
 528   const wxImage
&                    rImage
 
 532     wxCHECK_MSG(rImage
.Ok(), false, wxT("invalid image")); 
 533     m_refData 
= new wxBitmapRefData(); 
 535     int                             nSizeLimit 
= 1024 * 768 * 3; 
 536     int                             nWidth 
= rImage
.GetWidth(); 
 537     int                             nBmpHeight 
= rImage
.GetHeight(); 
 538     int                             nBytePerLine 
= nWidth 
* 3; 
 539     int                             nSizeDWORD 
= sizeof(DWORD
); 
 540     int                             nLineBoundary 
= nBytePerLine 
% nSizeDWORD
; 
 543     if (nLineBoundary 
> 0) 
 545         nPadding 
= nSizeDWORD 
- nLineBoundary
; 
 546         nBytePerLine 
+= nPadding
; 
 550     // Calc the number of DIBs and heights of DIBs 
 554     int                             nHeight 
= nSizeLimit 
/ nBytePerLine
; 
 556     if (nHeight 
>= nBmpHeight
) 
 557         nHeight 
= nBmpHeight
; 
 560         nNumDIB  
= nBmpHeight 
/ nHeight
; 
 561         nHRemain 
= nBmpHeight 
% nHeight
; 
 567     // Set bitmap parameters 
 569     wxCHECK_MSG(rImage
.Ok(), false, wxT("invalid image")); 
 571     SetHeight(nBmpHeight
); 
 577         nDepth 
= wxDisplayDepth(); 
 582     // Copy the palette from the source image 
 584     SetPalette(rImage
.GetPalette()); 
 585 #endif // wxUSE_PALETTE 
 588     // Create a DIB header 
 590     BITMAPINFOHEADER2               vHeader
; 
 594     // Fill in the DIB header 
 596     memset(&vHeader
, '\0', 16); 
 598     vHeader
.cx              
= (ULONG
)nWidth
; 
 599     vHeader
.cy              
= (ULONG
)nHeight
; 
 600     vHeader
.cPlanes         
= 1L; 
 601     vHeader
.cBitCount       
= 24; 
 604     // Memory for DIB data 
 606     unsigned char*                  pucBits
; 
 608     pucBits 
= (unsigned char *)malloc(nBytePerLine 
* nHeight
); 
 611         wxFAIL_MSG(wxT("could not allocate memory for DIB")); 
 614     memset(pucBits
, '\0', (nBytePerLine 
* nHeight
)); 
 617     // Create and set the device-dependent bitmap 
 619     DEVOPENSTRUC                    vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 620     SIZEL                           vSize 
= {0, 0}; 
 621     HDC                             hDC   
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
 622     HPS                             hPS   
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
 624     HDC                             hDCScreen 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
 629     memset(&vInfo
, '\0', 16); 
 631     vInfo
.cx              
= (ULONG
)nWidth
; 
 632     vInfo
.cy              
= (ULONG
)nHeight
; 
 634     vInfo
.cBitCount       
= 24; // Set to desired count going in 
 636     hBmp 
= ::GpiCreateBitmap( hPS
 
 643     HPAL                            hOldPalette 
= NULLHANDLE
; 
 644     if (rImage
.GetPalette().Ok()) 
 646         hOldPalette 
= ::GpiSelectPalette(hPS
, (HPAL
)rImage
.GetPalette().GetHPALETTE()); 
 648 #endif // wxUSE_PALETTE 
 651     // Copy image data into DIB data and then into DDB (in a loop) 
 653     unsigned char*                  pData 
= rImage
.GetData(); 
 658     unsigned char*                  ptdata 
= pData
; 
 659     unsigned char*                  ptbits
; 
 661     if ((hBmpOld 
= ::GpiSetBitmap(hPS
, hBmp
)) == HBM_ERROR
) 
 666         vError 
= ::WinGetLastError(vHabmain
); 
 667         sError 
= wxPMErrorToStr(vError
); 
 669     for (n 
= 0; n 
< nNumDIB
; n
++) 
 671         if (nNumDIB 
> 1 && n 
== nNumDIB 
- 1 && nHRemain 
> 0) 
 674             // Redefine height and size of the (possibly) last smaller DIB 
 675             // memory is not reallocated 
 678             vHeader
.cy      
= (DWORD
)(nHeight
); 
 679             vHeader
.cbImage 
= nBytePerLine 
* nHeight
; 
 682         for (j 
= 0; j 
< nHeight
; j
++) 
 684             for (i 
= 0; i 
< nWidth
; i
++) 
 686                 *(ptbits
++) = *(ptdata 
+ 2); 
 687                 *(ptbits
++) = *(ptdata 
+ 1); 
 688                 *(ptbits
++) = *(ptdata
); 
 691             for (i 
= 0; i 
< nPadding
; i
++) 
 696         // Have to do something similar to WIN32's StretchDIBits, use GpiBitBlt 
 697         // in combination with setting the bits into the selected bitmap 
 699         if ((lScans 
= ::GpiSetBitmapBits( hPS
 
 700                                          ,0             // Start at the bottom 
 701                                          ,(LONG
)nHeight 
// One line per scan 
 709             vError 
= ::WinGetLastError(vHabmain
); 
 710             sError 
= wxPMErrorToStr(vError
); 
 712         hPSScreen 
= ::GpiCreatePS( vHabmain
 
 715                                   ,PU_PELS 
| GPIA_ASSOC
 
 718         POINTL                      vPoint
[4] = { {0, nOrigin
}, 
 720                                                   {0, 0}, {nWidth
, nHeight
} 
 724         ::GpiBitBlt( hPSScreen
 
 731         ::GpiDestroyPS(hPSScreen
); 
 734     SetHBITMAP((WXHBITMAP
)hBmp
); 
 737         ::GpiSelectPalette(hPS
, hOldPalette
); 
 738 #endif // wxUSE_PALETTE 
 741     // Similarly, created an mono-bitmap for the possible mask 
 743     if (rImage
.HasMask()) 
 747         vHeader
.cy        
= nHeight
; 
 749         vHeader
.cBitCount 
= 24; 
 750         hBmp 
= ::GpiCreateBitmap( hPS
 
 756         hBmpOld 
= ::GpiSetBitmap(hPS
, hBmp
); 
 758             nHeight 
= nBmpHeight
; 
 760             nHeight 
= nSizeLimit 
/ nBytePerLine
; 
 761         vHeader
.cy 
= (DWORD
)(nHeight
); 
 764         unsigned char               cRed   
= rImage
.GetMaskRed(); 
 765         unsigned char               cGreen 
= rImage
.GetMaskGreen(); 
 766         unsigned char               cBlue  
= rImage
.GetMaskBlue(); 
 767         unsigned char               cZero 
= 0; 
 768         unsigned char               cOne 
= 255; 
 771         for (n 
= 0; n 
< nNumDIB
; n
++) 
 773             if (nNumDIB 
> 1 && n 
== nNumDIB 
- 1 && nHRemain 
> 0) 
 776                 // Redefine height and size of the (possibly) last smaller DIB 
 777                 // memory is not reallocated 
 780                 vHeader
.cy      
= (DWORD
)(nHeight
); 
 781                 vHeader
.cbImage 
= nBytePerLine 
* nHeight
; 
 784             for (int j 
= 0; j 
< nHeight
; j
++) 
 786                 for (i 
= 0; i 
< nWidth
; i
++) 
 788                     unsigned char cRedImage   
= (*(ptdata
++)) ; 
 789                     unsigned char cGreenImage 
= (*(ptdata
++)) ; 
 790                     unsigned char cBlueImage  
= (*(ptdata
++)) ; 
 792                     if ((cRedImage 
!= cRed
) || (cGreenImage 
!= cGreen
) || (cBlueImage 
!= cBlue
)) 
 805                 for (i 
= 0; i 
< nPadding
; i
++) 
 808             lScans 
= ::GpiSetBitmapBits( hPS
 
 809                                         ,0              // Start at the bottom 
 810                                         ,(LONG
)nHeight 
// One line per scan 
 814             hPSScreen 
= ::GpiCreatePS( vHabmain
 
 817                                       ,PU_PELS 
| GPIA_ASSOC
 
 819             POINTL vPoint2
[4] = { {0, nOrigin
}, 
 821                                   {0, 0}, {nWidth
, nHeight
} 
 823             ::GpiBitBlt( hPSScreen
 
 830             ::GpiDestroyPS(hPSScreen
); 
 835         // Create a wxMask object 
 837         wxMask
*                     pMask 
= new wxMask(); 
 839         pMask
->SetMaskBitmap((WXHBITMAP
)hBmp
); 
 841         hBmpOld 
= ::GpiSetBitmap(hPS
, hBmpOld
); 
 845     // Free allocated resources 
 847     ::GpiSetBitmap(hPS
, NULLHANDLE
); 
 849     ::DevCloseDC(hDCScreen
); 
 853 } // end of wxBitmap::CreateFromImage 
 855 wxImage 
wxBitmap::ConvertToImage() const 
 860     wxCHECK_MSG( Ok(), wxNullImage
, wxT("invalid bitmap") ); 
 863     // Create an wxImage object 
 865     int                             nWidth        
= GetWidth(); 
 866     int                             nHeight       
= GetHeight(); 
 869     int                             nBytePerLine  
= nWidth 
* 3; 
 870     int                             nSizeDWORD    
= sizeof(DWORD
); 
 871     int                             nLineBoundary 
= nBytePerLine 
% nSizeDWORD
; 
 873     unsigned char*                  pData
; 
 874     unsigned char*                  lpBits
; 
 876     BITMAPINFOHEADER2               vDIBh
; 
 877     BITMAPINFO2                     vDIBInfo
; 
 881     DEVOPENSTRUC                    vDop  
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 882     SIZEL                           vSizlPage 
= {0,0}; 
 883     HDC                             hDCMem 
= NULLHANDLE
; 
 885     vImage
.Create( nWidth
 
 888     pData 
= vImage
.GetData(); 
 891         wxFAIL_MSG( wxT("could not allocate data for image") ); 
 894     if(nLineBoundary 
> 0) 
 896         nPadding     
= nSizeDWORD 
- nLineBoundary
; 
 897         nBytePerLine 
+= nPadding
; 
 899     wxDisplaySize( &nDevWidth
 
 903     // Create and fill a DIB header 
 905     memset(&vDIBh
, '\0', 16); 
 910     vDIBh
.cBitCount 
= 24; 
 912     memset(&vDIBInfo
, '\0', 16); 
 914     vDIBInfo
.cx              
= nWidth
; 
 915     vDIBInfo
.cy              
= nHeight
; 
 916     vDIBInfo
.cPlanes         
= 1; 
 917     vDIBInfo
.cBitCount       
= 24; 
 919     lpBits 
= (unsigned char *)malloc(nBytePerLine 
* nHeight
); 
 922         wxFAIL_MSG(wxT("could not allocate data for DIB")); 
 926     memset(lpBits
, '\0', (nBytePerLine 
* nHeight
)); 
 927     hBitmap 
= (HBITMAP
)GetHBITMAP(); 
 930     // May already be selected into a PS 
 932     pDC 
= GetSelectedInto(); 
 933     const wxPMDCImpl 
*impl
;  
 935         (impl 
= wxDynamicCast( pDC
->GetImpl(), wxPMDCImpl 
)) != NULL
) 
 937         hPSMem 
= impl
->GetHPS(); 
 941         hDCMem 
= ::DevOpenDC( vHabmain
 
 948         hPSMem 
= ::GpiCreatePS( vHabmain
 
 951                                ,PU_PELS 
| GPIA_ASSOC
 
 954     if ((hOldBitmap 
= ::GpiSetBitmap(hPSMem
, hBitmap
)) == HBM_ERROR
) 
 959         vError 
= ::WinGetLastError(vHabmain
); 
 960         sError 
= wxPMErrorToStr(vError
); 
 964     // Copy data from the device-dependent bitmap to the DIB 
 966     if ((lScans 
= ::GpiQueryBitmapBits( hPSMem
 
 976         vError 
= ::WinGetLastError(vHabmain
); 
 977         sError 
= wxPMErrorToStr(vError
); 
 981     // Copy DIB data into the wxImage object 
 985     unsigned char*                  ptdata 
= pData
; 
 986     unsigned char*                  ptbits 
= lpBits
; 
 988     for (i 
= 0; i 
< nHeight
; i
++) 
 990         for (j 
= 0; j 
< nWidth
; j
++) 
 992             *(ptdata
++) = *(ptbits
+2); 
 993             *(ptdata
++) = *(ptbits
+1); 
 994             *(ptdata
++) = *(ptbits  
); 
 999     if ((pDC 
= GetSelectedInto()) == NULL
) 
1001         ::GpiSetBitmap(hPSMem
, NULLHANDLE
); 
1002         ::GpiDestroyPS(hPSMem
); 
1003         ::DevCloseDC(hDCMem
); 
1007     // Similarly, set data according to the possible mask bitmap 
1009     if (GetMask() && GetMask()->GetMaskBitmap()) 
1011         hBitmap 
= (HBITMAP
)GetMask()->GetMaskBitmap(); 
1014         // Memory DC/PS created, color set, data copied, and memory DC/PS deleted 
1016         HDC                        hMemDC 
= ::DevOpenDC( vHabmain
 
1020                                                         ,(PDEVOPENDATA
)&vDop
 
1023         HPS                         hMemPS 
= ::GpiCreatePS( vHabmain
 
1026                                                            ,PU_PELS 
| GPIA_ASSOC
 
1028         ::GpiSetColor(hMemPS
, OS2RGB(0, 0, 0)); 
1029         ::GpiSetBackColor(hMemPS
, OS2RGB(255, 255, 255) ); 
1030         ::GpiSetBitmap(hMemPS
, hBitmap
); 
1031         ::GpiQueryBitmapBits( hPSMem
 
1037         ::GpiSetBitmap(hMemPS
, NULLHANDLE
); 
1038         ::GpiDestroyPS(hMemPS
); 
1039         ::DevCloseDC(hMemDC
); 
1042         // Background color set to RGB(16,16,16) in consistent with wxGTK 
1044         unsigned char               ucRed 
= 16; 
1045         unsigned char               ucGreen 
= 16; 
1046         unsigned char               ucBlue 
= 16; 
1050         for (i 
= 0; i 
< nHeight
; i
++) 
1052             for (j 
= 0; j 
< nWidth
; j
++) 
1058                     *(ptdata
++)  = ucRed
; 
1059                     *(ptdata
++)  = ucGreen
; 
1060                     *(ptdata
++)  = ucBlue
; 
1066         vImage
.SetMaskColour( ucRed
 
1070         vImage
.SetMask(true); 
1074         vImage
.SetMask(false); 
1078     // Free allocated resources 
1082 } // end of wxBitmap::ConvertToImage 
1084 // ---------------------------------------------------------------------------- 
1085 // sub bitmap extraction 
1086 // ---------------------------------------------------------------------------- 
1088 wxBitmap 
wxBitmap::GetSubBitmap( 
1092     wxCHECK_MSG( Ok() && 
1093                  (rRect
.x 
>= 0) && (rRect
.y 
>= 0) && 
1094                  (rRect
.x 
+ rRect
.width 
<= GetWidth()) && 
1095                  (rRect
.y 
+ rRect
.height 
<= GetHeight()), 
1096                  wxNullBitmap
, wxT("Invalid bitmap or bitmap region") ); 
1098     wxBitmap                        
vRet( rRect
.width
 
1102     wxASSERT_MSG( vRet
.Ok(), wxT("GetSubBitmap error") ); 
1108     SIZEL                           vSize 
= {0, 0}; 
1109     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1110     HDC                             hDCSrc 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1111     HDC                             hDCDst 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1112     HPS                             hPSSrc 
= ::GpiCreatePS(vHabmain
, hDCSrc
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1113     HPS                             hPSDst 
= ::GpiCreatePS(vHabmain
, hDCDst
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1114     POINTL                          vPoint
[4] = { {0, 0}, {rRect
.width
, rRect
.height
}, 
1116                                                   {rRect
.x 
+ rRect
.width
, rRect
.y 
+ rRect
.height
} 
1119     ::GpiSetBitmap(hPSSrc
, (HBITMAP
) GetHBITMAP()); 
1120     ::GpiSetBitmap(hPSDst
, (HBITMAP
) vRet
.GetHBITMAP()); 
1130     // Copy mask if there is one 
1134         BITMAPINFOHEADER2           vBmih
; 
1136         memset(&vBmih
, '\0', sizeof(BITMAPINFOHEADER2
)); 
1137         vBmih
.cbFix     
= sizeof(BITMAPINFOHEADER2
); 
1138         vBmih
.cx        
= rRect
.width
; 
1139         vBmih
.cy        
= rRect
.height
; 
1141         vBmih
.cBitCount 
= 24; 
1143         HBITMAP                     hBmpMask 
= ::GpiCreateBitmap( hPSDst
 
1150         ::GpiSetBitmap(hPSSrc
, (HBITMAP
) GetHBITMAP()); 
1151         ::GpiSetBitmap(hPSDst
, (HBITMAP
) vRet
.GetHBITMAP()); 
1153         ::GpiSetBitmap(hPSSrc
, (HBITMAP
) GetMask()->GetMaskBitmap()); 
1154         ::GpiSetBitmap(hPSDst
, (HBITMAP
) hBmpMask
); 
1163         wxMask
*                     pMask 
= new wxMask((WXHBITMAP
)hBmpMask
); 
1164         vRet
.SetMask(pMask
); 
1167     ::GpiSetBitmap(hPSSrc
, NULL
); 
1168     ::GpiSetBitmap(hPSDst
, NULL
); 
1169     ::GpiDestroyPS(hPSSrc
); 
1170     ::GpiDestroyPS(hPSDst
); 
1171     ::DevCloseDC(hDCSrc
); 
1172     ::DevCloseDC(hDCDst
); 
1174 } // end of wxBitmap::GetSubBitmap 
1176 // ---------------------------------------------------------------------------- 
1177 // wxBitmap accessors 
1178 // ---------------------------------------------------------------------------- 
1180 void wxBitmap::SetQuality( 
1186     GetBitmapData()->m_nQuality 
= nQ
; 
1187 } // end of wxBitmap::SetQuality 
1189 void wxBitmap::SetPalette( 
1190   const wxPalette
&                  rPalette
 
1195     GetBitmapData()->m_vBitmapPalette 
= rPalette
; 
1196 } // end of wxBitmap::SetPalette 
1198 void wxBitmap::SetMask( 
1204     GetBitmapData()->m_pBitmapMask 
= pMask
; 
1205 } // end of wxBitmap::SetMask 
1207 wxBitmap 
wxBitmap::GetBitmapForDC(wxDC
& WXUNUSED(rDc
)) const 
1210 } // end of wxBitmap::GetBitmapForDC 
1212 // ---------------------------------------------------------------------------- 
1214 // ---------------------------------------------------------------------------- 
1219 } // end of wxMask::wxMask 
1221 wxMask::wxMask(const wxMask
& tocopy
) 
1223     m_hMaskBitmap 
= wxCopyBmp(tocopy
.m_hMaskBitmap
); 
1224 } // end of wxMask::wxMask 
1226 // Construct a mask from a bitmap and a colour indicating 
1227 // the transparent area 
1229   const wxBitmap
&                   rBitmap
 
1230 , const wxColour
&                   rColour
 
1237 } // end of wxMask::wxMask 
1239 // Construct a mask from a bitmap and a palette index indicating 
1240 // the transparent area 
1242   const wxBitmap
&                   rBitmap
 
1250 } // end of wxMask::wxMask 
1252 // Construct a mask from a mono bitmap (copies the bitmap). 
1254   const wxBitmap
&                   rBitmap
 
1259 } // end of wxMask::wxMask 
1264         ::GpiDeleteBitmap((HBITMAP
)m_hMaskBitmap
); 
1265 } // end of wxMask::~wxMask 
1267 // Create a mask from a mono bitmap (copies the bitmap). 
1268 bool wxMask::Create( 
1269   const wxBitmap
&                   rBitmap
 
1272     BITMAPINFOHEADER2               vBmih
; 
1273     SIZEL                           vSize 
= {0, 0}; 
1274     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1275     HDC                             hDCSrc 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1276     HDC                             hDCDst 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1277     HPS                             hPSSrc 
= ::GpiCreatePS(vHabmain
, hDCSrc
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1278     HPS                             hPSDst 
= ::GpiCreatePS(vHabmain
, hDCDst
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1279     POINTL                          vPoint
[4] = { {0 ,0}, {rBitmap
.GetWidth(), rBitmap
.GetHeight()}, 
1280                                                   {0, 0}, {rBitmap
.GetWidth(), rBitmap
.GetHeight()} 
1285         ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
); 
1288     if (!rBitmap
.Ok() || rBitmap
.GetDepth() != 1) 
1293     memset(&vBmih
, '\0', sizeof(BITMAPINFOHEADER2
)); 
1294     vBmih
.cbFix     
=  sizeof(BITMAPINFOHEADER2
); 
1295     vBmih
.cx        
= rBitmap
.GetWidth(); 
1296     vBmih
.cy        
= rBitmap
.GetHeight(); 
1298     vBmih
.cBitCount 
= 24; 
1300     m_hMaskBitmap 
= ::GpiCreateBitmap( hPSDst
 
1307     ::GpiSetBitmap(hPSSrc
, (HBITMAP
) rBitmap
.GetHBITMAP()); 
1308     ::GpiSetBitmap(hPSDst
, (HBITMAP
) m_hMaskBitmap
); 
1317     ::GpiDestroyPS(hPSSrc
); 
1318     ::GpiDestroyPS(hPSDst
); 
1319     ::DevCloseDC(hDCSrc
); 
1320     ::DevCloseDC(hDCDst
); 
1322 } // end of wxMask::Create 
1324 // Create a mask from a bitmap and a palette index indicating 
1325 // the transparent area 
1326 bool wxMask::Create( 
1327   const wxBitmap
&                   rBitmap
 
1333         ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
); 
1336     if (rBitmap
.Ok() && rBitmap
.GetPalette()->Ok()) 
1339         unsigned char               cGreen
; 
1340         unsigned char               cBlue
; 
1342         if (rBitmap
.GetPalette()->GetRGB( nPaletteIndex
 
1348             wxColour                
vTransparentColour( cRed
 
1353             return (Create( rBitmap
 
1359 } // end of wxMask::Create 
1361 // Create a mask from a bitmap and a colour indicating 
1362 // the transparent area 
1363 bool wxMask::Create( 
1364   const wxBitmap
&                   rBitmap
 
1365 , const wxColour
&                   rColour
 
1369     COLORREF                        vMaskColour 
= OS2RGB( rColour
.Red() 
1373     BITMAPINFOHEADER2               vBmih
; 
1374     SIZEL                           vSize 
= {0, 0}; 
1375     DEVOPENSTRUC                    vDop 
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL 
}; 
1376     HDC                             hDCSrc 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1377     HDC                             hDCDst 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1378     HPS                             hPSSrc 
= ::GpiCreatePS(vHabmain
, hDCSrc
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1379     HPS                             hPSDst 
= ::GpiCreatePS(vHabmain
, hDCDst
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1383         ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
); 
1392     // Scan the bitmap for the transparent colour and set 
1393     // the corresponding pixels in the mask to BLACK and 
1394     // the rest to WHITE 
1397     memset(&vBmih
, '\0', sizeof(BITMAPINFOHEADER2
)); 
1398     vBmih
.cbFix     
=  sizeof(BITMAPINFOHEADER2
); 
1399     vBmih
.cx        
= rBitmap
.GetWidth(); 
1400     vBmih
.cy        
= rBitmap
.GetHeight(); 
1402     vBmih
.cBitCount 
= 1; 
1404     m_hMaskBitmap 
= ::GpiCreateBitmap( hPSDst
 
1411     ::GpiSetBitmap(hPSSrc
, (HBITMAP
) rBitmap
.GetHBITMAP()); 
1412     ::GpiSetBitmap(hPSDst
, (HBITMAP
) m_hMaskBitmap
); 
1415     // This is not very efficient, but I can't think 
1416     // of a better way of doing it 
1418     for (int w 
= 0; w 
< rBitmap
.GetWidth(); w
++) 
1420         for (int h 
= 0; h 
< rBitmap
.GetHeight(); h
++) 
1422             POINTL                  vPt 
= {w
, h
}; 
1423             COLORREF                vCol 
= (COLORREF
)::GpiQueryPel(hPSSrc
, &vPt
); 
1424             if (vCol 
== (COLORREF
)CLR_NOINDEX
) 
1427                 // Doesn't make sense to continue 
1433             if (vCol 
== vMaskColour
) 
1435                 ::GpiSetColor(hPSDst
, OS2RGB(0, 0, 0)); 
1436                 ::GpiSetPel(hPSDst
, &vPt
); 
1440                 ::GpiSetColor(hPSDst
, OS2RGB(255, 255, 255)); 
1441                 ::GpiSetPel(hPSDst
, &vPt
); 
1445     ::GpiSetBitmap(hPSSrc
, NULL
); 
1446     ::GpiSetBitmap(hPSDst
, NULL
); 
1447     ::GpiDestroyPS(hPSSrc
); 
1448     ::GpiDestroyPS(hPSDst
); 
1449     ::DevCloseDC(hDCSrc
); 
1450     ::DevCloseDC(hDCDst
); 
1452 } // end of wxMask::Create 
1454 // ---------------------------------------------------------------------------- 
1456 // ---------------------------------------------------------------------------- 
1458 bool wxBitmapHandler::Create( wxGDIImage
* pImage
, 
1465     wxBitmap
* pBitmap 
= wxDynamicCast( pImage
 
1469     return(pBitmap 
? Create( pBitmap
 
1478 bool wxBitmapHandler::Load( 
1481 , wxBitmapType                      lFlags
 
1486     wxBitmap
*                       pBitmap 
= wxDynamicCast( pImage
 
1490     return(pBitmap 
? LoadFile( pBitmap
 
1498 bool wxBitmapHandler::Save( 
1499   const wxGDIImage
*                 pImage
 
1500 , const wxString
&                   rName
 
1501 , wxBitmapType                      lType
 
1504     wxBitmap
*                       pBitmap 
= wxDynamicCast( pImage
 
1508     return(pBitmap 
? SaveFile( pBitmap
 
1514 bool wxBitmapHandler::Create( 
1515   wxBitmap
*                         WXUNUSED(pBitmap
) 
1516 , const void*                       WXUNUSED(pData
) 
1517 , wxBitmapType                      
WXUNUSED(lType
) 
1518 , int                               WXUNUSED(nWidth
) 
1519 , int                               WXUNUSED(nHeight
) 
1520 , int                               WXUNUSED(nDepth
) 
1526 bool wxBitmapHandler::LoadFile( 
1527   wxBitmap
*                         WXUNUSED(pBitmap
) 
1529 , wxBitmapType                      
WXUNUSED(lType
) 
1530 , int                               WXUNUSED(nDesiredWidth
) 
1531 , int                               WXUNUSED(nDesiredHeight
) 
1537 bool wxBitmapHandler::LoadFile( 
1538   wxBitmap
*                         WXUNUSED(pBitmap
) 
1539 , const wxString
&                   WXUNUSED(rName
) 
1540 , wxBitmapType                      
WXUNUSED(lType
) 
1541 , int                               WXUNUSED(nDesiredWidth
) 
1542 , int                               WXUNUSED(nDesiredHeight
) 
1548 bool wxBitmapHandler::SaveFile( 
1549   wxBitmap
*                         WXUNUSED(pBitmap
) 
1550 , const wxString
&                   WXUNUSED(rName
) 
1551 , wxBitmapType                      
WXUNUSED(nType
) 
1552 , const wxPalette
*                  WXUNUSED(pPalette
) 
1558 // ---------------------------------------------------------------------------- 
1559 // Utility functions 
1560 // ---------------------------------------------------------------------------- 
1561 HBITMAP 
wxInvertMask( 
1567     HBITMAP                         hBmpInvMask 
= 0; 
1569     wxCHECK_MSG( hBmpMask
, 0, _T("invalid bitmap in wxInvertMask") ); 
1572     // Get width/height from the bitmap if not given 
1574     if (!nWidth 
|| !nHeight
) 
1576         BITMAPINFOHEADER2           vBmhdr
; 
1578         ::GpiQueryBitmapInfoHeader( hBmpMask
 
1581         nWidth  
= (int)vBmhdr
.cx
; 
1582         nHeight 
= (int)vBmhdr
.cy
; 
1585     BITMAPINFOHEADER2               vBmih
; 
1586     SIZEL                           vSize 
= {0, 0}; 
1587     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1588     HDC                             hDCSrc 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1589     HDC                             hDCDst 
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
); 
1590     HPS                             hPSSrc 
= ::GpiCreatePS(vHabmain
, hDCSrc
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1591     HPS                             hPSDst 
= ::GpiCreatePS(vHabmain
, hDCDst
, &vSize
, PU_PELS 
| GPIA_ASSOC
); 
1592     POINTL                          vPoint
[4] = { {0 ,0}, {nWidth
, nHeight
}, 
1593                                                   {0, 0}, {nWidth
, nHeight
} 
1596     memset(&vBmih
, '\0', 16); 
1601     vBmih
.cBitCount 
= 24; 
1603     hBmpInvMask 
= ::GpiCreateBitmap( hPSDst
 
1610     ::GpiSetBitmap(hPSSrc
, (HBITMAP
) hBmpMask
); 
1611     ::GpiSetBitmap(hPSDst
, (HBITMAP
) hBmpInvMask
); 
1621     ::GpiDestroyPS(hPSSrc
); 
1622     ::GpiDestroyPS(hPSDst
); 
1623     ::DevCloseDC(hDCSrc
); 
1624     ::DevCloseDC(hDCDst
); 
1627 } // end of WxWinGdi_InvertMask 
1629 HBITMAP 
wxCopyBmp( HBITMAP hBmp
, bool flip
, int nWidth
, int nHeight 
) 
1631     wxCHECK_MSG( hBmp
, 0, _T("invalid bitmap in wxCopyBmp") ); 
1634     // Get width/height from the bitmap if not given 
1636     if (!nWidth 
|| !nHeight
) 
1638         BITMAPINFOHEADER2 vBmhdr
; 
1641         ::GpiQueryBitmapInfoHeader( hBmp
, 
1643         nWidth        
= (int)vBmhdr
.cx
; 
1644         nHeight       
= (int)vBmhdr
.cy
; 
1647     BITMAPINFOHEADER2 vBmih
; 
1648     SIZEL             vSize     
= {0, 0}; 
1649     DEVOPENSTRUC      vDop      
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
1650     HDC               hDCSrc    
= ::DevOpenDC(  vHabmain
, 
1654                                                 (PDEVOPENDATA
)&vDop
, 
1656     HDC               hDCDst    
= ::DevOpenDC(  vHabmain
, 
1660                                                 (PDEVOPENDATA
)&vDop
, 
1662     HPS               hPSSrc    
= ::GpiCreatePS(  vHabmain
, 
1665                                                   PU_PELS 
| GPIA_ASSOC  
); 
1666     HPS               hPSDst    
= ::GpiCreatePS(  vHabmain
, 
1669                                                   PU_PELS 
| GPIA_ASSOC  
); 
1670     POINTL            vPoint
[4] = { {0,      nHeight
}, 
1673                                     {nWidth
, nHeight
} }; 
1677         vPoint
[1].y 
= nHeight
; 
1679     memset(&vBmih
, '\0', 16); 
1684     vBmih
.cBitCount 
= 24; 
1686     HBITMAP hInvBmp 
= ::GpiCreateBitmap(  hPSDst
, 
1692     ::GpiSetBitmap(hPSSrc
, (HBITMAP
) hBmp
); 
1693     ::GpiSetBitmap(hPSDst
, (HBITMAP
) hInvBmp
); 
1695     ::GpiBitBlt(  hPSDst
, 
1702     ::GpiDestroyPS(hPSSrc
); 
1703     ::GpiDestroyPS(hPSDst
); 
1704     ::DevCloseDC(hDCSrc
); 
1705     ::DevCloseDC(hDCDst
); 
1708 } // end of wxFlipBmp