1 /////////////////////////////////////////////////////////////////////////////
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "bitmap.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #include "wx/palette.h"
26 #include "wx/dcmemory.h"
27 #include "wx/bitmap.h"
31 #include "wx/os2/private.h"
34 //#include "wx/msw/dib.h"
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
42 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
44 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 wxBitmapRefData::wxBitmapRefData()
57 m_pSelectedInto
= NULL
;
62 void wxBitmapRefData::Free()
64 wxASSERT_MSG( !m_pSelectedInto
,
65 wxT("deleting bitmap still selected into wxMemoryDC") );
69 if ( !::GpiDeleteBitmap((HBITMAP
)m_hBitmap
) )
71 wxLogLastError("GpiDeleteBitmap(hbitmap)");
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 // this function should be called from all wxBitmap ctors
86 // m_refData = NULL; done in the base class ctor
89 wxTheBitmapList
->AddBitmap(this);
92 bool wxBitmap::CopyFromIconOrCursor(
93 const wxGDIImage
& rIcon
96 wxBitmapRefData
* pRefData
= new wxBitmapRefData
;
100 pRefData
->m_nWidth
= rIcon
.GetWidth();
101 pRefData
->m_nHeight
= rIcon
.GetHeight();
102 pRefData
->m_nDepth
= wxDisplayDepth();
104 pRefData
->m_hBitmap
= (WXHBITMAP
)rIcon
.GetHandle();
106 pRefData
->m_pBitmapMask
= new wxMask();
108 #if WXWIN_COMPATIBILITY_2
109 pRefData
->m_bOk
= TRUE
;
110 #endif // WXWIN_COMPATIBILITY_2
114 bool wxBitmap::CopyFromCursor(
115 const wxCursor
& rCursor
122 return(CopyFromIconOrCursor(rCursor
));
125 bool wxBitmap::CopyFromIcon(
134 #if WXWIN_COMPATIBILITY_2
135 refData
->m_ok
= TRUE
;
136 #endif // WXWIN_COMPATIBILITY_2
138 return CopyFromIconOrCursor(rIcon
);
141 wxBitmap::~wxBitmap()
144 wxTheBitmapList
->DeleteObject(this);
156 wxBitmapRefData
* pRefData
= new wxBitmapRefData
;
157 BITMAPINFOHEADER2 vHeader
;
161 DEVOPENSTRUC vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
162 SIZEL vSize
= {0, 0};
164 wxASSERT(vHabmain
!= NULL
);
166 hDc
= ::DevOpenDC(vHabmain
, OD_MEMORY
, (PSZ
)"*", 1L, (PDEVOPENDATA
)&vDop
, 0L);
168 vHeader
.cbFix
= sizeof(vHeader
);
169 vHeader
.cx
= (USHORT
)nTheWidth
;
170 vHeader
.cy
= (USHORT
)nTheHeight
;
171 vHeader
.cPlanes
= 1L;
172 vHeader
.cBitCount
= nNoBits
;
173 vHeader
.ulCompression
= BCA_UNCOMP
;
174 vHeader
.cxResolution
= 0;
175 vHeader
.cyResolution
= 0;
176 vHeader
.cclrUsed
= 0;
177 vHeader
.cclrImportant
= 0;
178 vHeader
.usUnits
= BRU_METRIC
;
179 vHeader
.usRecording
= BRA_BOTTOMUP
;
180 vHeader
.usRendering
= BRH_NOTHALFTONED
;
183 vHeader
.ulColorEncoding
= 0;
184 vHeader
.ulIdentifier
= 0;
186 hPs
= ::GpiCreatePS(vHabmain
, hDc
, &vSize
, GPIA_ASSOC
| PU_PELS
);
189 wxLogLastError("GpiCreatePS Failure");
192 m_refData
= pRefData
;
194 pRefData
->m_nWidth
= nTheWidth
;
195 pRefData
->m_nHeight
= nTheHeight
;
196 pRefData
->m_nDepth
= nNoBits
;
197 pRefData
->m_nNumColors
= 0;
198 pRefData
->m_pSelectedInto
= NULL
;
200 HBITMAP hBmp
= ::GpiCreateBitmap(hPs
, &vHeader
, 0L, NULL
, &vInfo
);
203 wxLogLastError("CreateBitmap");
205 SetHBITMAP((WXHBITMAP
)hBmp
);
208 // Create from XPM data
211 , wxControl
* WXUNUSED(pAnItem
))
215 (void)Create( (void *)ppData
216 ,wxBITMAP_TYPE_XPM_DATA
256 const wxString
& rFilename
267 bool wxBitmap::Create(
274 BITMAPINFOHEADER2 vHeader
;
278 DEVOPENSTRUC vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
279 SIZEL vSize
= {0, 0};
282 wxASSERT(vHabmain
!= NULL
);
284 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
285 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
286 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_BITCOUNT
, 1L, &lBitCount
);
288 vHeader
.cbFix
= sizeof(vHeader
);
289 vHeader
.cx
= (USHORT
)nW
;
290 vHeader
.cy
= (USHORT
)nH
;
291 vHeader
.cPlanes
= (USHORT
)nD
;
292 vHeader
.cBitCount
= lBitCount
;
293 vHeader
.ulCompression
= BCA_UNCOMP
;
294 vHeader
.cxResolution
= 0;
295 vHeader
.cyResolution
= 0;
296 vHeader
.cclrUsed
= 0;
297 vHeader
.cclrImportant
= 0;
298 vHeader
.usUnits
= BRU_METRIC
;
299 vHeader
.usRecording
= BRA_BOTTOMUP
;
300 vHeader
.usRendering
= BRH_NOTHALFTONED
;
303 vHeader
.ulColorEncoding
= 0;
304 vHeader
.ulIdentifier
= 0;
307 m_refData
= new wxBitmapRefData
;
309 GetBitmapData()->m_nWidth
= nW
;
310 GetBitmapData()->m_nHeight
= nH
;
311 GetBitmapData()->m_nDepth
= nD
;
315 hBmp
= ::GpiCreateBitmap(hpsScreen
, &vHeader
, 0L, NULL
, &vInfo
);
318 wxLogLastError("CreateBitmap");
325 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_PLANES
, 1L, &lPlanes
);
326 hBmp
= ::GpiCreateBitmap(hpsScreen
, &vHeader
, 0L, NULL
, &vInfo
);
329 wxLogLastError("CreateBitmap");
331 GetBitmapData()->m_nDepth
= wxDisplayDepth();
333 SetHBITMAP((WXHBITMAP
)hBmp
);
335 #if WXWIN_COMPATIBILITY_2
336 GetBitmapData()->m_bOk
= hBmp
!= 0;
337 #endif // WXWIN_COMPATIBILITY_2
342 bool wxBitmap::LoadFile(
343 const wxString
& rFilename
347 HPS hPs
= NULLHANDLE
;
351 wxBitmapHandler
* pHandler
= wxDynamicCast( FindHandler(lType
)
357 m_refData
= new wxBitmapRefData
;
359 return(pHandler
->LoadFile( this
371 if (!vImage
.LoadFile(rFilename
, lType
) || !vImage
.Ok() )
374 *this = vImage
.ConvertToBitmap();
380 bool wxBitmap::Create(
390 wxBitmapHandler
* pHandler
= wxDynamicCast( FindHandler(lType
)
396 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
397 "type %d defined."), lType
);
402 m_refData
= new wxBitmapRefData
;
404 return(pHandler
->Create( this
413 bool wxBitmap::SaveFile(
414 const wxString
& rFilename
416 , const wxPalette
* pPalette
419 wxBitmapHandler
* pHandler
= wxDynamicCast( FindHandler(lType
)
425 return pHandler
->SaveFile( this
433 // FIXME what about palette? shouldn't we use it?
434 wxImage
vImage(*this);
439 return(vImage
.SaveFile( rFilename
445 // ----------------------------------------------------------------------------
446 // wxBitmap accessors
447 // ----------------------------------------------------------------------------
449 void wxBitmap::SetQuality(
455 GetBitmapData()->m_nQuality
= nQ
;
458 #if WXWIN_COMPATIBILITY_2
459 void wxBitmap::SetOk(
465 GetBitmapData()->m_bOk
= bOk
;
467 #endif // WXWIN_COMPATIBILITY_2
469 void wxBitmap::SetPalette(
470 const wxPalette
& rPalette
475 GetBitmapData()->m_vBitmapPalette
= rPalette
;
478 void wxBitmap::SetMask(
484 GetBitmapData()->m_pBitmapMask
= pMask
;
487 // Will try something for OS/2 but not really sure how close
488 // to the msw intent this is.
489 wxBitmap
wxBitmap::GetBitmapForDC(
494 wxBitmap
vTmpBitmap( this->GetWidth()
498 WXHBITMAP vOldBitmap
;
504 hMemoryPS
= ::GpiCreatePS(vHabmain
, (HDC
)vMemDC
.GetHDC(), &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
505 hPs
= ::GpiCreatePS(vHabmain
, (HDC
)rDc
.GetHDC(), &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
507 // TODO: Set the points
509 vOldBitmap
= (WXHBITMAP
)::GpiSetBitmap(hPs
, (HBITMAP
)vTmpBitmap
.GetHBITMAP());
510 ::GpiBitBlt(hPs
, hMemoryPS
, 4L, vPoint
, ROP_SRCCOPY
, BBO_IGNORE
);
515 // ----------------------------------------------------------------------------
517 // ----------------------------------------------------------------------------
524 // Construct a mask from a bitmap and a colour indicating
525 // the transparent area
527 const wxBitmap
& rBitmap
528 , const wxColour
& rColour
537 // Construct a mask from a bitmap and a palette index indicating
538 // the transparent area
540 const wxBitmap
& rBitmap
550 // Construct a mask from a mono bitmap (copies the bitmap).
552 const wxBitmap
& rBitmap
562 ::GpiDeleteBitmap((HBITMAP
)m_hMaskBitmap
);
565 // Create a mask from a mono bitmap (copies the bitmap).
567 const wxBitmap
& rBitmap
570 BITMAPINFOHEADER2 vHeader
;
571 DEVOPENSTRUC vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
572 SIZEL vSize
= {0, 0};
577 ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
);
580 if (!rBitmap
.Ok() || rBitmap
.GetDepth() != 1)
584 vHeader
.cbFix
= sizeof(vHeader
);
585 vHeader
.cx
= (USHORT
)rBitmap
.GetWidth();
586 vHeader
.cy
= (USHORT
)rBitmap
.GetHeight();
588 vHeader
.cBitCount
= 1;
590 m_hMaskBitmap
= (WXHBITMAP
) ::GpiCreateBitmap( m_hPs
597 HPS srcPS
= ::GpiCreatePS(vHabmain
, m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
598 ::GpiSetBitmap(srcPS
, (HBITMAP
)rBitmap
.GetHBITMAP());
599 HPS destPS
= ::GpiCreatePS(vHabmain
, m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
600 ::GpiSetBitmap(srcPS
, (HBITMAP
)m_hMaskBitmap
);
601 // TODO: Set the point array
602 ::GpiBitBlt(destPS
, srcPS
, 4L, vPoint
, ROP_SRCCOPY
, BBO_IGNORE
);
604 ::GpiDestroyPS(srcPS
);
605 ::GpiDestroyPS(destPS
);
609 // Create a mask from a bitmap and a palette index indicating
610 // the transparent area
612 const wxBitmap
& rBitmap
618 ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
);
621 if (rBitmap
.Ok() && rBitmap
.GetPalette()->Ok())
624 unsigned char cGreen
;
627 if (rBitmap
.GetPalette()->GetRGB( nPaletteIndex
633 wxColour
vTransparentColour( cRed
638 return (Create( rBitmap
646 // Create a mask from a bitmap and a colour indicating
647 // the transparent area
649 const wxBitmap
& rBitmap
650 , const wxColour
& rColour
653 BITMAPINFOHEADER2 vHeader
;
654 DEVOPENSTRUC vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
655 SIZEL vSize
= {0, 0};
660 ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
);
668 // scan the bitmap for the transparent colour and set
669 // the corresponding pixels in the mask to BLACK and
671 COLORREF vMaskColour
= OS2RGB(rColour
.Red(), rColour
.Green(), rColour
.Blue());
673 vHeader
.cbFix
= sizeof(vHeader
);
674 vHeader
.cx
= (USHORT
)rBitmap
.GetWidth();
675 vHeader
.cy
= (USHORT
)rBitmap
.GetHeight();
677 vHeader
.cBitCount
= 1;
679 m_hMaskBitmap
= (WXHBITMAP
) ::GpiCreateBitmap( m_hPs
686 HPS srcPS
= ::GpiCreatePS(vHabmain
, m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
687 ::GpiSetBitmap(srcPS
, (HBITMAP
)rBitmap
.GetHBITMAP());
688 HPS destPS
= ::GpiCreatePS(vHabmain
, m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
689 ::GpiSetBitmap(srcPS
, (HBITMAP
)m_hMaskBitmap
);
691 // this is not very efficient, but I can't think
692 // of a better way of doing it
693 for (int w
= 0; w
< rBitmap
.GetWidth(); w
++)
695 for (int h
= 0; h
< rBitmap
.GetHeight(); h
++)
702 COLORREF col
= ::GpiQueryPel(srcPS
, &vPoint
);
704 if (col
== vMaskColour
)
706 ::GpiSetColor(destPS
, CLR_WHITE
);
707 ::GpiSetPel(destPS
, &vPoint
);
711 ::GpiSetColor(destPS
, CLR_BLACK
);
712 ::GpiSetPel(destPS
, &vPoint
);
716 ::GpiDestroyPS(srcPS
);
717 ::GpiDestroyPS(destPS
);
721 // ----------------------------------------------------------------------------
723 // ----------------------------------------------------------------------------
725 bool wxBitmapHandler::Create(
734 wxBitmap
* pBitmap
= wxDynamicCast( pImage
738 return(pBitmap
? Create( pBitmap
746 bool wxBitmapHandler::Load(
748 , const wxString
& rName
755 wxBitmap
* pBitmap
= wxDynamicCast( pImage
759 return(pBitmap
? LoadFile( pBitmap
768 bool wxBitmapHandler::Save(
770 , const wxString
& rName
774 wxBitmap
* pBitmap
= wxDynamicCast( pImage
778 return(pBitmap
? SaveFile( pBitmap
784 bool wxBitmapHandler::Create(
785 wxBitmap
* WXUNUSED(pBitmap
)
786 , void* WXUNUSED(pData
)
787 , long WXUNUSED(lType
)
788 , int WXUNUSED(nWidth
)
789 , int WXUNUSED(nHeight
)
790 , int WXUNUSED(nDepth
)
796 bool wxBitmapHandler::LoadFile(
797 wxBitmap
* WXUNUSED(pBitmap
)
798 , const wxString
& WXUNUSED(rName
)
800 , long WXUNUSED(lType
)
801 , int WXUNUSED(nDesiredWidth
)
802 , int WXUNUSED(nDesiredHeight
)
808 bool wxBitmapHandler::SaveFile(
809 wxBitmap
* WXUNUSED(pBitmap
)
810 , const wxString
& WXUNUSED(rName
)
811 , int WXUNUSED(nType
)
812 , const wxPalette
* WXUNUSED(pPalette
)