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(habMain
, 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
, &vSize
, PU_PELS
| GPI_ASSOC
);
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).
565 bool wxMask::Create(const wxBitmap
& bitmap
)
569 ::DeleteObject((HBITMAP
) m_maskBitmap
);
572 if (!bitmap
.Ok() || bitmap
.GetDepth() != 1)
576 m_maskBitmap
= (WXHBITMAP
) CreateBitmap(
581 HDC srcDC
= CreateCompatibleDC(0);
582 SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
583 HDC destDC
= CreateCompatibleDC(0);
584 SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
585 BitBlt(destDC
, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight(), srcDC
, 0, 0, SRCCOPY
);
586 SelectObject(srcDC
, 0);
588 SelectObject(destDC
, 0);
593 // Create a mask from a bitmap and a palette index indicating
594 // the transparent area
595 bool wxMask::Create(const wxBitmap
& bitmap
, int paletteIndex
)
599 ::DeleteObject((HBITMAP
) m_maskBitmap
);
602 if (bitmap
.Ok() && bitmap
.GetPalette()->Ok())
604 unsigned char red
, green
, blue
;
605 if (bitmap
.GetPalette()->GetRGB(paletteIndex
, &red
, &green
, &blue
))
607 wxColour
transparentColour(red
, green
, blue
);
608 return Create(bitmap
, transparentColour
);
614 // Create a mask from a bitmap and a colour indicating
615 // the transparent area
616 bool wxMask::Create(const wxBitmap
& bitmap
, const wxColour
& colour
)
620 ::DeleteObject((HBITMAP
) m_maskBitmap
);
628 // scan the bitmap for the transparent colour and set
629 // the corresponding pixels in the mask to BLACK and
631 COLORREF maskColour
= RGB(colour
.Red(), colour
.Green(), colour
.Blue());
632 m_maskBitmap
= (WXHBITMAP
) ::CreateBitmap(
637 HDC srcDC
= ::CreateCompatibleDC(0);
638 ::SelectObject(srcDC
, (HBITMAP
) bitmap
.GetHBITMAP());
639 HDC destDC
= ::CreateCompatibleDC(0);
640 ::SelectObject(destDC
, (HBITMAP
) m_maskBitmap
);
642 // this is not very efficient, but I can't think
643 // of a better way of doing it
644 for (int w
= 0; w
< bitmap
.GetWidth(); w
++)
646 for (int h
= 0; h
< bitmap
.GetHeight(); h
++)
648 COLORREF col
= GetPixel(srcDC
, w
, h
);
649 if (col
== maskColour
)
651 ::SetPixel(destDC
, w
, h
, RGB(0, 0, 0));
655 ::SetPixel(destDC
, w
, h
, RGB(255, 255, 255));
659 ::SelectObject(srcDC
, 0);
661 ::SelectObject(destDC
, 0);
666 // ----------------------------------------------------------------------------
668 // ----------------------------------------------------------------------------
670 bool wxBitmapHandler::Create(wxGDIImage
*image
,
673 int width
, int height
, int depth
)
675 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
677 return bitmap
? Create(bitmap
, data
, width
, height
, depth
) : FALSE
;
680 bool wxBitmapHandler::Load(wxGDIImage
*image
,
681 const wxString
& name
,
683 int width
, int height
)
685 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
687 return bitmap
? LoadFile(bitmap
, name
, flags
, width
, height
) : FALSE
;
690 bool wxBitmapHandler::Save(wxGDIImage
*image
,
691 const wxString
& name
,
694 wxBitmap
*bitmap
= wxDynamicCast(image
, wxBitmap
);
696 return bitmap
? SaveFile(bitmap
, name
, type
) : FALSE
;
699 bool wxBitmapHandler::Create(wxBitmap
*WXUNUSED(bitmap
),
700 void *WXUNUSED(data
),
703 int WXUNUSED(height
),
709 bool wxBitmapHandler::LoadFile(wxBitmap
*WXUNUSED(bitmap
),
710 const wxString
& WXUNUSED(name
),
712 int WXUNUSED(desiredWidth
),
713 int WXUNUSED(desiredHeight
))
718 bool wxBitmapHandler::SaveFile(wxBitmap
*WXUNUSED(bitmap
),
719 const wxString
& WXUNUSED(name
),
721 const wxPalette
*WXUNUSED(palette
))
726 // ----------------------------------------------------------------------------
728 // ----------------------------------------------------------------------------
730 bool wxCreateDIB(long xSize
, long ySize
, long bitsPerPixel
,
731 HPALETTE hPal
, LPBITMAPINFO
* lpDIBHeader
)
733 unsigned long i
, headerSize
;
734 LPBITMAPINFO lpDIBheader
= NULL
;
735 LPPALETTEENTRY lpPe
= NULL
;
738 // Allocate space for a DIB header
739 headerSize
= (sizeof(BITMAPINFOHEADER
) + (256 * sizeof(PALETTEENTRY
)));
740 lpDIBheader
= (BITMAPINFO
*) malloc(headerSize
);
741 lpPe
= (PALETTEENTRY
*)((BYTE
*)lpDIBheader
+ sizeof(BITMAPINFOHEADER
));
743 GetPaletteEntries(hPal
, 0, 256, lpPe
);
745 memset(lpDIBheader
, 0x00, sizeof(BITMAPINFOHEADER
));
747 // Fill in the static parts of the DIB header
748 lpDIBheader
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
749 lpDIBheader
->bmiHeader
.biWidth
= xSize
;
750 lpDIBheader
->bmiHeader
.biHeight
= ySize
;
751 lpDIBheader
->bmiHeader
.biPlanes
= 1;
753 // this value must be 1, 4, 8 or 24 so PixelDepth can only be
754 lpDIBheader
->bmiHeader
.biBitCount
= (WORD
)(bitsPerPixel
);
755 lpDIBheader
->bmiHeader
.biCompression
= BI_RGB
;
756 lpDIBheader
->bmiHeader
.biSizeImage
= xSize
* abs(ySize
) * bitsPerPixel
>> 3;
757 lpDIBheader
->bmiHeader
.biClrUsed
= 256;
760 // Initialize the DIB palette
761 for (i
= 0; i
< 256; i
++) {
762 lpDIBheader
->bmiColors
[i
].rgbReserved
= lpPe
[i
].peFlags
;
763 lpDIBheader
->bmiColors
[i
].rgbRed
= lpPe
[i
].peRed
;
764 lpDIBheader
->bmiColors
[i
].rgbGreen
= lpPe
[i
].peGreen
;
765 lpDIBheader
->bmiColors
[i
].rgbBlue
= lpPe
[i
].peBlue
;
768 *lpDIBHeader
= lpDIBheader
;
773 void wxFreeDIB(LPBITMAPINFO lpDIBHeader
)