home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / os2 / bitmap.cpp < prev    next >
C/C++ Source or Header  |  2002-07-22  |  52KB  |  1,615 lines

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