]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/bitmap.cpp
Typo fix
[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#include "wx/xpmdecod.h"
37
38// ----------------------------------------------------------------------------
39// macros
40// ----------------------------------------------------------------------------
41
42IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
43IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
44
45IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
46
47// ============================================================================
48// implementation
49// ============================================================================
50
51// ----------------------------------------------------------------------------
52// wxBitmapRefData
53// ----------------------------------------------------------------------------
54
55wxBitmapRefData::wxBitmapRefData()
56{
57 m_nQuality = 0;
58 m_pSelectedInto = NULL;
59 m_nNumColors = 0;
60 m_pBitmapMask = NULL;
61 m_hBitmap = (WXHBITMAP) NULL;
62} // end of wxBitmapRefData::wxBitmapRefData
63
64void wxBitmapRefData::Free()
65{
66 wxASSERT_MSG( !m_pSelectedInto,
67 wxT("deleting bitmap still selected into wxMemoryDC") );
68
69 if (m_hBitmap)
70 {
71 if (!::GpiDeleteBitmap((HBITMAP)m_hBitmap))
72 {
73 wxLogLastError("GpiDeleteBitmap(hbitmap)");
74 }
75 }
76
77 delete m_pBitmapMask;
78 m_pBitmapMask = NULL;
79} // end of wxBitmapRefData::Free
80
81// ----------------------------------------------------------------------------
82// wxBitmap creation
83// ----------------------------------------------------------------------------
84
85// this function should be called from all wxBitmap ctors
86void wxBitmap::Init()
87{
88} // end of wxBitmap::Init
89
90bool wxBitmap::CopyFromIconOrCursor(
91 const wxGDIImage& rIcon
92)
93{
94 HPOINTER hIcon = (HPOINTER)rIcon.GetHandle();
95 POINTERINFO SIconInfo;
96
97 if (!::WinQueryPointerInfo(hIcon, &SIconInfo))
98 {
99 wxLogLastError(wxT("WinQueryPointerInfo"));
100 return FALSE;
101 }
102 wxBitmapRefData* pRefData = new wxBitmapRefData;
103
104 m_refData = pRefData;
105
106 int nWidth = rIcon.GetWidth();
107 int nHeight = rIcon.GetHeight();
108
109 pRefData->m_nWidth = nWidth;
110 pRefData->m_nHeight = nHeight;
111 pRefData->m_nDepth = wxDisplayDepth();
112
113 pRefData->m_hBitmap = (WXHBITMAP)SIconInfo.hbmColor;
114
115 //
116 // No mask in the Info struct in OS/2
117 //
118 return(TRUE);
119} // end of wxBitmap::CopyFromIconOrCursor
120
121bool wxBitmap::CopyFromCursor(
122 const wxCursor& rCursor
123)
124{
125 UnRef();
126
127 if (!rCursor.Ok())
128 return(FALSE);
129 return(CopyFromIconOrCursor(rCursor));
130} // end of wxBitmap::CopyFromCursor
131
132bool wxBitmap::CopyFromIcon(
133 const wxIcon& rIcon
134)
135{
136 UnRef();
137
138 if (!rIcon.Ok())
139 return(FALSE);
140
141 return CopyFromIconOrCursor(rIcon);
142} // end of wxBitmap::CopyFromIcon
143
144wxBitmap::~wxBitmap()
145{
146} // end of wxBitmap::~wxBitmap
147
148wxBitmap::wxBitmap(
149 const char zBits[]
150, int nWidth
151, int nHeight
152, int nDepth
153)
154{
155 Init();
156
157 wxBitmapRefData* pRefData = new wxBitmapRefData;
158 BITMAPINFOHEADER2 vHeader;
159 BITMAPINFO2 vInfo;
160 HDC hDc;
161 HPS hPs;
162 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
163 SIZEL vSize = {0, 0};
164 char* pzData;
165
166 wxASSERT(vHabmain != NULL);
167
168 m_refData = pRefData;
169
170 pRefData->m_nWidth = nWidth;
171 pRefData->m_nHeight = nHeight;
172 pRefData->m_nDepth = nDepth;
173 pRefData->m_nNumColors = 0;
174 pRefData->m_pSelectedInto = NULL;
175
176 hDc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
177 hPs = ::GpiCreatePS(vHabmain, hDc, &vSize, GPIA_ASSOC | PU_PELS);
178 if (hPs == 0)
179 {
180 wxLogLastError("GpiCreatePS Failure");
181 }
182
183 if (nDepth == 1)
184 {
185 //
186 // We assume that it is in XBM format which is not quite the same as
187 // the format CreateBitmap() wants because the order of bytes in the
188 // line is inversed!
189 //
190 const size_t nBytesPerLine = (nWidth + 7) / 8;
191 const size_t nPadding = nBytesPerLine % 2;
192 const size_t nLen = nHeight * (nPadding + nBytesPerLine);
193 const char* pzSrc = zBits;
194 int nRows;
195 size_t nCols;
196
197 pzData = (char *)malloc(nLen);
198
199 char* pzDst = pzData;
200
201 for (nRows = 0; nRows < nHeight; nRows++)
202 {
203 for (nCols = 0; nCols < nBytesPerLine; nCols++)
204 {
205 unsigned char ucVal = *pzSrc++;
206 unsigned char ucReversed = 0;
207 int nBits;
208
209 for (nBits = 0; nBits < 8; nBits++)
210 {
211 ucReversed <<= 1;
212 ucReversed |= (ucVal & 0x01);
213 ucVal >>= 1;
214 }
215 *pzDst++ = ucReversed;
216 }
217 if (nPadding)
218 *pzDst++ = 0;
219 }
220 }
221 else
222 {
223 //
224 // Bits should already be in Windows standard format
225 //
226 pzData = (char *)zBits; // const_cast is harmless
227 }
228
229 memset(&vHeader, '\0', 16);
230 vHeader.cbFix = 16;
231 vHeader.cx = (USHORT)nWidth;
232 vHeader.cy = (USHORT)nHeight;
233 vHeader.cPlanes = 1L;
234 vHeader.cBitCount = nDepth;
235 vHeader.usReserved = 0;
236
237 memset(&vInfo, '\0', 16);
238 vInfo.cbFix = 16;
239 vInfo.cx = (USHORT)nWidth;
240 vInfo.cy = (USHORT)nHeight;
241 vInfo.cPlanes = 1L;
242 vInfo.cBitCount = nDepth;
243
244 HBITMAP hBmp = ::GpiCreateBitmap(hPs, &vHeader, CBM_INIT, (PBYTE)pzData, &vInfo);
245
246 if (!hBmp)
247 {
248 wxLogLastError("CreateBitmap");
249 }
250 ::GpiDestroyPS(hPs);
251 ::DevCloseDC(hDc);
252 SetHBITMAP((WXHBITMAP)hBmp);
253} // end of wxBitmap::wxBitmap
254
255wxBitmap::wxBitmap(
256 int nW
257, int nH
258, int nD
259)
260{
261 Init();
262
263 (void)Create( nW
264 ,nH
265 ,nD
266 );
267} // end of wxBitmap::wxBitmap
268
269wxBitmap::wxBitmap(
270 void* pData
271, long lType
272, int nWidth
273, int nHeight
274, int nDepth
275)
276{
277 Init();
278
279 (void)Create( pData
280 ,lType
281 ,nWidth
282 ,nHeight
283 ,nDepth
284 );
285} // end of wxBitmap::wxBitmap
286
287wxBitmap::wxBitmap(
288 const wxString& rFilename
289, long lType
290)
291{
292 Init();
293
294 LoadFile( rFilename
295 ,(int)lType
296 );
297} // end of wxBitmap::wxBitmap
298
299bool wxBitmap::Create(
300 int nW
301, int nH
302, int nD
303)
304{
305 HBITMAP hBmp;
306 BITMAPINFOHEADER2 vHeader;
307
308 wxASSERT(vHabmain != NULL);
309 UnRef();
310 m_refData = new wxBitmapRefData;
311 GetBitmapData()->m_nWidth = nW;
312 GetBitmapData()->m_nHeight = nH;
313 GetBitmapData()->m_nDepth = nD;
314
315 if (nD > 0)
316 {
317 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
318 SIZEL vSize = {0, 0};
319 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
320 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
321
322 memset(&vHeader, '\0', 16);
323 vHeader.cbFix = 16;
324 vHeader.cx = nW;
325 vHeader.cy = nH;
326 vHeader.cPlanes = 1;
327 vHeader.cBitCount = nD;
328
329 hBmp = ::GpiCreateBitmap( hPS
330 ,&vHeader
331 ,0L
332 ,NULL
333 ,NULL
334 );
335 ::GpiDestroyPS(hPS);
336 ::DevCloseDC(hDC);
337 }
338 else
339 {
340 HPS hPSScreen;
341 HDC hDCScreen;
342 LONG lBitCount;
343
344 hPSScreen = ::WinGetScreenPS(HWND_DESKTOP);
345 hDCScreen = ::GpiQueryDevice(hPSScreen);
346 ::DevQueryCaps(hDCScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitCount);
347
348 memset(&vHeader, '\0', 16);
349 vHeader.cbFix = 16;
350 vHeader.cx = nW;
351 vHeader.cy = nH;
352 vHeader.cPlanes = 1;
353 vHeader.cBitCount = lBitCount;
354
355 hBmp = ::GpiCreateBitmap( hPSScreen
356 ,&vHeader
357 ,0L
358 ,NULL
359 ,NULL
360 );
361
362 GetBitmapData()->m_nDepth = wxDisplayDepth();
363 ::WinReleasePS(hPSScreen);
364 }
365 SetHBITMAP((WXHBITMAP)hBmp);
366
367#if WXWIN_COMPATIBILITY_2
368 GetBitmapData()->m_bOk = hBmp != 0;
369#endif // WXWIN_COMPATIBILITY_2
370
371 return Ok();
372} // end of wxBitmap::Create
373
374bool wxBitmap::CreateFromXpm(
375 const char** ppData
376)
377{
378#if wxUSE_IMAGE && wxUSE_XPM
379 Init();
380
381 wxCHECK_MSG(ppData != NULL, FALSE, wxT("invalid bitmap data"))
382
383 wxXPMDecoder vDecoder;
384 wxImage vImg = vDecoder.ReadData(ppData);
385
386 wxCHECK_MSG(vImg.Ok(), FALSE, wxT("invalid bitmap data"))
387
388 *this = wxBitmap(vImg);
389 return TRUE;
390#else
391 return FALSE;
392#endif
393} // end of wxBitmap::CreateFromXpm
394
395bool wxBitmap::LoadFile(
396 const wxString& rFilename
397, long lType
398)
399{
400 HPS hPs = NULLHANDLE;
401
402 UnRef();
403
404 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
405 ,wxBitmapHandler
406 );
407
408 if (pHandler)
409 {
410 m_refData = new wxBitmapRefData;
411
412 return(pHandler->LoadFile( this
413 ,rFilename
414 ,hPs
415 ,lType
416 , -1
417 , -1
418 ));
419 }
420 else
421 {
422 wxImage vImage;
423
424 if (!vImage.LoadFile(rFilename, lType) || !vImage.Ok() )
425 return(FALSE);
426
427 *this = wxBitmap(vImage);
428
429 return(TRUE);
430 }
431} // end of wxBitmap::LoadFile
432
433bool wxBitmap::Create(
434 void* pData
435, long lType
436, int nWidth
437, int nHeight
438, int nDepth
439)
440{
441 UnRef();
442
443 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
444 ,wxBitmapHandler
445 );
446
447 if (!pHandler)
448 {
449 wxLogDebug(wxT("Failed to create bitmap: no bitmap handler for "
450 "type %d defined."), lType);
451
452 return(FALSE);
453 }
454
455 m_refData = new wxBitmapRefData;
456
457 return(pHandler->Create( this
458 ,pData
459 ,lType
460 ,nWidth
461 ,nHeight
462 ,nDepth
463 ));
464} // end of wxBitmap::Create
465
466bool wxBitmap::SaveFile(
467 const wxString& rFilename
468, int lType
469, const wxPalette* pPalette
470)
471{
472 wxBitmapHandler* pHandler = wxDynamicCast( FindHandler(lType)
473 ,wxBitmapHandler
474 );
475
476 if (pHandler)
477 {
478 return pHandler->SaveFile( this
479 ,rFilename
480 ,lType
481 ,pPalette
482 );
483 }
484 else
485 {
486 // FIXME what about palette? shouldn't we use it?
487 wxImage vImage = ConvertToImage();
488
489 if (!vImage.Ok())
490 return(FALSE);
491
492 return(vImage.SaveFile( rFilename
493 ,lType
494 ));
495 }
496} // end of wxBitmap::SaveFile
497
498
499// ----------------------------------------------------------------------------
500// wxImage-wxBitmap convertion
501// ----------------------------------------------------------------------------
502
503bool wxBitmap::CreateFromImage (
504 const wxImage& rImage
505, int nDepth
506)
507{
508 wxCHECK_MSG(rImage.Ok(), FALSE, wxT("invalid image"));
509 m_refData = new wxBitmapRefData();
510
511
512 int nSizeLimit = 1024 * 768 * 3;
513 int nWidth = rImage.GetWidth();
514 int nBmpHeight = rImage.GetHeight();
515 int nBytePerLine = nWidth * 3;
516 int nSizeDWORD = sizeof(DWORD);
517 int nLineBoundary = nBytePerLine % nSizeDWORD;
518 int nPadding = 0;
519
520 if (nLineBoundary > 0)
521 {
522 nPadding = nSizeDWORD - nLineBoundary;
523 nBytePerLine += nPadding;
524 }
525
526 //
527 // Calc the number of DIBs and heights of DIBs
528 //
529 int nNumDIB = 1;
530 int nHRemain = 0;
531 int nHeight = nSizeLimit / nBytePerLine;
532
533 if (nHeight >= nBmpHeight)
534 nHeight = nBmpHeight;
535 else
536 {
537 nNumDIB = nBmpHeight / nHeight;
538 nHRemain = nBmpHeight % nHeight;
539 if (nHRemain > 0)
540 nNumDIB++;
541 }
542
543 //
544 // Set bitmap parameters
545 //
546 wxCHECK_MSG(rImage.Ok(), FALSE, wxT("invalid image"));
547 SetWidth(nWidth);
548 SetHeight(nBmpHeight);
549 if (nDepth == -1)
550 nDepth = 16; // wxDisplayDepth();
551 SetDepth(nDepth);
552
553#if wxUSE_PALETTE
554 //
555 // Copy the palette from the source image
556 //
557 SetPalette(rImage.GetPalette());
558#endif // wxUSE_PALETTE
559
560 //
561 // Create a DIB header
562 //
563 BITMAPINFOHEADER2 vHeader;
564 BITMAPINFO2 vInfo;
565
566 //
567 // Fill in the DIB header
568 //
569 memset(&vHeader, '\0', 16);
570 vHeader.cbFix = 16;
571 vHeader.cx = (ULONG)nWidth;
572 vHeader.cy = (ULONG)nHeight;
573 vHeader.cPlanes = 1L;
574 vHeader.cBitCount = 24;
575
576 memset(&vInfo, '\0', 16);
577 vInfo.cbFix = 16;
578 vInfo.cx = (ULONG)nWidth;
579 vInfo.cy = (ULONG)nHeight;
580 vInfo.cPlanes = 1L;
581 vInfo.cBitCount = 24;
582 //
583 // Memory for DIB data
584 //
585 unsigned char* pucBits;
586
587 pucBits = (unsigned char *)malloc(nBytePerLine * nHeight);
588 if(!pucBits)
589 {
590 wxFAIL_MSG(wxT("could not allocate memory for DIB"));
591 return FALSE;
592 }
593
594 //
595 // Create and set the device-dependent bitmap
596 //
597 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
598 SIZEL vSize = {0, 0};
599 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
600 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
601 LONG lScans;
602 HDC hDCScreen = ::WinOpenWindowDC(HWND_DESKTOP);
603 HPS hPSScreen;
604 HBITMAP hBmp;
605 HBITMAP hBmpOld;
606
607 hBmp = ::GpiCreateBitmap( hPS
608 ,&vHeader
609 ,0L
610 ,NULL
611 ,NULL
612 );
613 hBmpOld = ::GpiSetBitmap(hPS, hBmp);
614#if wxUSE_PALETTE
615 HPAL hOldPalette = NULLHANDLE;
616 if (rImage.GetPalette().Ok())
617 {
618 hOldPalette = ::GpiSelectPalette(hPS, (HPAL)rImage.GetPalette().GetHPALETTE());
619 }
620#endif // wxUSE_PALETTE
621
622 //
623 // Copy image data into DIB data and then into DDB (in a loop)
624 //
625 unsigned char* pData = rImage.GetData();
626 int i;
627 int j;
628 int n;
629 int nOrigin = 0;
630 unsigned char* ptdata = pData;
631 unsigned char* ptbits;
632
633 for (n = 0; n < nNumDIB; n++)
634 {
635 if (nNumDIB > 1 && n == nNumDIB - 1 && nHRemain > 0)
636 {
637 //
638 // Redefine height and size of the (possibly) last smaller DIB
639 // memory is not reallocated
640 //
641 nHeight = nHRemain;
642 vHeader.cy = (DWORD)(nHeight);
643 vHeader.cbImage = nBytePerLine * nHeight;
644 }
645 ptbits = pucBits;
646 for (j = 0; j < nHeight; j++)
647 {
648 for (i = 0; i < nWidth; i++)
649 {
650 *(ptbits++) = *(ptdata + 2);
651 *(ptbits++) = *(ptdata + 1);
652 *(ptbits++) = *(ptdata);
653 ptdata += 3;
654 }
655 for (i = 0; i < nPadding; i++)
656 *(ptbits++) = 0;
657 }
658
659 //
660 // Have to do something similar to WIN32's StretchDIBits, use GpiBitBlt
661 // in combination with setting the bits into the selected bitmap
662 //
663 lScans = ::GpiSetBitmapBits( hPS
664 ,0 // Start at the bottom
665 ,(LONG)nHeight // One line per scan
666 ,(PBYTE)pucBits
667 ,&vInfo
668 );
669 hPSScreen = ::GpiCreatePS( vHabmain
670 ,hDCScreen
671 ,&vSize
672 ,PU_PELS | GPIA_ASSOC
673 );
674
675 POINTL vPoint[4] = { 0, nOrigin,
676 nWidth, nHeight,
677 0, 0, nWidth, nHeight
678 };
679
680
681 ::GpiBitBlt( hPSScreen
682 ,hPS
683 ,4
684 ,vPoint
685 ,ROP_SRCCOPY
686 ,BBO_IGNORE
687 );
688 ::GpiDestroyPS(hPSScreen);
689 nOrigin += nHeight;
690 }
691 SetHBITMAP((WXHBITMAP)hBmp);
692#if wxUSE_PALETTE
693 if (hOldPalette)
694 ::GpiSelectPalette(hPS, hOldPalette);
695#endif // wxUSE_PALETTE
696
697 //
698 // Similarly, created an mono-bitmap for the possible mask
699 //
700 if (rImage.HasMask())
701 {
702 hBmp = ::GpiCreateBitmap( hPS
703 ,&vHeader
704 ,0L
705 ,NULL
706 ,NULL
707 );
708 memset(&vHeader, '\0', sizeof(BITMAPINFOHEADER2));
709 hBmpOld = ::GpiSetBitmap(hPS, hBmp);
710
711 vHeader.cbFix = sizeof(BITMAPINFOHEADER2);
712 vHeader.cx = nWidth;
713 vHeader.cy = nHeight;
714 vHeader.cPlanes = 1;
715 vHeader.cBitCount = 1;
716 hBmp = ::GpiCreateBitmap( hPS
717 ,&vHeader
718 ,0L
719 ,NULL
720 ,NULL
721 );
722 if (nNumDIB == 1)
723 nHeight = nBmpHeight;
724 else
725 nHeight = nSizeLimit / nBytePerLine;
726 vHeader.cy = (DWORD)(nHeight);
727 vHeader.cbImage = nBytePerLine * nHeight;
728 nOrigin = 0;
729
730 unsigned char cRed = rImage.GetMaskRed();
731 unsigned char cGreen = rImage.GetMaskGreen();
732 unsigned char cBlue = rImage.GetMaskBlue();
733 unsigned char cZero = 0;
734 unsigned char cOne = 255;
735
736 ptdata = pData;
737 for (n = 0; n < nNumDIB; n++)
738 {
739 if (nNumDIB > 1 && n == nNumDIB - 1 && nHRemain > 0)
740 {
741 //
742 // Redefine height and size of the (possibly) last smaller DIB
743 // memory is not reallocated
744 //
745 nHeight = nHRemain;
746 vHeader.cy = (DWORD)(nHeight);
747 vHeader.cbImage = nBytePerLine * nHeight;
748 }
749 ptbits = pucBits;
750 for (int j = 0; j < nHeight; j++)
751 {
752 for (i = 0; i < nWidth; i++)
753 {
754 if ((*(ptdata++) != cRed) || (*(ptdata++) != cGreen) || (*(ptdata++) != cBlue))
755 {
756 *(ptbits++) = cOne;
757 *(ptbits++) = cOne;
758 *(ptbits++) = cOne;
759 }
760 else
761 {
762 *(ptbits++) = cZero;
763 *(ptbits++) = cZero;
764 *(ptbits++) = cZero;
765 }
766 }
767 for (i = 0; i < nPadding; i++)
768 *(ptbits++) = cZero;
769 }
770 lScans = ::GpiSetBitmapBits( hPS
771 ,0 // Start at the bottom
772 ,(LONG)nHeight // One line per scan
773 ,(PBYTE)pucBits
774 ,&vInfo
775 );
776 hPSScreen = ::GpiCreatePS( vHabmain
777 ,hDCScreen
778 ,&vSize
779 ,PU_PELS | GPIA_ASSOC
780 );
781 POINTL vPoint2[4] = { 0, nOrigin,
782 nWidth, nHeight,
783 0, 0, nWidth, nHeight
784 };
785 ::GpiBitBlt( hPSScreen
786 ,hPS
787 ,4
788 ,vPoint2
789 ,ROP_SRCCOPY
790 ,BBO_IGNORE
791 );
792 ::GpiDestroyPS(hPSScreen);
793 nOrigin += nHeight;
794 }
795
796 //
797 // Create a wxMask object
798 //
799 wxMask* pMask = new wxMask();
800
801 pMask->SetMaskBitmap((WXHBITMAP)hBmp);
802 SetMask(pMask);
803 hBmpOld = ::GpiSetBitmap(hPS, hBmp);
804 }
805
806 //
807 // Free allocated resources
808 //
809 ::GpiSetBitmap(hPS, NULLHANDLE);
810 ::GpiDestroyPS(hPS);
811 ::DevCloseDC(hDC);
812 free(pucBits);
813 return TRUE;
814} // end of wxBitmap::CreateFromImage
815
816wxImage wxBitmap::ConvertToImage() const
817{
818 wxImage vImage;
819
820 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
821
822 //
823 // Create an wxImage object
824 //
825 int nWidth = GetWidth();
826 int nHeight = GetHeight();
827 int nDevWidth;
828 int nDevHeight;
829 int nBytePerLine = nWidth * 3;
830 int nSizeDWORD = sizeof(DWORD);
831 int nLineBoundary = nBytePerLine % nSizeDWORD;
832 int nPadding = 0;
833 unsigned char* pData;
834 unsigned char* lpBits;
835 long lScans;
836 BITMAPINFOHEADER2 vDIBh;
837 BITMAPINFO2 vDIBInfo;
838 HDC hDCMem;
839 PSZ pszData[4] = { "Display", NULL, NULL, NULL };
840 HPS hPSMem;
841 HPS hPS;
842 SIZEL vSizlPage = {0,0};
843 HBITMAP hBitmap;
844
845 vImage.Create( nWidth
846 ,nHeight
847 );
848 pData = vImage.GetData();
849 if(!pData)
850 {
851 wxFAIL_MSG( wxT("could not allocate data for image") );
852 return wxNullImage;
853 }
854 if(nLineBoundary > 0)
855 {
856 nPadding = nSizeDWORD - nLineBoundary;
857 nBytePerLine += nPadding;
858 }
859 wxDisplaySize( &nDevWidth
860 ,&nDevHeight
861 );
862 //
863 // Create and fill a DIB header
864 //
865 memset(&vDIBh, '\0', 16);
866 vDIBh.cbFix = 16;
867 vDIBh.cx = nWidth;
868 vDIBh.cy = nHeight;
869 vDIBh.cPlanes = 1;
870 vDIBh.cBitCount = 24;
871
872 memset(&vDIBInfo, '\0', 16);
873 vDIBInfo.cbFix = 16;
874 vDIBInfo.cx = nWidth;
875 vDIBInfo.cy = nHeight;
876 vDIBInfo.cPlanes = 1;
877 vDIBInfo.cBitCount = 24;
878
879 lpBits = (unsigned char *)malloc(nBytePerLine * nHeight);
880 if (!lpBits)
881 {
882 wxFAIL_MSG(wxT("could not allocate data for DIB"));
883 free(pData);
884 return wxNullImage;
885 }
886
887 //
888 // Copy data from the device-dependent bitmap to the DIB
889 //
890 hDCMem = ::DevOpenDC( vHabmain
891 ,OD_MEMORY
892 ,"*"
893 ,4
894 ,(PDEVOPENDATA)pszData
895 ,NULLHANDLE
896 );
897 hPSMem = ::GpiCreatePS( vHabmain
898 ,hDCMem
899 ,&vSizlPage
900 ,PU_PELS | GPIA_ASSOC | GPIT_MICRO
901 );
902 hBitmap = ::GpiCreateBitmap( hPSMem
903 ,&vDIBh
904 ,0L
905 ,NULL
906 ,NULL
907 );
908 lScans = ::GpiQueryBitmapBits( hPSMem
909 ,0L
910 ,(LONG)nHeight
911 ,(PBYTE)lpBits
912 ,&vDIBInfo
913 );
914
915 //
916 // Copy DIB data into the wxImage object
917 //
918 int i;
919 int j;
920 unsigned char* ptdata = pData;
921 unsigned char* ptbits = lpBits;
922
923 for (i = 0; i < nHeight; i++)
924 {
925 for (j = 0; j < nWidth; j++)
926 {
927 *(ptdata++) = *(ptbits+2);
928 *(ptdata++) = *(ptbits+1);
929 *(ptdata++) = *(ptbits );
930 ptbits += 3;
931 }
932 ptbits += nPadding;
933 }
934
935 //
936 // Similarly, set data according to the possible mask bitmap
937 //
938 if (GetMask() && GetMask()->GetMaskBitmap())
939 {
940 hBitmap = (HBITMAP)GetMask()->GetMaskBitmap();
941
942 //
943 // Memory DC/PS created, color set, data copied, and memory DC/PS deleted
944 //
945 HDC hMemDC = ::DevOpenDC( vHabmain
946 ,OD_MEMORY
947 ,"*"
948 ,4
949 ,(PDEVOPENDATA)pszData
950 ,NULLHANDLE
951 );
952 HPS hMemPS = ::GpiCreatePS( vHabmain
953 ,hMemDC
954 ,&vSizlPage
955 ,PU_PELS | GPIA_ASSOC | GPIT_MICRO
956 );
957 ::GpiSetColor(hMemPS, OS2RGB(0, 0, 0));
958 ::GpiSetBackColor(hMemPS, OS2RGB(255, 255, 255) );
959 ::GpiQueryBitmapBits( hPSMem
960 ,0L
961 ,(LONG)nHeight
962 ,(PBYTE)lpBits
963 ,&vDIBInfo
964 );
965 ::GpiDestroyPS(hMemPS);
966 ::DevCloseDC(hMemDC);
967
968 //
969 // Background color set to RGB(16,16,16) in consistent with wxGTK
970 //
971 unsigned char ucRed = 16;
972 unsigned char ucGreen = 16;
973 unsigned char ucBlue = 16;
974
975 ptdata = pData;
976 ptbits = lpBits;
977 for (i = 0; i < nHeight; i++)
978 {
979 for (j = 0; j < nWidth; j++)
980 {
981 if (*ptbits != 0)
982 ptdata += 3;
983 else
984 {
985 *(ptdata++) = ucRed;
986 *(ptdata++) = ucGreen;
987 *(ptdata++) = ucBlue;
988 }
989 ptbits += 3;
990 }
991 ptbits += nPadding;
992 }
993 vImage.SetMaskColour( ucRed
994 ,ucGreen
995 ,ucBlue
996 );
997 vImage.SetMask(TRUE);
998 }
999 else
1000 {
1001 vImage.SetMask(FALSE);
1002 }
1003
1004 //
1005 // Free allocated resources
1006 //
1007 ::GpiDestroyPS(hPSMem);
1008 ::DevCloseDC(hDCMem);
1009 free(lpBits);
1010 return vImage;
1011} // end of wxBitmap::ConvertToImage
1012
1013// ----------------------------------------------------------------------------
1014// sub bitmap extraction
1015// ----------------------------------------------------------------------------
1016
1017wxBitmap wxBitmap::GetSubBitmap(
1018 const wxRect& rRect
1019) const
1020{
1021 wxCHECK_MSG( Ok() &&
1022 (rRect.x >= 0) && (rRect.y >= 0) &&
1023 (rRect.x + rRect.width <= GetWidth()) &&
1024 (rRect.y + rRect.height <= GetHeight()),
1025 wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
1026
1027 wxBitmap vRet( rRect.width
1028 ,rRect.height
1029 ,GetDepth()
1030 );
1031 wxASSERT_MSG( vRet.Ok(), wxT("GetSubBitmap error") );
1032
1033
1034 //
1035 // Copy bitmap data
1036 //
1037 SIZEL vSize = {0, 0};
1038 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1039 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1040 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1041 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1042 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1043 POINTL vPoint[4] = { 0, 0, rRect.width, rRect.height,
1044 rRect.x, rRect.y
1045 rRect.x + rRect.width, rRect.y + rRect.height
1046 };
1047
1048 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetHBITMAP());
1049 ::GpiSetBitmap(hPSDst, (HBITMAP) vRet.GetHBITMAP());
1050 ::GpiBitBlt( hPSDst
1051 ,hPSSrc
1052 ,4L
1053 ,vPoint
1054 ,ROP_SRCCOPY
1055 ,BBO_IGNORE
1056 );
1057
1058 //
1059 // Copy mask if there is one
1060 //
1061 if (GetMask())
1062 {
1063 BITMAPINFOHEADER2 vBmih;
1064
1065 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1066 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1067 vBmih.cx = rRect.width;
1068 vBmih.cy = rRect.height;
1069 vBmih.cPlanes = 1;
1070 vBmih.cBitCount = 1;
1071
1072 HBITMAP hBmpMask = ::GpiCreateBitmap( hPSDst
1073 ,&vBmih
1074 ,0L
1075 ,NULL
1076 ,NULL
1077 );
1078
1079 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetHBITMAP());
1080 ::GpiSetBitmap(hPSDst, (HBITMAP) vRet.GetHBITMAP());
1081
1082 ::GpiSetBitmap(hPSSrc, (HBITMAP) GetMask()->GetMaskBitmap());
1083 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpMask);
1084 ::GpiBitBlt( hPSDst
1085 ,hPSSrc
1086 ,4L
1087 ,vPoint
1088 ,ROP_SRCCOPY
1089 ,BBO_IGNORE
1090 );
1091
1092 wxMask* pMask = new wxMask((WXHBITMAP)hBmpMask);
1093 vRet.SetMask(pMask);
1094 }
1095
1096 ::GpiSetBitmap(hPSSrc, NULL);
1097 ::GpiSetBitmap(hPSDst, NULL);
1098 ::GpiDestroyPS(hPSSrc);
1099 ::GpiDestroyPS(hPSDst);
1100 ::DevCloseDC(hDCSrc);
1101 ::DevCloseDC(hDCDst);
1102 return vRet;
1103} // end of wxBitmap::GetSubBitmap
1104
1105// ----------------------------------------------------------------------------
1106// wxBitmap accessors
1107// ----------------------------------------------------------------------------
1108
1109void wxBitmap::SetQuality(
1110 int nQ
1111)
1112{
1113 EnsureHasData();
1114
1115 GetBitmapData()->m_nQuality = nQ;
1116} // end of wxBitmap::SetQuality
1117
1118#if WXWIN_COMPATIBILITY_2
1119void wxBitmap::SetOk(
1120 bool bOk
1121)
1122{
1123 EnsureHasData();
1124
1125 GetBitmapData()->m_bOk = bOk;
1126} // end of wxBitmap::SetOk
1127#endif // WXWIN_COMPATIBILITY_2
1128
1129void wxBitmap::SetPalette(
1130 const wxPalette& rPalette
1131)
1132{
1133 EnsureHasData();
1134
1135 GetBitmapData()->m_vBitmapPalette = rPalette;
1136} // end of wxBitmap::SetPalette
1137
1138void wxBitmap::SetMask(
1139 wxMask* pMask
1140)
1141{
1142 EnsureHasData();
1143
1144 GetBitmapData()->m_pBitmapMask = pMask;
1145} // end of wxBitmap::SetMask
1146
1147wxBitmap wxBitmap::GetBitmapForDC(
1148 wxDC& rDc
1149) const
1150{
1151 return(*this);
1152} // end of wxBitmap::GetBitmapForDC
1153
1154// ----------------------------------------------------------------------------
1155// wxMask
1156// ----------------------------------------------------------------------------
1157
1158wxMask::wxMask()
1159{
1160 m_hMaskBitmap = 0;
1161} // end of wxMask::wxMask
1162
1163// Construct a mask from a bitmap and a colour indicating
1164// the transparent area
1165wxMask::wxMask(
1166 const wxBitmap& rBitmap
1167, const wxColour& rColour
1168)
1169{
1170 m_hMaskBitmap = 0;
1171 Create( rBitmap
1172 ,rColour
1173 );
1174} // end of wxMask::wxMask
1175
1176// Construct a mask from a bitmap and a palette index indicating
1177// the transparent area
1178wxMask::wxMask(
1179 const wxBitmap& rBitmap
1180, int nPaletteIndex
1181)
1182{
1183 m_hMaskBitmap = 0;
1184 Create( rBitmap
1185 ,nPaletteIndex
1186 );
1187} // end of wxMask::wxMask
1188
1189// Construct a mask from a mono bitmap (copies the bitmap).
1190wxMask::wxMask(
1191 const wxBitmap& rBitmap
1192)
1193{
1194 m_hMaskBitmap = 0;
1195 Create(rBitmap);
1196} // end of wxMask::wxMask
1197
1198wxMask::~wxMask()
1199{
1200 if (m_hMaskBitmap)
1201 ::GpiDeleteBitmap((HBITMAP)m_hMaskBitmap);
1202} // end of wxMask::~wxMask
1203
1204// Create a mask from a mono bitmap (copies the bitmap).
1205bool wxMask::Create(
1206 const wxBitmap& rBitmap
1207)
1208{
1209 BITMAPINFOHEADER2 vBmih;
1210 SIZEL vSize = {0, 0};
1211 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1212 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1213 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1214 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1215 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1216 POINTL vPoint[4] = { 0 ,0, rBitmap.GetWidth(), rBitmap.GetHeight(),
1217 0, 0, rBitmap.GetWidth(), rBitmap.GetHeight()
1218 };
1219
1220 if (m_hMaskBitmap)
1221 {
1222 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1223 m_hMaskBitmap = 0;
1224 }
1225 if (!rBitmap.Ok() || rBitmap.GetDepth() != 1)
1226 {
1227 return(FALSE);
1228 }
1229
1230 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1231 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1232 vBmih.cx = rBitmap.GetWidth();
1233 vBmih.cy = rBitmap.GetHeight();
1234 vBmih.cPlanes = 1;
1235 vBmih.cBitCount = 1;
1236
1237 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
1238 ,&vBmih
1239 ,0L
1240 ,NULL
1241 ,NULL
1242 );
1243
1244 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
1245 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
1246 ::GpiBitBlt( hPSDst
1247 ,hPSSrc
1248 ,4L
1249 ,vPoint
1250 ,ROP_SRCCOPY
1251 ,BBO_IGNORE
1252 );
1253
1254 ::GpiDestroyPS(hPSSrc);
1255 ::GpiDestroyPS(hPSDst);
1256 ::DevCloseDC(hDCSrc);
1257 ::DevCloseDC(hDCDst);
1258 return(TRUE);
1259} // end of wxMask::Create
1260
1261// Create a mask from a bitmap and a palette index indicating
1262// the transparent area
1263bool wxMask::Create(
1264 const wxBitmap& rBitmap
1265, int nPaletteIndex
1266)
1267{
1268 if (m_hMaskBitmap)
1269 {
1270 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1271 m_hMaskBitmap = 0;
1272 }
1273 if (rBitmap.Ok() && rBitmap.GetPalette()->Ok())
1274 {
1275 unsigned char cRed;
1276 unsigned char cGreen;
1277 unsigned char cBlue;
1278
1279 if (rBitmap.GetPalette()->GetRGB( nPaletteIndex
1280 ,&cRed
1281 ,&cGreen
1282 ,&cBlue
1283 ))
1284 {
1285 wxColour vTransparentColour( cRed
1286 ,cGreen
1287 ,cBlue
1288 );
1289
1290 return (Create( rBitmap
1291 ,vTransparentColour
1292 ));
1293 }
1294 }
1295 return(FALSE);
1296} // end of wxMask::Create
1297
1298// Create a mask from a bitmap and a colour indicating
1299// the transparent area
1300bool wxMask::Create(
1301 const wxBitmap& rBitmap
1302, const wxColour& rColour
1303)
1304{
1305 bool bOk = TRUE;
1306 COLORREF vMaskColour = OS2RGB( rColour.Red()
1307 ,rColour.Green()
1308 ,rColour.Blue()
1309 );
1310 BITMAPINFOHEADER2 vBmih;
1311 SIZEL vSize = {0, 0};
1312 DEVOPENSTRUC vDop = { NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1313 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1314 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1315 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1316 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1317 POINTL vPoint[4] = { 0 ,0, rBitmap.GetWidth(), rBitmap.GetHeight(),
1318 0, 0, rBitmap.GetWidth(), rBitmap.GetHeight()
1319 };
1320
1321 if (m_hMaskBitmap)
1322 {
1323 ::GpiDeleteBitmap((HBITMAP) m_hMaskBitmap);
1324 m_hMaskBitmap = 0;
1325 }
1326 if (!rBitmap.Ok())
1327 {
1328 return(FALSE);
1329 }
1330
1331 //
1332 // Scan the bitmap for the transparent colour and set
1333 // the corresponding pixels in the mask to BLACK and
1334 // the rest to WHITE
1335 //
1336
1337 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1338 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1339 vBmih.cx = rBitmap.GetWidth();
1340 vBmih.cy = rBitmap.GetHeight();
1341 vBmih.cPlanes = 1;
1342 vBmih.cBitCount = 1;
1343
1344 m_hMaskBitmap = ::GpiCreateBitmap( hPSDst
1345 ,&vBmih
1346 ,0L
1347 ,NULL
1348 ,NULL
1349 );
1350
1351 ::GpiSetBitmap(hPSSrc, (HBITMAP) rBitmap.GetHBITMAP());
1352 ::GpiSetBitmap(hPSDst, (HBITMAP) m_hMaskBitmap);
1353
1354 //
1355 // This is not very efficient, but I can't think
1356 // of a better way of doing it
1357 //
1358 for (int w = 0; w < rBitmap.GetWidth(); w++)
1359 {
1360 for (int h = 0; h < rBitmap.GetHeight(); h++)
1361 {
1362 POINTL vPt = {w, h};
1363 COLORREF vCol = (COLORREF)::GpiQueryPel(hPSSrc, &vPt);
1364 if (vCol == (COLORREF)CLR_NOINDEX)
1365 {
1366 //
1367 // Doesn't make sense to continue
1368 //
1369 bOk = FALSE;
1370 break;
1371 }
1372
1373 if (vCol == vMaskColour)
1374 {
1375 ::GpiSetColor(hPSDst, OS2RGB(0, 0, 0));
1376 ::GpiSetPel(hPSDst, &vPt);
1377 }
1378 else
1379 {
1380 ::GpiSetColor(hPSDst, OS2RGB(255, 255, 255));
1381 ::GpiSetPel(hPSDst, &vPt);
1382 }
1383 }
1384 }
1385 ::GpiSetBitmap(hPSSrc, NULL);
1386 ::GpiSetBitmap(hPSDst, NULL);
1387 ::GpiDestroyPS(hPSSrc);
1388 ::GpiDestroyPS(hPSDst);
1389 ::DevCloseDC(hDCSrc);
1390 ::DevCloseDC(hDCDst);
1391 return(TRUE);
1392} // end of wxMask::Create
1393
1394// ----------------------------------------------------------------------------
1395// wxBitmapHandler
1396// ----------------------------------------------------------------------------
1397
1398bool wxBitmapHandler::Create(
1399 wxGDIImage* pImage
1400, void* pData
1401, long lFlags
1402, int nWidth
1403, int nHeight
1404, int nDepth
1405)
1406{
1407 wxBitmap* pBitmap = wxDynamicCast( pImage
1408 ,wxBitmap
1409 );
1410
1411 return(pBitmap ? Create( pBitmap
1412 ,pData
1413 ,nWidth
1414 ,nHeight
1415 ,nDepth
1416 ) : FALSE);
1417}
1418
1419bool wxBitmapHandler::Load(
1420 wxGDIImage* pImage
1421, const wxString& rName
1422, HPS hPs
1423, long lFlags
1424, int nWidth
1425, int nHeight
1426)
1427{
1428 wxBitmap* pBitmap = wxDynamicCast( pImage
1429 ,wxBitmap
1430 );
1431
1432 return(pBitmap ? LoadFile( pBitmap
1433 ,rName
1434 ,hPs
1435 ,lFlags
1436 ,nWidth
1437 ,nHeight
1438 ) : FALSE);
1439}
1440
1441bool wxBitmapHandler::Save(
1442 wxGDIImage* pImage
1443, const wxString& rName
1444, int lType
1445)
1446{
1447 wxBitmap* pBitmap = wxDynamicCast( pImage
1448 ,wxBitmap
1449 );
1450
1451 return(pBitmap ? SaveFile( pBitmap
1452 ,rName
1453 ,lType
1454 ) : FALSE);
1455}
1456
1457bool wxBitmapHandler::Create(
1458 wxBitmap* WXUNUSED(pBitmap)
1459, void* WXUNUSED(pData)
1460, long WXUNUSED(lType)
1461, int WXUNUSED(nWidth)
1462, int WXUNUSED(nHeight)
1463, int WXUNUSED(nDepth)
1464)
1465{
1466 return(FALSE);
1467}
1468
1469bool wxBitmapHandler::LoadFile(
1470 wxBitmap* WXUNUSED(pBitmap)
1471, const wxString& WXUNUSED(rName)
1472, HPS WXUNUSED(hPs)
1473, long WXUNUSED(lType)
1474, int WXUNUSED(nDesiredWidth)
1475, int WXUNUSED(nDesiredHeight)
1476)
1477{
1478 return(FALSE);
1479}
1480
1481bool wxBitmapHandler::SaveFile(
1482 wxBitmap* WXUNUSED(pBitmap)
1483, const wxString& WXUNUSED(rName)
1484, int WXUNUSED(nType)
1485, const wxPalette* WXUNUSED(pPalette)
1486)
1487{
1488 return(FALSE);
1489}
1490
1491// ----------------------------------------------------------------------------
1492// Utility functions
1493// ----------------------------------------------------------------------------
1494HBITMAP wxInvertMask(
1495 HBITMAP hBmpMask
1496, int nWidth
1497, int nHeight
1498)
1499{
1500 HBITMAP hBmpInvMask = 0;
1501
1502 wxCHECK_MSG( hBmpMask, 0, _T("invalid bitmap in wxInvertMask") );
1503
1504 //
1505 // Get width/height from the bitmap if not given
1506 //
1507 if (!nWidth || !nHeight)
1508 {
1509 BITMAPINFOHEADER2 vBmhdr;
1510
1511 ::GpiQueryBitmapInfoHeader( hBmpMask
1512 ,&vBmhdr
1513 );
1514 nWidth = (int)vBmhdr.cx;
1515 nHeight = (int)vBmhdr.cy;
1516 }
1517
1518 BITMAPINFOHEADER2 vBmih;
1519 SIZEL vSize = {0, 0};
1520 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1521 HDC hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1522 HDC hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1523 HPS hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
1524 HPS hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
1525 POINTL vPoint[4] = { 0 ,0, nWidth, nHeight,
1526 0, 0, nWidth, nHeight
1527 };
1528
1529 memset(&vBmih, '\0', sizeof(BITMAPINFOHEADER2));
1530 vBmih.cbFix = sizeof(BITMAPINFOHEADER2);
1531 vBmih.cx = nWidth;
1532 vBmih.cy = nHeight;
1533 vBmih.cPlanes = 1;
1534 vBmih.cBitCount = 1;
1535
1536 hBmpInvMask = ::GpiCreateBitmap( hPSDst
1537 ,&vBmih
1538 ,0L
1539 ,NULL
1540 ,NULL
1541 );
1542
1543 ::GpiSetBitmap(hPSSrc, (HBITMAP) hBmpMask);
1544 ::GpiSetBitmap(hPSDst, (HBITMAP) hBmpInvMask);
1545
1546 ::GpiBitBlt( hPSDst
1547 ,hPSSrc
1548 ,4L
1549 ,vPoint
1550 ,ROP_SRCINVERT
1551 ,BBO_IGNORE
1552 );
1553
1554 ::GpiDestroyPS(hPSSrc);
1555 ::GpiDestroyPS(hPSDst);
1556 ::DevCloseDC(hDCSrc);
1557 ::DevCloseDC(hDCDst);
1558
1559 return hBmpInvMask;
1560} // end of WxWinGdi_InvertMask
1561