Bitmap updates
[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 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
86 void wxBitmap::Init()
87 {
88 } // end of wxBitmap::Init
89
90 bool 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
121 bool 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
132 bool 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
144 wxBitmap::~wxBitmap()
145 {
146 } // end of wxBitmap::~wxBitmap
147
148 wxBitmap::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
255 wxBitmap::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
269 wxBitmap::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
287 wxBitmap::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
299 bool 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
374 bool 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
395 bool 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
433 bool 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
466 bool 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
503 bool 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
816 wxImage 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
1017 wxBitmap 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
1109 void 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
1119 void 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
1129 void wxBitmap::SetPalette(
1130 const wxPalette& rPalette
1131 )
1132 {
1133 EnsureHasData();
1134
1135 GetBitmapData()->m_vBitmapPalette = rPalette;
1136 } // end of wxBitmap::SetPalette
1137
1138 void wxBitmap::SetMask(
1139 wxMask* pMask
1140 )
1141 {
1142 EnsureHasData();
1143
1144 GetBitmapData()->m_pBitmapMask = pMask;
1145 } // end of wxBitmap::SetMask
1146
1147 wxBitmap wxBitmap::GetBitmapForDC(
1148 wxDC& rDc
1149 ) const
1150 {
1151 return(*this);
1152 } // end of wxBitmap::GetBitmapForDC
1153
1154 // ----------------------------------------------------------------------------
1155 // wxMask
1156 // ----------------------------------------------------------------------------
1157
1158 wxMask::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
1165 wxMask::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
1178 wxMask::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).
1190 wxMask::wxMask(
1191 const wxBitmap& rBitmap
1192 )
1193 {
1194 m_hMaskBitmap = 0;
1195 Create(rBitmap);
1196 } // end of wxMask::wxMask
1197
1198 wxMask::~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).
1205 bool 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
1263 bool 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
1300 bool 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
1398 bool 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
1419 bool 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
1441 bool 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
1457 bool 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
1469 bool 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
1481 bool 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 // ----------------------------------------------------------------------------
1494 HBITMAP 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