InvertMask fix
[wxWidgets.git] / src / os2 / bitmap.cpp
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
41 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
42 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
43
44 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
45
46 // ============================================================================
47 // implementation
48 // ============================================================================
49
50 // ----------------------------------------------------------------------------
51 // wxBitmapRefData
52 // ----------------------------------------------------------------------------
53
54 wxBitmapRefData::wxBitmapRefData()
55 {
56 m_nQuality = 0;
57 m_pSelectedInto = NULL;
58 m_nNumColors = 0;
59 m_pBitmapMask = NULL;
60 m_hBitmap = (WXHBITMAP) NULL;
61 } // end of wxBitmapRefData::wxBitmapRefData
62
63 void wxBitmapRefData::Free()
64 {
65 wxASSERT_MSG( !m_pSelectedInto,
66 wxT("deleting bitmap still selected into wxMemoryDC") );
67
68 if (m_hBitmap)
69 {
70 if ( !::GpiDeleteBitmap((HBITMAP)m_hBitmap) )
71 {
72 wxLogLastError("GpiDeleteBitmap(hbitmap)");
73 }
74 }
75
76 delete m_pBitmapMask;
77 m_pBitmapMask = NULL;
78 } // end of wxBitmapRefData::Free
79
80 // ----------------------------------------------------------------------------
81 // wxBitmap creation
82 // ----------------------------------------------------------------------------
83
84 // this function should be called from all wxBitmap ctors
85 void wxBitmap::Init()
86 {
87 // m_refData = NULL; done in the base class ctor
88
89 if (wxTheBitmapList)
90 wxTheBitmapList->AddBitmap(this);
91 } // end of wxBitmap::Init
92
93 bool wxBitmap::CopyFromIconOrCursor(
94 const wxGDIImage& rIcon
95 )
96 {
97 HPOINTER hIcon = (HPOINTER)rIcon.GetHandle();
98 POINTERINFO SIconInfo;
99
100 if (!::WinQueryPointerInfo(hIcon, &SIconInfo))
101 {
102 wxLogLastError(wxT("WinQueryPointerInfo"));
103 return FALSE;
104 }
105 wxBitmapRefData* pRefData = new wxBitmapRefData;
106
107 m_refData = pRefData;
108
109 int nWidth = rIcon.GetWidth();
110 int nHeight = rIcon.GetHeight();
111
112 pRefData->m_nWidth = nWidth;
113 pRefData->m_nHeight = nHeight;
114 pRefData->m_nDepth = wxDisplayDepth();
115
116 pRefData->m_hBitmap = (WXHBITMAP)SIconInfo.hbmColor;
117
118 //
119 // No mask in the Info struct in OS/2
120 //
121 return(TRUE);
122 } // end of wxBitmap::CopyFromIconOrCursor
123
124 bool wxBitmap::CopyFromCursor(
125 const wxCursor& rCursor
126 )
127 {
128 UnRef();
129
130 if (!rCursor.Ok())
131 return(FALSE);
132 return(CopyFromIconOrCursor(rCursor));
133 } // end of wxBitmap::CopyFromCursor
134
135 bool wxBitmap::CopyFromIcon(
136 const wxIcon& rIcon
137 )
138 {
139 UnRef();
140
141 if (!rIcon.Ok())
142 return(FALSE);
143
144 return CopyFromIconOrCursor(rIcon);
145 } // end of wxBitmap::CopyFromIcon
146
147 wxBitmap::~wxBitmap()
148 {
149 if (wxTheBitmapList)
150 wxTheBitmapList->DeleteObject(this);
151 } // end of wxBitmap::~wxBitmap
152
153 wxBitmap::wxBitmap(
154 const char zBits[]
155 , int nTheWidth
156 , int nTheHeight
157 , int nNoBits
158 )
159 {
160 Init();
161
162 wxBitmapRefData* pRefData = new wxBitmapRefData;
163 BITMAPINFOHEADER2 vHeader;
164 BITMAPINFO2 vInfo;
165 HDC hDc;
166 HPS hPs;
167 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
168 SIZEL vSize = {0, 0};
169
170 wxASSERT(vHabmain != NULL);
171
172 hDc = ::DevOpenDC(vHabmain, OD_MEMORY, (PSZ)"*", 1L, (PDEVOPENDATA)&vDop, 0L);
173
174 vHeader.cbFix = sizeof(vHeader);
175 vHeader.cx = (USHORT)nTheWidth;
176 vHeader.cy = (USHORT)nTheHeight;
177 vHeader.cPlanes = 1L;
178 vHeader.cBitCount = nNoBits;
179 vHeader.ulCompression = BCA_UNCOMP;
180 vHeader.cxResolution = 0;
181 vHeader.cyResolution = 0;
182 vHeader.cclrUsed = 0;
183 vHeader.cclrImportant = 0;
184 vHeader.usUnits = BRU_METRIC;
185 vHeader.usRecording = BRA_BOTTOMUP;
186 vHeader.usRendering = BRH_NOTHALFTONED;
187 vHeader.cSize1 = 0;
188 vHeader.cSize2 = 0;
189 vHeader.ulColorEncoding = 0;
190 vHeader.ulIdentifier = 0;
191
192 hPs = ::GpiCreatePS(vHabmain, hDc, &vSize, GPIA_ASSOC | PU_PELS);
193 if (hPs == 0)
194 {
195 wxLogLastError("GpiCreatePS Failure");
196 }
197
198 m_refData = pRefData;
199
200 pRefData->m_nWidth = nTheWidth;
201 pRefData->m_nHeight = nTheHeight;
202 pRefData->m_nDepth = nNoBits;
203 pRefData->m_nNumColors = 0;
204 pRefData->m_pSelectedInto = NULL;
205
206 HBITMAP hBmp = ::GpiCreateBitmap(hPs, &vHeader, 0L, NULL, &vInfo);
207 if (!hBmp)
208 {
209 wxLogLastError("CreateBitmap");
210 }
211 SetHBITMAP((WXHBITMAP)hBmp);
212 } // end of wxBitmap::wxBitmap
213
214 //
215 // Create from XPM data
216 //
217 wxBitmap::wxBitmap(
218 char** ppData
219 )
220 {
221 Init();
222
223 (void)Create( (void *)ppData
224 ,wxBITMAP_TYPE_XPM_DATA
225 ,0
226 ,0
227 ,0
228 );
229 } // end of wxBitmap::wxBitmap
230
231 wxBitmap::wxBitmap(
232 const char** ppData
233 )
234 {
235 Init();
236
237 (void)Create( (void *)ppData
238 ,wxBITMAP_TYPE_XPM_DATA
239 ,0
240 ,0
241 ,0
242 );
243 } // end of wxBitmap::wxBitmap
244
245 wxBitmap::wxBitmap(
246 int nW
247 , int nH
248 , int nD
249 )
250 {
251 Init();
252
253 (void)Create( nW
254 ,nH
255 ,nD
256 );
257 } // end of wxBitmap::wxBitmap
258
259 wxBitmap::wxBitmap(
260 void* pData
261 , long lType
262 , int nWidth
263 , int nHeight
264 , int nDepth
265 )
266 {
267 Init();
268
269 (void)Create( pData
270 ,lType
271 ,nWidth
272 ,nHeight
273 ,nDepth
274 );
275 } // end of wxBitmap::wxBitmap
276
277 wxBitmap::wxBitmap(
278 const wxString& rFilename
279 , long lType
280 )
281 {
282 Init();
283
284 LoadFile( rFilename
285 ,(int)lType
286 );
287 } // end of wxBitmap::wxBitmap
288
289 bool wxBitmap::Create(
290 int nW
291 , int nH
292 , int nD
293 )
294 {
295 HBITMAP hBmp;
296 BITMAPINFOHEADER2 vHeader;
297
298 wxASSERT(vHabmain != NULL);
299 UnRef();
300 m_refData = new wxBitmapRefData;
301 GetBitmapData()->m_nWidth = nW;
302 GetBitmapData()->m_nHeight = nH;
303 GetBitmapData()->m_nDepth = nD;
304
305 if (nD > 0)
306 {
307 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
308 SIZEL vSize = {0, 0};
309 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
310 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
311
312 memset(&vHeader, '\0', sizeof(BITMAPINFOHEADER2));
313 vHeader.cbFix = sizeof(BITMAPINFOHEADER2);
314 vHeader.cx = nW;
315 vHeader.cy = nH;
316 vHeader.cPlanes = 1;
317 vHeader.cBitCount = nD;
318
319 hBmp = ::GpiCreateBitmap( hPS
320 ,&vHeader
321 ,0L
322 ,NULL
323 ,NULL
324 );
325 ::GpiDestroyPS(hPS);
326 ::DevCloseDC(hDC);
327 }
328 else
329 {
330 HPS hPSScreen;
331 HDC hDCScreen;
332 LONG lBitCount;
333
334 hPSScreen = ::WinGetScreenPS(HWND_DESKTOP);
335 hDCScreen = ::GpiQueryDevice(hPSScreen);
336 ::DevQueryCaps(hDCScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitCount);
337
338 memset(&vHeader, '\0', sizeof(BITMAPINFOHEADER2));
339 vHeader.cbFix = sizeof(BITMAPINFOHEADER2);
340 vHeader.cx = nW;
341 vHeader.cy = nH;
342 vHeader.cPlanes = 1;
343 vHeader.cBitCount = lBitCount;
344
345 hBmp = ::GpiCreateBitmap( hPSScreen
346 ,&vHeader
347 ,0L
348 ,NULL
349 ,NULL
350 );
351
352 GetBitmapData()->m_nDepth = wxDisplayDepth();
353 ::WinReleasePS(hPSScreen);
354 }
355 SetHBITMAP((WXHBITMAP)hBmp);
356
357 #if WXWIN_COMPATIBILITY_2
358 GetBitmapData()->m_bOk = hBmp != 0;
359 #endif // WXWIN_COMPATIBILITY_2
360
361 return Ok();
362 } // end of wxBitmap::Create
363
364 bool wxBitmap::LoadFile(
365 const wxString& rFilename
366 , long lType
367 )
368 {
369 HPS hPs = NULLHANDLE;
370
371 UnRef();
372
373 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
374 ,wxBitmapHandler
375 );
376
377 if (pHandler)
378 {
379 m_refData = new wxBitmapRefData;
380
381 return(pHandler->LoadFile( this
382 ,rFilename
383 ,hPs
384 ,lType
385 , -1
386 , -1
387 ));
388 }
389 else
390 {
391 wxImage vImage;
392
393 if (!vImage.LoadFile(rFilename, lType) || !vImage.Ok() )
394 return(FALSE);
395
396 *this = vImage.ConvertToBitmap();
397
398 return(TRUE);
399 }
400 } // end of wxBitmap::LoadFile
401
402 bool wxBitmap::Create(
403 void* pData
404 , long lType
405 , int nWidth
406 , int nHeight
407 , int nDepth
408 )
409 {
410 UnRef();
411
412 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
413 ,wxBitmapHandler
414 );
415
416 if (!pHandler)
417 {
418 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
419 "type %d defined."), lType);
420
421 return(FALSE);
422 }
423
424 m_refData = new wxBitmapRefData;
425
426 return(pHandler->Create( this
427 ,pData
428 ,lType
429 ,nWidth
430 ,nHeight
431 ,nDepth
432 ));
433 } // end of wxBitmap::Create
434
435 bool wxBitmap::SaveFile(
436 const wxString& rFilename
437 , int lType
438 , const wxPalette* pPalette
439 )
440 {
441 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
442 ,wxBitmapHandler
443 );
444
445 if (pHandler)
446 {
447 return pHandler->SaveFile( this
448 ,rFilename
449 ,lType
450 ,pPalette
451 );
452 }
453 else
454 {
455 // FIXME what about palette? shouldn't we use it?
456 wxImage vImage(*this);
457
458 if (!vImage.Ok())
459 return(FALSE);
460
461 return(vImage.SaveFile( rFilename
462 ,lType
463 ));
464 }
465 } // end of wxBitmap::SaveFile
466
467 // ----------------------------------------------------------------------------
468 // sub bitmap extraction
469 // ----------------------------------------------------------------------------
470
471 wxBitmap wxBitmap::GetSubBitmap(
472 const wxRect& rRect
473 ) const
474 {
475 wxCHECK_MSG( Ok() &&
476 (rRect.x >= 0) && (rRect.y >= 0) &&
477 (rRect.x + rRect.width <= GetWidth()) &&
478 (rRect.y + rRect.height <= GetHeight()),
479 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
480
481 wxBitmap vRet( rRect.width
482 ,rRect.height
483 ,GetDepth()
484 );
485 wxASSERT_MSG( vRet.Ok(), wxT("GetSubBitmap error") );
486
487
488 //
489 // Copy bitmap data
490 //
491 SIZEL vSize = {0, 0};
492 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
493 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
494 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
495 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
496 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
497 POINTL vPoint[4] = { rRect.x, rRect.y,
498 rRect.x + rRect.width, rRect.y + rRect.height,
499 0, 0, GetWidth(), GetHeight()
500 };
501
502 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetHBITMAP());
503 ::GpiSetBitmap(hPSDst, (HBITMAP) vRet.GetHBITMAP());
504 ::GpiBitBlt( hPSDst
505 ,hPSSrc
506 ,4L
507 ,vPoint
508 ,ROP_SRCCOPY
509 ,BBO_IGNORE
510 );
511
512 //
513 // Copy mask if there is one
514 //
515 if (GetMask())
516 {
517 BITMAPINFOHEADER2 vBmih;
518
519 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
520 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
521 vBmih.cx = rRect.width;
522 vBmih.cy = rRect.height;
523 vBmih.cPlanes = 1;
524 vBmih.cBitCount = 1;
525
526 HBITMAP hBmpMask = ::GpiCreateBitmap( hPSDst
527 ,&vBmih
528 ,0L
529 ,NULL
530 ,NULL
531 );
532
533 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetHBITMAP());
534 ::GpiSetBitmap(hPSDst, (HBITMAP) vRet.GetHBITMAP());
535
536 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetMask()->GetMaskBitmap());
537 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpMask);
538 ::GpiBitBlt( hPSDst
539 ,hPSSrc
540 ,4L
541 ,vPoint
542 ,ROP_SRCCOPY
543 ,BBO_IGNORE
544 );
545
546 wxMask* pMask = new wxMask((WXHBITMAP)hBmpMask);
547 vRet.SetMask(pMask);
548 }
549
550 ::GpiSetBitmap(hPSSrc, NULL);
551 ::GpiSetBitmap(hPSDst, NULL);
552 ::GpiDestroyPS(hPSSrc);
553 ::GpiDestroyPS(hPSDst);
554 ::DevCloseDC(hDCSrc);
555 ::DevCloseDC(hDCDst);
556 return vRet;
557 } // end of wxBitmap::GetSubBitmap
558
559 // ----------------------------------------------------------------------------
560 // wxBitmap accessors
561 // ----------------------------------------------------------------------------
562
563 void wxBitmap::SetQuality(
564 int nQ
565 )
566 {
567 EnsureHasData();
568
569 GetBitmapData()->m_nQuality = nQ;
570 } // end of wxBitmap::SetQuality
571
572 #if WXWIN_COMPATIBILITY_2
573 void wxBitmap::SetOk(
574 bool bOk
575 )
576 {
577 EnsureHasData();
578
579 GetBitmapData()->m_bOk = bOk;
580 } // end of wxBitmap::SetOk
581 #endif // WXWIN_COMPATIBILITY_2
582
583 void wxBitmap::SetPalette(
584 const wxPalette& rPalette
585 )
586 {
587 EnsureHasData();
588
589 GetBitmapData()->m_vBitmapPalette = rPalette;
590 } // end of wxBitmap::SetPalette
591
592 void wxBitmap::SetMask(
593 wxMask* pMask
594 )
595 {
596 EnsureHasData();
597
598 GetBitmapData()->m_pBitmapMask = pMask;
599 } // end of wxBitmap::SetMask
600
601 //
602 // Will try something for OS/2 but not really sure how close
603 // to the msw intent this is.
604 //
605 wxBitmap wxBitmap::GetBitmapForDC(
606 wxDC& rDc
607 ) const
608 {
609 wxMemoryDC vMemDC;
610 wxBitmap vTmpBitmap( this->GetWidth()
611 ,this->GetHeight()
612 ,rDc.GetDepth()
613 );
614 WXHBITMAP vOldBitmap;
615 HPS hMemoryPS;
616 HPS hPs;
617 POINTL vPoint[4];
618 SIZEL vSize = {0,0};
619
620 hMemoryPS = ::GpiCreatePS(vHabmain, (HDC)vMemDC.GetHDC(), &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
621 hPs = ::GpiCreatePS(vHabmain, (HDC)rDc.GetHDC(), &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
622
623 // TODO: Set the points
624
625 vOldBitmap = (WXHBITMAP)::GpiSetBitmap(hPs, (HBITMAP)vTmpBitmap.GetHBITMAP());
626 ::GpiBitBlt(hPs, hMemoryPS, 4L, vPoint, ROP_SRCCOPY, BBO_IGNORE);
627
628 return(vTmpBitmap);
629 } // end of wxBitmap::GetBitmapForDC
630
631 // ----------------------------------------------------------------------------
632 // wxMask
633 // ----------------------------------------------------------------------------
634
635 wxMask::wxMask()
636 {
637 m_hMaskBitmap = 0;
638 } // end of wxMask::wxMask
639
640 // Construct a mask from a bitmap and a colour indicating
641 // the transparent area
642 wxMask::wxMask(
643 const wxBitmap& rBitmap
644 , const wxColour& rColour
645 )
646 {
647 m_hMaskBitmap = 0;
648 Create( rBitmap
649 ,rColour
650 );
651 } // end of wxMask::wxMask
652
653 // Construct a mask from a bitmap and a palette index indicating
654 // the transparent area
655 wxMask::wxMask(
656 const wxBitmap& rBitmap
657 , int nPaletteIndex
658 )
659 {
660 m_hMaskBitmap = 0;
661 Create( rBitmap
662 ,nPaletteIndex
663 );
664 } // end of wxMask::wxMask
665
666 // Construct a mask from a mono bitmap (copies the bitmap).
667 wxMask::wxMask(
668 const wxBitmap& rBitmap
669 )
670 {
671 m_hMaskBitmap = 0;
672 Create(rBitmap);
673 } // end of wxMask::wxMask
674
675 wxMask::~wxMask()
676 {
677 if (m_hMaskBitmap)
678 ::GpiDeleteBitmap((HBITMAP)m_hMaskBitmap);
679 } // end of wxMask::~wxMask
680
681 // Create a mask from a mono bitmap (copies the bitmap).
682 bool wxMask::Create(
683 const wxBitmap& rBitmap
684 )
685 {
686 BITMAPINFOHEADER2 vBmih;
687 SIZEL vSize = {0, 0};
688 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
689 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
690 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
691 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
692 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
693 POINTL vPoint[4] = { 0 ,0, rBitmap.GetWidth(), rBitmap.GetHeight(),
694 0, 0, rBitmap.GetWidth(), rBitmap.GetHeight()
695 };
696
697 if (m_hMaskBitmap)
698 {
699 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
700 m_hMaskBitmap = 0;
701 }
702 if (!rBitmap.Ok() || rBitmap.GetDepth() != 1)
703 {
704 return(FALSE);
705 }
706
707 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
708 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
709 vBmih.cx = rBitmap.GetWidth();
710 vBmih.cy = rBitmap.GetHeight();
711 vBmih.cPlanes = 1;
712 vBmih.cBitCount = 1;
713
714 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
715 ,&vBmih
716 ,0L
717 ,NULL
718 ,NULL
719 );
720
721 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
722 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
723 ::GpiBitBlt( hPSDst
724 ,hPSSrc
725 ,4L
726 ,vPoint
727 ,ROP_SRCCOPY
728 ,BBO_IGNORE
729 );
730
731 ::GpiDestroyPS(hPSSrc);
732 ::GpiDestroyPS(hPSDst);
733 ::DevCloseDC(hDCSrc);
734 ::DevCloseDC(hDCDst);
735 return(TRUE);
736 } // end of wxMask::Create
737
738 // Create a mask from a bitmap and a palette index indicating
739 // the transparent area
740 bool wxMask::Create(
741 const wxBitmap& rBitmap
742 , int nPaletteIndex
743 )
744 {
745 if (m_hMaskBitmap)
746 {
747 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
748 m_hMaskBitmap = 0;
749 }
750 if (rBitmap.Ok() && rBitmap.GetPalette()->Ok())
751 {
752 unsigned char cRed;
753 unsigned char cGreen;
754 unsigned char cBlue;
755
756 if (rBitmap.GetPalette()->GetRGB( nPaletteIndex
757 ,&cRed
758 ,&cGreen
759 ,&cBlue
760 ))
761 {
762 wxColour vTransparentColour( cRed
763 ,cGreen
764 ,cBlue
765 );
766
767 return (Create( rBitmap
768 ,vTransparentColour
769 ));
770 }
771 }
772 return(FALSE);
773 } // end of wxMask::Create
774
775 // Create a mask from a bitmap and a colour indicating
776 // the transparent area
777 bool wxMask::Create(
778 const wxBitmap& rBitmap
779 , const wxColour& rColour
780 )
781 {
782 bool bOk = TRUE;
783 COLORREF vMaskColour = OS2RGB( rColour.Red()
784 ,rColour.Green()
785 ,rColour.Blue()
786 );
787 BITMAPINFOHEADER2 vBmih;
788 SIZEL vSize = {0, 0};
789 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
790 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
791 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
792 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
793 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
794 POINTL vPoint[4] = { 0 ,0, rBitmap.GetWidth(), rBitmap.GetHeight(),
795 0, 0, rBitmap.GetWidth(), rBitmap.GetHeight()
796 };
797
798 if (m_hMaskBitmap)
799 {
800 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
801 m_hMaskBitmap = 0;
802 }
803 if (!rBitmap.Ok())
804 {
805 return(FALSE);
806 }
807
808 //
809 // Scan the bitmap for the transparent colour and set
810 // the corresponding pixels in the mask to BLACK and
811 // the rest to WHITE
812 //
813
814 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
815 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
816 vBmih.cx = rBitmap.GetWidth();
817 vBmih.cy = rBitmap.GetHeight();
818 vBmih.cPlanes = 1;
819 vBmih.cBitCount = 1;
820
821 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
822 ,&vBmih
823 ,0L
824 ,NULL
825 ,NULL
826 );
827
828 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
829 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
830
831 //
832 // This is not very efficient, but I can't think
833 // of a better way of doing it
834 //
835 for (int w = 0; w < rBitmap.GetWidth(); w++)
836 {
837 for (int h = 0; h < rBitmap.GetHeight(); h++)
838 {
839 POINTL vPt = {w, h};
840 COLORREF vCol = (COLORREF)::GpiQueryPel(hPSSrc, &vPt);
841 if (vCol == (COLORREF)CLR_NOINDEX)
842 {
843 //
844 // Doesn't make sense to continue
845 //
846 bOk = FALSE;
847 break;
848 }
849
850 if (vCol == vMaskColour)
851 {
852 ::GpiSetColor(hPSDst, OS2RGB(0, 0, 0));
853 ::GpiSetPel(hPSDst, &vPt);
854 }
855 else
856 {
857 ::GpiSetColor(hPSDst, OS2RGB(255, 255, 255));
858 ::GpiSetPel(hPSDst, &vPt);
859 }
860 }
861 }
862 ::GpiSetBitmap(hPSSrc, NULL);
863 ::GpiSetBitmap(hPSDst, NULL);
864 ::GpiDestroyPS(hPSSrc);
865 ::GpiDestroyPS(hPSDst);
866 ::DevCloseDC(hDCSrc);
867 ::DevCloseDC(hDCDst);
868 return(TRUE);
869 } // end of wxMask::Create
870
871 // ----------------------------------------------------------------------------
872 // wxBitmapHandler
873 // ----------------------------------------------------------------------------
874
875 bool wxBitmapHandler::Create(
876 wxGDIImage* pImage
877 , void* pData
878 , long lFlags
879 , int nWidth
880 , int nHeight
881 , int nDepth
882 )
883 {
884 wxBitmap* pBitmap = wxDynamicCast( pImage
885 ,wxBitmap
886 );
887
888 return(pBitmap ? Create( pBitmap
889 ,pData
890 ,nWidth
891 ,nHeight
892 ,nDepth
893 ) : FALSE);
894 }
895
896 bool wxBitmapHandler::Load(
897 wxGDIImage* pImage
898 , const wxString& rName
899 , HPS hPs
900 , long lFlags
901 , int nWidth
902 , int nHeight
903 )
904 {
905 wxBitmap* pBitmap = wxDynamicCast( pImage
906 ,wxBitmap
907 );
908
909 return(pBitmap ? LoadFile( pBitmap
910 ,rName
911 ,hPs
912 ,lFlags
913 ,nWidth
914 ,nHeight
915 ) : FALSE);
916 }
917
918 bool wxBitmapHandler::Save(
919 wxGDIImage* pImage
920 , const wxString& rName
921 , int lType
922 )
923 {
924 wxBitmap* pBitmap = wxDynamicCast( pImage
925 ,wxBitmap
926 );
927
928 return(pBitmap ? SaveFile( pBitmap
929 ,rName
930 ,lType
931 ) : FALSE);
932 }
933
934 bool wxBitmapHandler::Create(
935 wxBitmap* WXUNUSED(pBitmap)
936 , void* WXUNUSED(pData)
937 , long WXUNUSED(lType)
938 , int WXUNUSED(nWidth)
939 , int WXUNUSED(nHeight)
940 , int WXUNUSED(nDepth)
941 )
942 {
943 return(FALSE);
944 }
945
946 bool wxBitmapHandler::LoadFile(
947 wxBitmap* WXUNUSED(pBitmap)
948 , const wxString& WXUNUSED(rName)
949 , HPS WXUNUSED(hPs)
950 , long WXUNUSED(lType)
951 , int WXUNUSED(nDesiredWidth)
952 , int WXUNUSED(nDesiredHeight)
953 )
954 {
955 return(FALSE);
956 }
957
958 bool wxBitmapHandler::SaveFile(
959 wxBitmap* WXUNUSED(pBitmap)
960 , const wxString& WXUNUSED(rName)
961 , int WXUNUSED(nType)
962 , const wxPalette* WXUNUSED(pPalette)
963 )
964 {
965 return(FALSE);
966 }
967
968 // ----------------------------------------------------------------------------
969 // Utility functions
970 // ----------------------------------------------------------------------------
971 HBITMAP wxInvertMask(
972 HBITMAP hBmpMask
973 , int nWidth
974 , int nHeight
975 )
976 {
977 HBITMAP hBmpInvMask = 0;
978
979 wxCHECK_MSG( hBmpMask, 0, _T("invalid bitmap in wxInvertMask") );
980
981 //
982 // Get width/height from the bitmap if not given
983 //
984 if (!nWidth || !nHeight)
985 {
986 BITMAPINFOHEADER2 vBmhdr;
987
988 ::GpiQueryBitmapInfoHeader( hBmpMask
989 ,&vBmhdr
990 );
991 nWidth = (int)vBmhdr.cx;
992 nHeight = (int)vBmhdr.cy;
993 }
994
995 BITMAPINFOHEADER2 vBmih;
996 SIZEL vSize = {0, 0};
997 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
998 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
999 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1000 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1001 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1002 POINTL vPoint[4] = { 0 ,0, nWidth, nHeight,
1003 0, 0, nWidth, nHeight
1004 };
1005
1006 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1007 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1008 vBmih.cx = nWidth;
1009 vBmih.cy = nHeight;
1010 vBmih.cPlanes = 1;
1011 vBmih.cBitCount = 1;
1012
1013 hBmpInvMask = ::GpiCreateBitmap( hPSDst
1014 ,&vBmih
1015 ,0L
1016 ,NULL
1017 ,NULL
1018 );
1019
1020 ::GpiSetBitmap(hPSSrc, (HBITMAP) hBmpMask);
1021 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpInvMask);
1022
1023 ::GpiBitBlt( hPSDst
1024 ,hPSSrc
1025 ,4L
1026 ,vPoint
1027 ,ROP_SRCINVERT
1028 ,BBO_IGNORE
1029 );
1030
1031 ::GpiDestroyPS(hPSSrc);
1032 ::GpiDestroyPS(hPSDst);
1033 ::DevCloseDC(hDCSrc);
1034 ::DevCloseDC(hDCDst);
1035
1036 return hBmpInvMask;
1037 } // end of WxWinGdi_InvertMask