1 /////////////////////////////////////////////////////////////////////////////
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"
21 #include "wx/palette.h"
22 #include "wx/dcmemory.h"
23 #include "wx/bitmap.h"
27 #include "wx/os2/private.h"
30 //#include "wx/msw/dib.h"
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 #if !USE_SHARED_LIBRARIES
38 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
, wxGDIObject
)
39 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxObject
)
41 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler
, wxObject
)
44 // ============================================================================
46 // ============================================================================
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 wxBitmapRefData::wxBitmapRefData()
55 m_pSelectedInto
= NULL
;
60 void wxBitmapRefData::Free()
62 wxASSERT_MSG( !m_pSelectedInto
,
63 wxT("deleting bitmap still selected into wxMemoryDC") );
67 if ( !::GpiDeleteBitmap((HBITMAP
)m_hBitmap
) )
69 wxLogLastError("GpiDeleteBitmap(hbitmap)");
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 // this function should be called from all wxBitmap ctors
84 // m_refData = NULL; done in the base class ctor
87 wxTheBitmapList
->AddBitmap(this);
90 bool wxBitmap::CopyFromIconOrCursor(
91 const wxGDIImage
& rIcon
94 wxBitmapRefData
* pRefData
= new wxBitmapRefData
;
98 refData
->m_width
= rIcon
.GetWidth();
99 refData
->m_height
= rIcon
.GetHeight();
100 refData
->m_depth
= wxDisplayDepth();
102 refData
->m_hBitmap
= (WXHBITMAP
)rIcon
.GetHandle();
104 refData
->m_bitmapMask
= new wxMask();
106 #if WXWIN_COMPATIBILITY_2
107 refData
->m_ok
= TRUE
;
108 #endif // WXWIN_COMPATIBILITY_2
113 bool wxBitmap::CopyFromCursor(
114 const wxCursor
& rCursor
121 return CopyFromIconOrCursor(wxGDIImage
)rCursor
);
124 bool wxBitmap::CopyFromIcon(
133 #if WXWIN_COMPATIBILITY_2
134 refData
->m_ok
= TRUE
;
135 #endif // WXWIN_COMPATIBILITY_2
137 return CopyFromIconOrCursor(icon
);
140 wxBitmap::~wxBitmap()
143 wxTheBitmapList
->DeleteObject(this);
155 wxBitmapRefData
* pRefData
= new wxBitmapRefData
;
156 BITMAPINFOHEADER2 vHeader
;
160 DEVOPENSTRUCT vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
161 SIZEL vSize
= {0, 0};
163 wxAssert(vHabmain
!= NULL
);
165 hDc
= ::DevOpenDC(vHabmain
, OD_MEMORY
, (PSZ
)"*", 1L, (PDEVOPENDATA
)&vDop
, 0L);
167 vHeader
.cbFix
= sizeof(vHeader
);
168 vHeader
.cx
= (USHORT
)nTheWidth
;
169 vHeader
.cy
= (USHORT
)nTheHeight
;
170 vHeader
.cPlanes
= 1L;
171 vHeader
.cBitCount
= nNoBits
;
172 vHeader
.ulCompression
= BCA_UNCOMP
;
173 vHeader
.cxResolution
= 0;
174 vHeader
.cyResolution
= 0;
175 vHeader
.cclrUsed
= 0;
176 vHeader
.cclrImportant
= 0;
177 vHeader
.usUnits
= BRU_METRIC
;
178 vHeader
.usRecording
= BRA_BOTTOMUP
;
179 vHeader
.usRendering
= BRH_NOTHALFTONED
;
182 vHeader
.ulColorEncoding
= 0;
183 vHeader
.ulIdentifier
= 0;
185 hPs
= ::GpiCreatePS(vHabMain
, hdc
, &vSize
, GPIA_ASSOC
| PU_PELS
);
188 wxLogLastError("GpiCreatePS Failure");
194 m_refData
= pRefData
;
196 refData
->m_width
= nTheWidth
;
197 refData
->m_height
= nTheHeight
;
198 refData
->m_depth
= nNoBits
;
199 refData
->m_numColors
= 0;
200 refData
->m_selectedInto
= NULL
;
202 HBITMAP hBmp
= ::GpiCreateBitmap(hPs
, &vHeader
, 0L, NULL
, &vInfo
);
205 wxLogLastError("CreateBitmap");
207 SetHBITMAP((WXHBITMAP
)hbmp
);
210 // Create from XPM data
213 , wxControl
* WXUNUSED(pAnItem
))
217 F (void)Create( (void *)ppData
218 ,wxBITMAP_TYPE_XPM_DATA
258 const wxString
& rFilename
269 bool wxBitmap::Create(
276 BITMAPINFOHEADER2 vHeader
;
280 DEVOPENSTRUCT vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
281 SIZEL vSize
= {0, 0};
284 wxAssert(vHabmain
!= NULL
);
286 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
287 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
288 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_BITCOUNT
, &lBitCount
);
290 vHeader
.cbFix
= sizeof(vHeader
);
291 vHeader
.cx
= (USHORT
)nW
;
292 vHeader
.cy
= (USHORT
)nH
;
293 vHeader
.cPlanes
= (USHORT
)nD
;
294 vHeader
.cBitCount
= lBitCount
;
295 vHeader
.ulCompression
= BCA_UNCOMP
;
296 vHeader
.cxResolution
= 0;
297 vHeader
.cyResolution
= 0;
298 vHeader
.cclrUsed
= 0;
299 vHeader
.cclrImportant
= 0;
300 vHeader
.usUnits
= BRU_METRIC
;
301 vHeader
.usRecording
= BRA_BOTTOMUP
;
302 vHeader
.usRendering
= BRH_NOTHALFTONED
;
305 vHeader
.ulColorEncoding
= 0;
306 vHeader
.ulIdentifier
= 0;
310 m_refData
= new wxBitmapRefData
;
312 GetBitmapData()->m_width
= nW
;
313 GetBitmapData()->m_height
= nH
;
314 GetBitmapData()->m_depth
= nD
;
318 hBmp
= ::GpiCreateBitmap(hpsScreen
, &vHeader
, 0L, NULL
, &vInfo
);
321 wxLogLastError("CreateBitmap");
328 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_PLANES
, &lPlanes
);
329 hBmp
= ::GpiCreateBitmap(hpsScreen
, &vHeader
, 0L, NULL
, &vInfo
);
332 wxLogLastError("CreateBitmap");
334 GetBitmapData()->m_depth
= wxDisplayDepth();
336 SetHBITMAP((WXHBITMAP
)hBmp
);
338 #if WXWIN_COMPATIBILITY_2
339 GetBitmapData()->m_bOk
= hBmp
!= 0;
340 #endif // WXWIN_COMPATIBILITY_2
345 bool wxBitmap::LoadFile(
346 const wxString
& rFilename
352 wxBitmapHandler
* pHandler
= wxDynamicCast( FindHandler(lType
)
358 m_refData
= new wxBitmapRefData
;
360 return(pHandler
->LoadFile( this
371 if (!vImage
.LoadFile(rFilename
, lType
) || !image
.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."), type
);
402 m_refData
= new wxBitmapRefData
;
404 return(handler
->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()
503 hMemoryPS
= ::GpiCreatePS(habMain
, (HDC
)vMemDC
.m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPI_ASSOC
);
504 hPs
= ::GpiCreatePS(habMain
, (HDC
)rDc
.m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPI_ASSOC
);
506 // TODO: Set the points
508 rDc
.m_oldBitmap
= (WXHBITMAP
)::GpiSetBitMap(hPs
, (HBITMAP
)vTmpBitmap
.GetHBITMAP());
509 :GpiBitBlt(hPs
, hMemoryPS
, 4L, vPoint
, ROP_SRCCOPY
| BBO_IGNORE
);
514 // ----------------------------------------------------------------------------
516 // ----------------------------------------------------------------------------
523 // Construct a mask from a bitmap and a colour indicating
524 // the transparent area
526 const wxBitmap
& rBitmap
527 , const wxColour
& rColour
536 // Construct a mask from a bitmap and a palette index indicating
537 // the transparent area
539 const wxBitmap
& rBitmap
549 // Construct a mask from a mono bitmap (copies the bitmap).
551 const wxBitmap
& rBitmap
561 ::GpiDeleteBitmap((HBITMAP
)m_hMaskBitmap
);
564 // Create a mask from a mono bitmap (copies the bitmap).
566 const wxBitmap
& rBitmap
569 BITMAPINFOHEADER2 vHeader
;
570 DEVOPENSTRUCT vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
571 SIZEL vSize
= {0, 0};
576 ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
);
579 if (!rBitmap
.Ok() || rBitmap
.GetDepth() != 1)
583 vHeader
.cbFix
= sizeof(vHeader
);
584 vHeader
.cx
= (USHORT
)rBitmap
.GetWidth();
585 vHeader
.cy
= (USHORT
)rBitmap
.GetHeight();
587 vHeader
.cBitCount
= 1;
589 m_hMaskBitmap
= (WXHBITMAP
) ::GpiCreateBitmap( m_hPs
596 HPS srcPS
= ::GpiCreatePS(vHabmain
, m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
597 ::GpiSetBitmap(srcPS
, (HBITMAP
)rBitmap
.GetHBITMAP());
598 HPS destPS
= ::GpiCreatePS(vHabmain
, m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
599 ::GpiSetBitmap(srcPS
, (HBITMAP
)m_hMaskBitmap
);
600 // TODO: Set the point array
601 :GpiBitBlt(destPs
, srcPS
, 4L, vPoint
, ROP_SRCCOPY
| BBO_IGNORE
);
603 ::GpiDestroyPS(srcPS
);
604 ::GpiDestroyPS(destPS
);
608 // Create a mask from a bitmap and a palette index indicating
609 // the transparent area
611 const wxBitmap
& rBitmap
617 ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
);
620 if (rBitmap
.Ok() && rBitmap
.GetPalette()->Ok())
622 unsigned char red
, green
, blue
;
623 if (rBitmap
.GetPalette()->GetRGB( nPaletteIndex
629 wxColour
vTransparentColour( rRed
634 return (Create( rBitmap
642 // Create a mask from a bitmap and a colour indicating
643 // the transparent area
645 const wxBitmap
& rBitmap
646 , const wxColour
& rColour
649 BITMAPINFOHEADER2 vHeader
;
650 DEVOPENSTRUCT vDop
= { NULL
, "DISPLAY", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
651 SIZEL vSize
= {0, 0};
656 ::GpiDeleteBitmap((HBITMAP
) m_hMaskBitmap
);
664 // scan the bitmap for the transparent colour and set
665 // the corresponding pixels in the mask to BLACK and
667 COLORREF vMaskColour
= OS2RGB(rColour
.Red(), rColour
.Green(), rColour
.Blue());
669 vHeader
.cbFix
= sizeof(vHeader
);
670 vHeader
.cx
= (USHORT
)rBitmap
.GetWidth();
671 vHeader
.cy
= (USHORT
)rBitmap
.GetHeight();
673 vHeader
.cBitCount
= 1;
675 m_hMaskBitmap
= (WXHBITMAP
) ::GpiCreateBitmap( m_hPs
682 HPS srcPS
= ::GpiCreatePS(vHabmain
, m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
683 ::GpiSetBitmap(srcPS
, (HBITMAP
)rBitmap
.GetHBITMAP());
684 HPS destPS
= ::GpiCreatePS(vHabmain
, m_hDc
, &vSize
, PU_PELS
| GPIT_MICRO
| GPIA_ASSOC
);
685 ::GpiSetBitmap(srcPS
, (HBITMAP
)m_hMaskBitmap
);
687 // this is not very efficient, but I can't think
688 // of a better way of doing it
689 for (int w
= 0; w
< rBitmap
.GetWidth(); w
++)
691 for (int h
= 0; h
< rBitmap
.GetHeight(); h
++)
698 COLORREF col
= ::GpiQueryPel(srcPS
, w
, h
);
700 if (col
== vMaskColour
)
702 ::GpiSetColor(destPS
, CLR_WHITE
);
703 ::GpiSetPel(destPS
, &vPoint
);
707 ::GpiSetColor(destPS
, CLR_BLACK
);
708 ::GpiSetPel(destPS
, &vPoint
);
712 ::GpiDestroyPS(srcPS
);
713 ::GpiDestroyPS(destPS
);
717 // ----------------------------------------------------------------------------
719 // ----------------------------------------------------------------------------
721 bool wxBitmapHandler::Create(
730 wxBitmap
* pBitmap
= wxDynamicCast( pImage
734 return(pBitmap
? Create( pBitmap
742 bool wxBitmapHandler::Load(
744 , const wxString
& rName
750 wxBitmap
* bitmap
= wxDynamicCast( pImage
754 return(pBitmap
? LoadFile( pBitmap
762 bool wxBitmapHandler::Save(
764 , const wxString
& rName
768 wxBitmap
* pBitmap
= wxDynamicCast( pImage
772 return(pBitmap
? SaveFile( pBitmap
778 bool wxBitmapHandler::Create(
779 wxBitmap
* WXUNUSED(pBitmap
)
780 , void* WXUNUSED(pData
)
781 , long WXUNUSED(lType
)
782 , int WXUNUSED(nWidth
)
783 , int WXUNUSED(nHeight
)
784 , int WXUNUSED(nDepth
)
790 bool wxBitmapHandler::LoadFile(
791 wxBitmap
* WXUNUSED(pBitmap
)
792 , const wxString
& WXUNUSED(rName
)
793 , long WXUNUSED(lType
)
794 , int WXUNUSED(nDesiredWidth
)
795 , int WXUNUSED(nDesiredHeight
)
801 bool wxBitmapHandler::SaveFile(
802 wxBitmap
* WXUNUSED(pBitmap
)
803 , const wxString
& WXUNUSED(rName
)
804 , int WXUNUSED(nType
)
805 , const wxPalette
* WXUNUSED(pPalette
)