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