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