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