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