]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/bitmap.cpp
Merged some STC fixes over to the main branch
[wxWidgets.git] / src / os2 / bitmap.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: bitmap.cpp
3// Purpose: wxBitmap
4// Author: David Webster
5// Modified by:
6// Created: 08/08/99
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13 #pragma implementation "bitmap.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifndef WX_PRECOMP
20 #include <stdio.h>
21
22 #include "wx/list.h"
23 #include "wx/utils.h"
24 #include "wx/app.h"
25 #include "wx/palette.h"
26 #include "wx/dcmemory.h"
27 #include "wx/bitmap.h"
28 #include "wx/icon.h"
29#endif
30
31#include "wx/os2/private.h"
32#include "wx/log.h"
33
34//#include "wx/msw/dib.h"
35#include "wx/image.h"
36
37// ----------------------------------------------------------------------------
38// macros
39// ----------------------------------------------------------------------------
40
41IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
42IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
43
44IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
45
46// ============================================================================
47// implementation
48// ============================================================================
49
50// ----------------------------------------------------------------------------
51// wxBitmapRefData
52// ----------------------------------------------------------------------------
53
54wxBitmapRefData::wxBitmapRefData()
55{
56 m_nQuality = 0;
57 m_pSelectedInto = NULL;
58 m_nNumColors = 0;
59 m_pBitmapMask = NULL;
60}
61
62void wxBitmapRefData::Free()
63{
64 wxASSERT_MSG( !m_pSelectedInto,
65 wxT("deleting bitmap still selected into wxMemoryDC") );
66
67 if (m_hBitmap)
68 {
69 if ( !::GpiDeleteBitmap((HBITMAP)m_hBitmap) )
70 {
71 wxLogLastError("GpiDeleteBitmap(hbitmap)");
72 }
73 }
74
75 delete m_pBitmapMask;
76 m_pBitmapMask = NULL;
77}
78
79// ----------------------------------------------------------------------------
80// wxBitmap creation
81// ----------------------------------------------------------------------------
82
83// this function should be called from all wxBitmap ctors
84void wxBitmap::Init()
85{
86 // m_refData = NULL; done in the base class ctor
87
88 if (wxTheBitmapList)
89 wxTheBitmapList->AddBitmap(this);
90}
91
92bool wxBitmap::CopyFromIconOrCursor(
93 const wxGDIImage& rIcon
94)
95{
96 wxBitmapRefData* pRefData = new wxBitmapRefData;
97
98 m_refData = pRefData;
99
100 pRefData->m_nWidth = rIcon.GetWidth();
101 pRefData->m_nHeight = rIcon.GetHeight();
102 pRefData->m_nDepth = wxDisplayDepth();
103
104 pRefData->m_hBitmap = (WXHBITMAP)rIcon.GetHandle();
105 // no mask???
106 pRefData->m_pBitmapMask = new wxMask();
107
108#if WXWIN_COMPATIBILITY_2
109 pRefData->m_bOk = TRUE;
110#endif // WXWIN_COMPATIBILITY_2
111 return(TRUE);
112}
113
114bool wxBitmap::CopyFromCursor(
115 const wxCursor& rCursor
116)
117{
118 UnRef();
119
120 if (!rCursor.Ok())
121 return(FALSE);
122 return(CopyFromIconOrCursor(rCursor));
123}
124
125bool wxBitmap::CopyFromIcon(
126 const wxIcon& rIcon
127)
128{
129 UnRef();
130
131 if (!rIcon.Ok())
132 return(FALSE);
133
134 return CopyFromIconOrCursor(rIcon);
135}
136
137wxBitmap::~wxBitmap()
138{
139 if (wxTheBitmapList)
140 wxTheBitmapList->DeleteObject(this);
141}
142
143wxBitmap::wxBitmap(
144 const char zBits[]
145, int nTheWidth
146, int nTheHeight
147, int nNoBits
148)
149{
150 Init();
151
152 wxBitmapRefData* pRefData = new wxBitmapRefData;
153 BITMAPINFOHEADER2 vHeader;
154 BITMAPINFO2 vInfo;
155 HDC hDc;
156 HPS hPs;
157 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
158 SIZEL vSize = {0, 0};
159
160 wxASSERT(vHabmain != NULL);
161
162 hDc = ::DevOpenDC(vHabmain, OD_MEMORY, (PSZ)"*", 1L, (PDEVOPENDATA)&vDop, 0L);
163
164 vHeader.cbFix = sizeof(vHeader);
165 vHeader.cx = (USHORT)nTheWidth;
166 vHeader.cy = (USHORT)nTheHeight;
167 vHeader.cPlanes = 1L;
168 vHeader.cBitCount = nNoBits;
169 vHeader.ulCompression = BCA_UNCOMP;
170 vHeader.cxResolution = 0;
171 vHeader.cyResolution = 0;
172 vHeader.cclrUsed = 0;
173 vHeader.cclrImportant = 0;
174 vHeader.usUnits = BRU_METRIC;
175 vHeader.usRecording = BRA_BOTTOMUP;
176 vHeader.usRendering = BRH_NOTHALFTONED;
177 vHeader.cSize1 = 0;
178 vHeader.cSize2 = 0;
179 vHeader.ulColorEncoding = 0;
180 vHeader.ulIdentifier = 0;
181
182 hPs = ::GpiCreatePS(vHabmain, hDc, &vSize, GPIA_ASSOC | PU_PELS);
183 if (hPs == 0)
184 {
185 wxLogLastError("GpiCreatePS Failure");
186 }
187
188 m_refData = pRefData;
189
190 pRefData->m_nWidth = nTheWidth;
191 pRefData->m_nHeight = nTheHeight;
192 pRefData->m_nDepth = nNoBits;
193 pRefData->m_nNumColors = 0;
194 pRefData->m_pSelectedInto = NULL;
195
196 HBITMAP hBmp = ::GpiCreateBitmap(hPs, &vHeader, 0L, NULL, &vInfo);
197 if (!hBmp)
198 {
199 wxLogLastError("CreateBitmap");
200 }
201 SetHBITMAP((WXHBITMAP)hBmp);
202}
203
204// Create from XPM data
205wxBitmap::wxBitmap(
206 char** ppData
207, wxControl* WXUNUSED(pAnItem))
208{
209 Init();
210
211 (void)Create( (void *)ppData
212 ,wxBITMAP_TYPE_XPM_DATA
213 ,0
214 ,0
215 ,0
216 );
217}
218
219wxBitmap::wxBitmap(
220 int nW
221, int nH
222, int nD
223)
224{
225 Init();
226
227 (void)Create( nW
228 ,nH
229 ,nD
230 );
231}
232
233wxBitmap::wxBitmap(
234 void* pData
235, long lType
236, int nWidth
237, int nHeight
238, int nDepth
239)
240{
241 Init();
242
243 (void)Create( pData
244 ,lType
245 ,nWidth
246 ,nHeight
247 ,nDepth
248 );
249}
250
251wxBitmap::wxBitmap(
252 const wxString& rFilename
253, long lType
254)
255{
256 Init();
257
258 LoadFile( rFilename
259 ,(int)lType
260 );
261}
262
263bool wxBitmap::Create(
264 int nW
265, int nH
266, int nD
267)
268{
269 HBITMAP hBmp;
270 BITMAPINFOHEADER2 vHeader;
271 BITMAPINFO2 vInfo;
272 HPS hpsScreen;
273 HDC hdcScreen;
274 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
275 SIZEL vSize = {0, 0};
276 LONG lBitCount;
277
278 wxASSERT(vHabmain != NULL);
279
280 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
281 hdcScreen = ::GpiQueryDevice(hpsScreen);
282 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitCount);
283
284 vHeader.cbFix = sizeof(vHeader);
285 vHeader.cx = (USHORT)nW;
286 vHeader.cy = (USHORT)nH;
287 vHeader.cPlanes = (USHORT)nD;
288 vHeader.cBitCount = lBitCount;
289 vHeader.ulCompression = BCA_UNCOMP;
290 vHeader.cxResolution = 0;
291 vHeader.cyResolution = 0;
292 vHeader.cclrUsed = 0;
293 vHeader.cclrImportant = 0;
294 vHeader.usUnits = BRU_METRIC;
295 vHeader.usRecording = BRA_BOTTOMUP;
296 vHeader.usRendering = BRH_NOTHALFTONED;
297 vHeader.cSize1 = 0;
298 vHeader.cSize2 = 0;
299 vHeader.ulColorEncoding = 0;
300 vHeader.ulIdentifier = 0;
301
302 UnRef();
303 m_refData = new wxBitmapRefData;
304
305 GetBitmapData()->m_nWidth = nW;
306 GetBitmapData()->m_nHeight = nH;
307 GetBitmapData()->m_nDepth = nD;
308
309 if (nD > 0)
310 {
311 hBmp = ::GpiCreateBitmap(hpsScreen, &vHeader, 0L, NULL, &vInfo);
312 if (!hBmp)
313 {
314 wxLogLastError("CreateBitmap");
315 }
316 }
317 else
318 {
319 LONG lPlanes;
320
321 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes);
322 hBmp = ::GpiCreateBitmap(hpsScreen, &vHeader, 0L, NULL, &vInfo);
323 if (!hBmp)
324 {
325 wxLogLastError("CreateBitmap");
326 }
327 GetBitmapData()->m_nDepth = wxDisplayDepth();
328 }
329 SetHBITMAP((WXHBITMAP)hBmp);
330
331#if WXWIN_COMPATIBILITY_2
332 GetBitmapData()->m_bOk = hBmp != 0;
333#endif // WXWIN_COMPATIBILITY_2
334
335 return Ok();
336}
337
338bool wxBitmap::LoadFile(
339 const wxString& rFilename
340, long lType
341)
342{
343 HPS hPs = NULLHANDLE;
344
345 UnRef();
346
347 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
348 ,wxBitmapHandler
349 );
350
351 if (pHandler)
352 {
353 m_refData = new wxBitmapRefData;
354
355 return(pHandler->LoadFile( this
356 ,rFilename
357 ,hPs
358 ,lType
359 , -1
360 , -1
361 ));
362 }
363 else
364 {
365 wxImage vImage;
366
367 if (!vImage.LoadFile(rFilename, lType) || !vImage.Ok() )
368 return(FALSE);
369
370 *this = vImage.ConvertToBitmap();
371
372 return(TRUE);
373 }
374}
375
376bool wxBitmap::Create(
377 void* pData
378, long lType
379, int nWidth
380, int nHeight
381, int nDepth
382)
383{
384 UnRef();
385
386 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
387 ,wxBitmapHandler
388 );
389
390 if (!pHandler)
391 {
392 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
393 "type %d defined."), lType);
394
395 return(FALSE);
396 }
397
398 m_refData = new wxBitmapRefData;
399
400 return(pHandler->Create( this
401 ,pData
402 ,lType
403 ,nWidth
404 ,nHeight
405 ,nDepth
406 ));
407}
408
409bool wxBitmap::SaveFile(
410 const wxString& rFilename
411, int lType
412, const wxPalette* pPalette
413)
414{
415 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
416 ,wxBitmapHandler
417 );
418
419 if (pHandler)
420 {
421 return pHandler->SaveFile( this
422 ,rFilename
423 ,lType
424 ,pPalette
425 );
426 }
427 else
428 {
429 // FIXME what about palette? shouldn't we use it?
430 wxImage vImage(*this);
431
432 if (!vImage.Ok())
433 return(FALSE);
434
435 return(vImage.SaveFile( rFilename
436 ,lType
437 ));
438 }
439}
440
441// ----------------------------------------------------------------------------
442// wxBitmap accessors
443// ----------------------------------------------------------------------------
444
445void wxBitmap::SetQuality(
446 int nQ
447)
448{
449 EnsureHasData();
450
451 GetBitmapData()->m_nQuality = nQ;
452}
453
454#if WXWIN_COMPATIBILITY_2
455void wxBitmap::SetOk(
456 bool bOk
457)
458{
459 EnsureHasData();
460
461 GetBitmapData()->m_bOk = bOk;
462}
463#endif // WXWIN_COMPATIBILITY_2
464
465void wxBitmap::SetPalette(
466 const wxPalette& rPalette
467)
468{
469 EnsureHasData();
470
471 GetBitmapData()->m_vBitmapPalette = rPalette;
472}
473
474void wxBitmap::SetMask(
475 wxMask* pMask
476)
477{
478 EnsureHasData();
479
480 GetBitmapData()->m_pBitmapMask = pMask;
481}
482
483// Will try something for OS/2 but not really sure how close
484// to the msw intent this is.
485wxBitmap wxBitmap::GetBitmapForDC(
486 wxDC& rDc
487) const
488{
489 wxMemoryDC vMemDC;
490 wxBitmap vTmpBitmap( this->GetWidth()
491 ,this->GetHeight()
492 ,rDc.GetDepth()
493 );
494 WXHBITMAP vOldBitmap;
495 HPS hMemoryPS;
496 HPS hPs;
497 POINTL vPoint[4];
498 SIZEL vSize = {0,0};
499
500 hMemoryPS = ::GpiCreatePS(vHabmain, (HDC)vMemDC.GetHDC(), &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
501 hPs = ::GpiCreatePS(vHabmain, (HDC)rDc.GetHDC(), &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
502
503 // TODO: Set the points
504
505 vOldBitmap = (WXHBITMAP)::GpiSetBitmap(hPs, (HBITMAP)vTmpBitmap.GetHBITMAP());
506 ::GpiBitBlt(hPs, hMemoryPS, 4L, vPoint, ROP_SRCCOPY, BBO_IGNORE);
507
508 return(vTmpBitmap);
509}
510
511// ----------------------------------------------------------------------------
512// wxMask
513// ----------------------------------------------------------------------------
514
515wxMask::wxMask()
516{
517 m_hMaskBitmap = 0;
518}
519
520// Construct a mask from a bitmap and a colour indicating
521// the transparent area
522wxMask::wxMask(
523 const wxBitmap& rBitmap
524, const wxColour& rColour
525)
526{
527 m_hMaskBitmap = 0;
528 Create( rBitmap
529 ,rColour
530 );
531}
532
533// Construct a mask from a bitmap and a palette index indicating
534// the transparent area
535wxMask::wxMask(
536 const wxBitmap& rBitmap
537, int nPaletteIndex
538)
539{
540 m_hMaskBitmap = 0;
541 Create( rBitmap
542 ,nPaletteIndex
543 );
544}
545
546// Construct a mask from a mono bitmap (copies the bitmap).
547wxMask::wxMask(
548 const wxBitmap& rBitmap
549)
550{
551 m_hMaskBitmap = 0;
552 Create(rBitmap);
553}
554
555wxMask::~wxMask()
556{
557 if (m_hMaskBitmap)
558 ::GpiDeleteBitmap((HBITMAP)m_hMaskBitmap);
559}
560
561// Create a mask from a mono bitmap (copies the bitmap).
562bool wxMask::Create(
563 const wxBitmap& rBitmap
564)
565{
566 BITMAPINFOHEADER2 vHeader;
567 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
568 SIZEL vSize = {0, 0};
569 POINTL vPoint[4];
570
571 if (m_hMaskBitmap)
572 {
573 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
574 m_hMaskBitmap = 0;
575 }
576 if (!rBitmap.Ok() || rBitmap.GetDepth() != 1)
577 {
578 return(FALSE);
579 }
580 vHeader.cbFix = sizeof(vHeader);
581 vHeader.cx = (USHORT)rBitmap.GetWidth();
582 vHeader.cy = (USHORT)rBitmap.GetHeight();
583 vHeader.cPlanes = 1;
584 vHeader.cBitCount = 1;
585
586 m_hMaskBitmap = (WXHBITMAP) ::GpiCreateBitmap( m_hPs
587 ,&vHeader
588 ,0L
589 ,NULL
590 ,NULL
591 );
592
593 HPS srcPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
594 ::GpiSetBitmap(srcPS, (HBITMAP)rBitmap.GetHBITMAP());
595 HPS destPS = ::GpiCreatePS(vHabmain, m_hDc, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
596 ::GpiSetBitmap(srcPS, (HBITMAP)m_hMaskBitmap);
597 // TODO: Set the point array
598 ::GpiBitBlt(destPS, srcPS, 4L, vPoint, ROP_SRCCOPY , BBO_IGNORE);
599
600 ::GpiDestroyPS(srcPS);
601 ::GpiDestroyPS(destPS);
602 return(TRUE);
603}
604
605// Create a mask from a bitmap and a palette index indicating
606// the transparent area
607bool wxMask::Create(
608 const wxBitmap& rBitmap
609, int nPaletteIndex
610)
611{
612 if (m_hMaskBitmap)
613 {
614 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
615 m_hMaskBitmap = 0;
616 }
617 if (rBitmap.Ok() && rBitmap.GetPalette()->Ok())
618 {
619 unsigned char cRed;
620 unsigned char cGreen;
621 unsigned char cBlue;
622
623 if (rBitmap.GetPalette()->GetRGB( nPaletteIndex
624 ,&cRed
625 ,&cGreen
626 ,&cBlue
627 ))
628 {
629 wxColour vTransparentColour( cRed
630 ,cGreen
631 ,cBlue
632 );
633
634 return (Create( rBitmap
635 ,vTransparentColour
636 ));
637 }
638 }
639 return(FALSE);
640}
641
642// Create a mask from a bitmap and a colour indicating
643// the transparent area
644bool wxMask::Create(
645 const wxBitmap& rBitmap
646, const wxColour& rColour
647)
648{
649 BITMAPINFOHEADER2 vHeader;
650 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
651 SIZEL vSize = {0, 0};
652 POINTL vPoint[4];
653
654 if (m_hMaskBitmap)
655 {
656 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
657 m_hMaskBitmap = 0;
658 }
659 if (!rBitmap.Ok())
660 {
661 return(FALSE);
662 }
663
664 // scan the bitmap for the transparent colour and set
665 // the corresponding pixels in the mask to BLACK and
666 // the rest to WHITE
667 COLORREF vMaskColour = OS2RGB(rColour.Red(), rColour.Green(), rColour.Blue());
668
669 vHeader.cbFix = sizeof(vHeader);
670 vHeader.cx = (USHORT)rBitmap.GetWidth();
671 vHeader.cy = (USHORT)rBitmap.GetHeight();
672 vHeader.cPlanes = 1;
673 vHeader.cBitCount = 1;
674
675 m_hMaskBitmap = (WXHBITMAP) ::GpiCreateBitmap( m_hPs
676 ,&vHeader
677 ,0L
678 ,NULL
679 ,NULL
680 );
681
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);
686
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++)
690 {
691 for (int h = 0; h < rBitmap.GetHeight(); h++)
692 {
693 POINTL vPoint;
694
695 vPoint.x = w;
696 vPoint.y = h;
697
698 COLORREF col = ::GpiQueryPel(srcPS, &vPoint);
699
700 if (col == vMaskColour)
701 {
702 ::GpiSetColor(destPS, CLR_WHITE);
703 ::GpiSetPel(destPS, &vPoint);
704 }
705 else
706 {
707 ::GpiSetColor(destPS, CLR_BLACK);
708 ::GpiSetPel(destPS, &vPoint);
709 }
710 }
711 }
712 ::GpiDestroyPS(srcPS);
713 ::GpiDestroyPS(destPS);
714 return(TRUE);
715}
716
717// ----------------------------------------------------------------------------
718// wxBitmapHandler
719// ----------------------------------------------------------------------------
720
721bool wxBitmapHandler::Create(
722 wxGDIImage* pImage
723, void* pData
724, long lFlags
725, int nWidth
726, int nHeight
727, int nDepth
728)
729{
730 wxBitmap* pBitmap = wxDynamicCast( pImage
731 ,wxBitmap
732 );
733
734 return(pBitmap ? Create( pBitmap
735 ,pData
736 ,nWidth
737 ,nHeight
738 ,nDepth
739 ) : FALSE);
740}
741
742bool wxBitmapHandler::Load(
743 wxGDIImage* pImage
744, const wxString& rName
745, HPS hPs
746, long lFlags
747, int nWidth
748, int nHeight
749)
750{
751 wxBitmap* pBitmap = wxDynamicCast( pImage
752 ,wxBitmap
753 );
754
755 return(pBitmap ? LoadFile( pBitmap
756 ,rName
757 ,hPs
758 ,lFlags
759 ,nWidth
760 ,nHeight
761 ) : FALSE);
762}
763
764bool wxBitmapHandler::Save(
765 wxGDIImage* pImage
766, const wxString& rName
767, int lType
768)
769{
770 wxBitmap* pBitmap = wxDynamicCast( pImage
771 ,wxBitmap
772 );
773
774 return(pBitmap ? SaveFile( pBitmap
775 ,rName
776 ,lType
777 ) : FALSE);
778}
779
780bool wxBitmapHandler::Create(
781 wxBitmap* WXUNUSED(pBitmap)
782, void* WXUNUSED(pData)
783, long WXUNUSED(lType)
784, int WXUNUSED(nWidth)
785, int WXUNUSED(nHeight)
786, int WXUNUSED(nDepth)
787)
788{
789 return(FALSE);
790}
791
792bool wxBitmapHandler::LoadFile(
793 wxBitmap* WXUNUSED(pBitmap)
794, const wxString& WXUNUSED(rName)
795, HPS WXUNUSED(hPs)
796, long WXUNUSED(lType)
797, int WXUNUSED(nDesiredWidth)
798, int WXUNUSED(nDesiredHeight)
799)
800{
801 return(FALSE);
802}
803
804bool wxBitmapHandler::SaveFile(
805 wxBitmap* WXUNUSED(pBitmap)
806, const wxString& WXUNUSED(rName)
807, int WXUNUSED(nType)
808, const wxPalette* WXUNUSED(pPalette)
809)
810{
811 return(FALSE);
812}
813