home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vos2-121.zip / v / srcos2 / vicon.cpp < prev    next >
C/C++ Source or Header  |  1999-03-03  |  26KB  |  675 lines

  1. //===============================================================
  2. // vicon.cpp - icon class
  3. //
  4. // Copyright (C) 1995,1996,1997,1998  Bruce E. Wampler
  5. //
  6. // This file is part of the V C++ GUI Framework, and is covered
  7. // under the terms of the GNU Library General Public License,
  8. // Version 2. This library has NO WARRANTY. See the source file
  9. // vapp.cxx for more complete information about license terms.
  10. //===============================================================
  11. #include <v/v_defs.h>
  12. #include <v/vos2.h>        // for OS/2 stuff
  13. #include <v/vapp.h>
  14. #include <v/vicon.h>
  15.  
  16. //=============================>>> vIcon::vIcon <<<=====================
  17.   vIcon::vIcon()
  18.   {
  19.     _hbm = 0;
  20.     _hmsk = 0;
  21.     _currentDC = 0;
  22.     _trColor = 0;
  23.   }
  24.  
  25. //=============================>>> vIcon::vIcon  <<<=====================
  26.   vIcon::vIcon(unsigned char* ic, int h, int w, int d, IconType it)
  27.   {
  28.     icon = ic; height = h; width = w; depth = d; iType = it;
  29.     _hbm = 0;
  30.     _currentDC = 0;
  31.     _trColor = 0;
  32.   }
  33.  
  34. //=============================>>> vIcon::~vIcon <<<=====================
  35.   vIcon::~vIcon()
  36.   {
  37.     if (_hbm != 0)
  38.       GpiDeleteBitmap(_hbm);
  39.     if (_hmsk != 0)
  40.       GpiDeleteBitmap(_hmsk);
  41.   }
  42.  
  43. //=============================>>> vIcon::NeedBMPBytes <<<==================
  44.   int vIcon::NeedBMPBytes() VCONST
  45.   {
  46.     // calculate how many bytes of storage pixel data will take
  47.     // includes allowance for mandatory word boundary alignment of rows
  48.     // note: does not include color map storage
  49.  
  50.     int needWords = height*((depth*width+31)/32);
  51.     return (needWords * 4);    // convert to bytes
  52.   }
  53.  
  54. //=============================>>> vIcon::vIconToBMP  <<<=====================
  55.   void vIcon::vIconToBMP(HPS iDC) VCONST
  56.   {
  57.     // We use _currentDC to track whether the current _hbm is valid
  58.     // for the requesting DC.  If it is, we can improve performance
  59.     // by just returning the _hbm without recreating it again.  If it
  60.     // is not the same, we need to destroy the _hbm and recreate it
  61.     // with the appropriate compatible memory PS
  62.  
  63.     // The inline code for GetIconHBM checks to see if the (iDC/HBM)
  64.     // pair is valid.  If we get this far then the pair must be invalid
  65.     // (or undefined) and thus we need to create a new bitmap.
  66.  
  67.     if (_currentDC != 0)
  68.     {
  69.       GpiDeleteBitmap(_hbm);
  70.  
  71.       if (_hmsk != 0)
  72.       {
  73.         GpiDeleteBitmap(_hmsk);
  74.         _trColor = 0;
  75.       }
  76.     }
  77.  
  78.     _currentDC = iDC;
  79.  
  80.     // bitmap data structures
  81.     PVBYTE vbytes = (PVBYTE) icon;
  82.     PVBYTE bmbits;
  83.     PBITMAPINFO2 pbmi;
  84.     LONG trIndex;
  85.     HDC DevCxtComp, DevCxtMem;
  86.     HPS hdcMem;
  87.  
  88.     // build a memory PS compatible with calling PS
  89.     DevCxtComp = GpiQueryDevice(iDC);
  90.     DevCxtMem = DevOpenDC(theApp->AppHab(), OD_MEMORY, "*", 0L, NULL, DevCxtComp);
  91.     SIZEL size = {width, height};
  92.     hdcMem = GpiCreatePS (theApp->AppHab(), DevCxtMem, &size,
  93.                           PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
  94.  
  95.     // set the PS to RGB mode
  96.     GpiCreateLogColorTable(hdcMem, 0L, LCOLF_RGB, 0L, 0L, NULL);
  97.  
  98.     // First, create a blank bitmap compatible with the
  99.     // current context that is size of bitmap.
  100.     BITMAPINFOHEADER2 bmih;
  101.     memset(&bmih, 0, sizeof(BITMAPINFOHEADER2));
  102.     bmih.cbFix = sizeof(BITMAPINFOHEADER2);
  103.     bmih.cx = width;
  104.     bmih.cy = height;
  105.     bmih.ulColorEncoding = BCE_RGB;
  106.     bmih.cPlanes = 1;         // always 1 for OS/2
  107.     bmih.cBitCount = depth;   // bits of color per pixel
  108.  
  109.     _hbm = GpiCreateBitmap(hdcMem, &bmih, 0L, NULL, NULL);
  110.  
  111.     // now we need to load the bitmap with data by associating
  112.     // with a memory PS and setting each pel
  113.     GpiSetBitmap(hdcMem, _hbm);
  114.  
  115.     // now we need to load the bitmap with data
  116.     if (depth == 8)        // 8 bit icons
  117.     {
  118.       // 8 bit vicon structure:
  119.       // header:     [n][rgb0][rgb1][...][rgbn]
  120.       // pixel data: [p1][p2][...][phxw]
  121.  
  122.       // we first need to create the bitmapinfo structure and
  123.       // color table
  124.       // get the total number of entries in color table
  125.       unsigned int numColors = (unsigned int) *vbytes++ + 1;
  126.  
  127.       // allocate space for header and color table
  128.       LONG colorTableSize = numColors*sizeof(RGB2);
  129.       pbmi = (PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)+colorTableSize];
  130.  
  131.       // copy the header to the bitmap info structure
  132.       memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
  133.       pbmi->cbImage = NeedBMPBytes();
  134.       pbmi->cclrUsed = numColors ;
  135.  
  136.       // create the color table
  137.       PRGB2 ColorEntry = pbmi->argbColor;
  138.       for (unsigned int ix = 0 ; ix < numColors ; ++ix) // map the colors
  139.       {
  140.         ColorEntry->bRed = *vbytes++;
  141.         ColorEntry->bGreen = *vbytes++;
  142.         ColorEntry->bBlue = *vbytes++;
  143.         ColorEntry->fcOptions = 0;
  144.         ColorEntry++;
  145.       }
  146.  
  147.       // Colors mapped, vbytes now points to beginning of data
  148.       // The lower left hand pixel of the bitmap is reserved for the
  149.       // transparent color. Any pixel in the bitmap which matches that
  150.       // lower left hand pixel will be transparent (for Transparent icons)
  151.       if (iType == Transparent)
  152.       {
  153.         trIndex = vbytes[ ( height - 1 ) * width ];
  154.         RGB2 trColor = pbmi->argbColor[ trIndex ];
  155.         _trColor = SETRGB(trColor.bRed, trColor.bGreen, trColor.bBlue);
  156.       }
  157.  
  158.       // allocate space for bitmap data
  159.       bmbits = new VBYTE[NeedBMPBytes()];
  160.  
  161.       // Now need to copy pixel data over from V icon format
  162.       // The V format is essentially based on the X way of
  163.       // defining a bitmap.  To fix it up, we need to
  164.       // pad rows to even words.
  165.       //
  166.       // Although OS/2 row order is upsidedown in OS/2 compared
  167.       // to X, since we invert the DC using the model space transform
  168.       // it all works out in the end.
  169.  
  170.       int rowwords = (width+3) / 4;     // number of words (for OS/2 bitmap data)
  171. //      PVBYTE to = bmbits + (height-1)*rowwords*4;   // set to last row of pixel data
  172.       PVBYTE to = bmbits;                           // set to first row of pixel data
  173.  
  174.       for (int row = 0 ; row < height ; ++row)        // copy by row
  175.       {
  176.         int col;
  177.         for (col = 0 ; col < width ; ++col)   // do each V byte per row
  178.         {
  179.           *to++ = *vbytes++;
  180.         }
  181.         // Finished a row, need to pad to a word boundary
  182.         while (col < 4*rowwords)
  183.         {
  184.           *to++ = 0x00;           // pad with 0's
  185.           col++;
  186.         }
  187.         // now jump back to the row previous to the row just written
  188.         // since we are writing rows from back to front
  189. //      to -= rowwords*8;
  190.       }
  191.     }
  192.     else if (depth > 8)        // 24 bit icons
  193.     {
  194.       // We first need to create the bitmapinfo structure
  195.       // (a color table is not needed for 24 bit bitmaps)
  196.       // allocate space for header
  197.       pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)];
  198.  
  199.       // copy the header to the bitmap info structure
  200.       memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
  201.       pbmi->cbImage = width*height*4;   // image size (bytes)
  202.       pbmi->cclrUsed = 0 ;              // no color table needed
  203.  
  204.       // vbytes points to beginning of data
  205.       // The lower left hand pixel of the bitmap is reserved for the
  206.       // transparent color. Any pixel in the bitmap which matches that
  207.       // lower left hand pixel will be transparent (for Transparent icons)
  208.       if (iType == Transparent)
  209.       {
  210.         _trColor = SETRGB( vbytes[ ( height - 1 ) * width * 3 ],
  211.                            vbytes[ ( height - 1 ) * width * 3 + 1],
  212.                            vbytes[ ( height - 1 ) * width * 3 + 2] );
  213. printf("_trcolor= %x (%u) \n", _trColor, _trColor);
  214.       }
  215.  
  216.       // Now need to copy pixel data over from V icon format
  217.       // The V format is essentially based on the X way of
  218.       // defining a bitmap. To fix it up, we need to
  219.       // swap row order in the data.
  220.       VBYTE R, G, B;
  221.       bmbits = new VBYTE[NeedBMPBytes()];    // allocate space
  222.       int rowwords = ((width*3)+3) / 4;   // number of words (for OS/2 bitmap data)
  223. //    PVBYTE to = bmbits + (height-1)*rowwords*4;  // set to last row of pixel data
  224.       PVBYTE to = bmbits;                          // set to first row of pixel data
  225.  
  226.       for (int row = 0 ; row < height ; ++row)        // copy by row
  227.       {
  228.         int col;
  229.         for (col = 0 ; col < width ; ++col)   // do each V pixel per row
  230.         {
  231.           // R G B
  232.           // careful with the order here!
  233.           R = *vbytes++; G = *vbytes++; B = *vbytes++;
  234.           *to++ = B; *to++ = G; *to++ = R;
  235.         }
  236.         // Finished a row, need to pad to a word boundary
  237.         while ( (col*3)<(4*rowwords) )
  238.         {
  239.           *to++ = 0x00;           // pad with 0's
  240.           col++;
  241.         }
  242.         // now jump back to the row previous to the row just written
  243.         // since we are writing rows from back to front
  244. //      to -= rowwords*8;
  245.       }
  246.     }
  247.     else
  248.     {
  249.       // We will use depth == 1 as the default case since if the
  250.       // depth isn't legal, we will at least get some kind of picture
  251.       // of the right size.
  252.  
  253.       // We first need to create the bitmapinfo structure and
  254.       // color table
  255.  
  256.       // allocate space for header and color table
  257.       LONG colorTableSize=(1<<depth)*sizeof(RGB2);
  258.       pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)+colorTableSize];
  259.  
  260.       // copy the header to the bitmap info structure
  261.       memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
  262.       pbmi->cbImage = NeedBMPBytes();
  263.       pbmi->cclrUsed = 1<<depth ;
  264.  
  265.       // create the color table
  266.       // for monochrome bitmaps the color choice here
  267.       // will affect which bits become foreground and which
  268.       // are background color in the target canvas.  We choose
  269.       // colors here that will map (1) bits to the foreground
  270.       // color in the target (the expected result)
  271.       PLONG colorTableEntry = (PLONG) pbmi->argbColor;
  272.       *colorTableEntry++ = SETRGB2(0,0,0,0);
  273.       *colorTableEntry = SETRGB2(0,255,255,255);
  274.  
  275.       static VBYTE Xmask[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  276.       static VBYTE Wmask[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
  277.       bmbits = new VBYTE[NeedBMPBytes()];    // allocate space
  278.  
  279.       // Now need to copy pixel data over from V icon format
  280.       // The V format is essentially based on the X way of
  281.       // defining a bitmap which is completely orthogonal to
  282.       // the OS/2 way.  To fix it up, we need to swap byte bit order
  283.       // pad rows to even words, and swap row order in the data, yuck!
  284.  
  285.       int rowbytes = (width+7) / 8;        // number of bytes (for V icon data)
  286.       int rowwords = (rowbytes+3) / 4;     // number of words (for OS/2 bitmap data)
  287. //    PVBYTE to = bmbits + (height-1)*rowwords*4;   // set to last row of pixel data
  288.       PVBYTE to = bmbits;                           // set to first row of pixel data
  289.  
  290.       for (int row = 0 ; row < height ; ++row)        // copy by row
  291.       {
  292.         int col;
  293.         for (col = 0 ; col < rowbytes ; ++col)   // do each V byte per row
  294.         {
  295.           VBYTE X = *vbytes++;            // source V-icon byte
  296.           VBYTE W = 0;                  // target OS/2 byte
  297.           for (int ix = 0 ; ix < 8 ; ++ix) // reverse bits
  298.           {
  299.             if (X & Xmask[ix])   // is there a better way to do this?
  300.               W |= Wmask[ix];
  301.           }
  302.       *to++ = W;             // save the pixel data in the row
  303.     }
  304.     // Finished a row, need to pad to a word boundary
  305.     while (col < 4*rowwords)
  306.     {
  307.       *to++ = 0x00;           // pad with 0's
  308.       col++;
  309.     }
  310.     // now jump back to the row previous to the row just written
  311.     // since we are writing rows from back to front
  312. //    to -= rowwords*8;
  313.       }
  314.     }
  315.  
  316.     // Now, create the bitmap
  317.     GpiSetBitmapBits(hdcMem, 0L, pbmi->cy, (PBYTE) bmbits, pbmi);
  318.     // free up resources and we are done
  319.     delete [] bmbits;
  320.     delete [] pbmi;
  321.  
  322.     GpiSetBitmap (hdcMem, NULLHANDLE);
  323.     GpiAssociate (hdcMem, NULLHANDLE);
  324.     GpiDestroyPS (hdcMem);
  325.     DevCloseDC (DevCxtMem);
  326.   }
  327.  
  328.  
  329. //=============================>>> vIcon::vIconToDLG  <<<=====================
  330.   HBITMAP vIcon::GetIconDLG(CmdType ct, LONG bgColor)
  331.   // this code is similar to vIconToBMP except it inverts the
  332.   // bitmap image (right-side-up) for use in dialogs
  333.   {
  334.     if (_hDlgbm != 0 && ct != C_Icon)
  335.       return(_hDlgbm);
  336.  
  337.     // bitmap data structures
  338.     PVBYTE vbytes = (PVBYTE) icon;
  339.     PVBYTE bmbits;
  340.     PBITMAPINFO2 pbmi;
  341.     LONG trIndex;
  342.     HDC DevCxtMem, DevCxtMsk;
  343.     HPS hdcMem, hdcMsk;
  344.  
  345.     // build a memory PS compatible with calling PS
  346.     // using NULLHANDLE for compatible-device-context forces compatibility with screen
  347.     // which is okay since this is only for dialogs
  348.     DevCxtMem = DevOpenDC(theApp->AppHab(), OD_MEMORY, "*", 0L, NULL, NULLHANDLE);
  349.     SIZEL size = {width, height};
  350.     hdcMem = GpiCreatePS (theApp->AppHab(), DevCxtMem, &size,
  351.                           PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
  352.  
  353.     // set the PS to RGB mode
  354.     GpiCreateLogColorTable(hdcMem, 0L, LCOLF_RGB, 0L, 0L, NULL);
  355.  
  356.     // First, create a blank bitmap compatible with the
  357.     // current context that is size of bitmap.
  358.     BITMAPINFOHEADER2 bmih;
  359.     memset(&bmih, 0, sizeof(BITMAPINFOHEADER2));
  360.     bmih.cbFix = sizeof(BITMAPINFOHEADER2);
  361.     bmih.cx = width;
  362.     bmih.cy = height;
  363.     bmih.ulColorEncoding = BCE_RGB;
  364.     bmih.cPlanes = 1;         // always 1 for OS/2
  365.     if (depth == 1)
  366.       bmih.cBitCount = 4;   // we treat monochromes as 4 bit due to OS/2 bug
  367.     else
  368.       bmih.cBitCount = depth;   // bits of color per pixel
  369.  
  370.     _hDlgbm = GpiCreateBitmap(hdcMem, &bmih, 0L, NULL, NULL);
  371.  
  372.     // now we need to load the bitmap with data by associating
  373.     // with a memory PS and setting each pel
  374.     GpiSetBitmap(hdcMem, _hDlgbm);
  375.  
  376.     // For Transparent icons,
  377.     // create second 24bit bitmap with same dimensions for the transparent version
  378.     if (iType == Transparent)
  379.     {
  380.       // build a memory PS compatible with calling PS
  381.  
  382.       DevCxtMsk = DevOpenDC(theApp->AppHab(), OD_MEMORY, "*", 0L, NULL, NULLHANDLE);
  383.       SIZEL size = {width, height};
  384.       hdcMsk = GpiCreatePS (theApp->AppHab(), DevCxtMsk, &size,
  385.                             PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
  386.  
  387.       // switch to RGB color mode
  388. //      GpiCreateLogColorTable(hdcMsk, 0L, LCOLF_RGB, 0L, 0L, NULL);
  389.  
  390.       BITMAPINFOHEADER2 mskBmih;
  391.       memset(&mskBmih, 0, sizeof(BITMAPINFOHEADER2));
  392.       mskBmih.cbFix = sizeof(BITMAPINFOHEADER2);
  393.       mskBmih.cx = width;
  394.       mskBmih.cy = height;
  395.       mskBmih.ulColorEncoding = BCE_RGB;
  396.       mskBmih.cPlanes = 1;      // always 1 for OS/2
  397.       mskBmih.cBitCount = 24;   // transparent icons are 24 bit
  398.       mskBmih.cbImage = width*height*4;   // image size (bytes)
  399.       mskBmih.cclrUsed = 0 ;              // no color table needed
  400.  
  401.       _hDlgmsk = GpiCreateBitmap(hdcMsk, &mskBmih, 0L, NULL, NULL);
  402.  
  403.       // now we need to load the bitmap with data by associating
  404.       // with a memory PS and setting each pel
  405.       GpiSetBitmap(hdcMsk, _hDlgmsk);
  406.     }
  407.  
  408.     if (depth == 8)        // 8 bit icons
  409.     {
  410.       // 8 bit vicon structure:
  411.       // header:     [n][rgb0][rgb1][...][rgbn]
  412.       // pixel data: [p1][p2][...][phxw]
  413.  
  414.       // we first need to create the bitmapinfo structure and
  415.       // color table
  416.       // get the total number of entries in color table
  417.       unsigned int numColors = (unsigned int) *vbytes++ + 1;
  418.  
  419.       // allocate space for header and color table
  420.       LONG colorTableSize = numColors*sizeof(RGB2);
  421.       pbmi = (PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)+colorTableSize];
  422.  
  423.       // copy the header to the bitmap info structure
  424.       memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
  425.       pbmi->cbImage = NeedBMPBytes();
  426.       pbmi->cclrUsed = numColors ;
  427.  
  428.       // create the color table
  429.       PRGB2 ColorEntry = pbmi->argbColor;
  430.       for (unsigned int ix = 0 ; ix < numColors ; ++ix) // map the colors
  431.       {
  432.         ColorEntry->bRed = *vbytes++;
  433.         ColorEntry->bGreen = *vbytes++;
  434.         ColorEntry->bBlue = *vbytes++;
  435.         ColorEntry->fcOptions = 0;
  436.         ColorEntry++;
  437.       }
  438.  
  439.       // Colors mapped, vbytes now points to beginning of data
  440.       // The lower left hand pixel of the bitmap is reserved for the
  441.       // transparent color. Any pixel in the bitmap which matches that
  442.       // lower left hand pixel will be transparent (for Transparent icons)
  443.       if (iType == Transparent)
  444.       {
  445.         trIndex = vbytes[ ( height - 1 ) * width ];
  446.         RGB2 trColor = pbmi->argbColor[ trIndex ];
  447.         _trColor = SETRGB(trColor.bRed, trColor.bGreen, trColor.bBlue);
  448.       }
  449.  
  450.       bmbits = new VBYTE[NeedBMPBytes()];    // allocate space
  451.  
  452.       // Now need to copy pixel data over from V icon format
  453.       // The V format is essentially based on the X way of
  454.       // defining a bitmap.  To fix it up, we need to
  455.       // pad rows to even words.
  456.       // Although OS/2 row order is upsidedown in OS/2 compared
  457.       // to X, since we invert the DC using the model space transform
  458.       // it all works out in the end.
  459.  
  460.       int rowwords = (width+3) / 4;     // number of words (for OS/2 bitmap data)
  461.       PVBYTE to = bmbits + (height-1)*rowwords*4;   // set to last row of pixel data
  462. //      PVBYTE to = bmbits;                           // set to first row of pixel data
  463.  
  464.       for (int row = 0 ; row < height ; ++row)        // copy by row
  465.       {
  466.         int col;
  467.         for (col = 0 ; col < width ; ++col)   // do each V byte per row
  468.         {
  469.           *to++ = *vbytes++;
  470.         }
  471.         // Finished a row, need to pad to a word boundary
  472.         while (col < 4*rowwords)
  473.         {
  474.           *to++ = 0x00;           // pad with 0's
  475.           col++;
  476.         }
  477.         // now jump back to the row previous to the row just written
  478.         // since we are writing rows from back to front
  479.         to -= rowwords*8;
  480.       }
  481.     }
  482.     else if (depth > 8)        // 24 bit icons
  483.     {
  484.  
  485.       // We first need to create the bitmapinfo structure
  486.       // (a color table is not needed for 24 bit bitmaps)
  487.       // allocate space for header
  488.       pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)];
  489.  
  490.       // copy the header to the bitmap info structure
  491.       memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
  492.       pbmi->cbImage = width*height*4;   // image size (bytes)
  493.       pbmi->cclrUsed = 0 ;              // no color table needed
  494.  
  495.       // vbytes points to beginning of data
  496.       // The lower left hand pixel of the bitmap is reserved for the
  497.       // transparent color. Any pixel in the bitmap which matches that
  498.       // lower left hand pixel will be transparent (for Transparent icons)
  499.       if (iType == Transparent)
  500.       {
  501.     _trColor = SETRGB( vbytes[ ( height - 1 ) * width * 3 ],
  502.                vbytes[ ( height - 1 ) * width * 3 + 1],
  503.               vbytes[ ( height - 1 ) * width * 3 + 2] );
  504.       }
  505.  
  506.       // Now need to copy pixel data over from V icon format
  507.       // The V format is essentially based on the X way of
  508.       // defining a bitmap. To fix it up, we need to
  509.       // swap row order in the data.
  510.       VBYTE R, G, B;
  511.       bmbits = new VBYTE[NeedBMPBytes()];    // allocate space
  512.       int rowwords = ((width*3)+3) / 4;   // number of words (for OS/2 bitmap data)
  513.       PVBYTE to = bmbits + (height-1)*rowwords*4;  // set to last row of pixel data
  514. //      PVBYTE to = bmbits;                          // set to first row of pixel data
  515.  
  516.       for (int row = 0 ; row < height ; ++row)        // copy by row
  517.       {
  518.         int col;
  519.         for (col = 0 ; col < width ; ++col)   // do each V pixel per row
  520.         {
  521.           // R G B
  522.           // careful with the order here!
  523.           R = *vbytes++; G = *vbytes++; B = *vbytes++;
  524.           *to++ = B; *to++ = G; *to++ = R;
  525.         }
  526.         // Finished a row, need to pad to a word boundary
  527.         while ( (col*3)<(4*rowwords) )
  528.         {
  529.           *to++ = 0x00;           // pad with 0's
  530.           col++;
  531.         }
  532.         // now jump back to the row previous to the row just written
  533.         // since we are writing rows from back to front
  534.         to -= rowwords*8;
  535.       }
  536.     }
  537.     else
  538.     {
  539.       // we really want a monochrome bitmap here, but the dialog
  540.       // routines do not handle monochrome bitmaps properly (the
  541.       // colors are off).  We will convert the monochrome bitmaps
  542.       // to a 4 bit bitmap but only use 2 colors (ie. monochrome)
  543.       LONG orgDepth = depth;
  544.       depth = 4;    // temporary color depth
  545.  
  546.       // We first need to create the bitmapinfo structure and
  547.       // color table
  548.  
  549.       // allocate space for header and color table
  550.       ULONG numColors = 2;
  551.       LONG colorTableSize=numColors * sizeof(RGB2);
  552.       pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)+colorTableSize];
  553.  
  554.       // copy the header to the bitmap info structure
  555.       memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
  556.       pbmi->cbImage = NeedBMPBytes();
  557.       pbmi->cclrUsed = numColors;
  558.  
  559.       // create the color table
  560.       // for monochrome bitmaps the color choice here
  561.       // will affect which bits become foreground and which
  562.       // are background color in the target canvas.  We choose
  563.       // colors here that will map (1) bits to the foreground
  564.       // color in the target (the expected result)
  565.       PLONG colorTableEntry = (PLONG) pbmi->argbColor;
  566.       *colorTableEntry++ = WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONMIDDLE, 0L);
  567.       *colorTableEntry = WinQuerySysColor(HWND_DESKTOP, SYSCLR_MENUTEXT, 0L);
  568.  
  569.       static VBYTE Xmask[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  570.       static VBYTE Wmask[] = {0x10,0x01,0x10,0x01,0x10,0x01,0x10,0x01};
  571.  
  572.       // Now need to copy pixel data over from V icon format.
  573.       // Every byte in the original V monochrome icon data will
  574.       // map exactly to one word (4 bytes) in the OS/2 bitmap data
  575.  
  576.       int rowwords = (width+7) / 8;     // number of words per row (OS/2 bitmap data)
  577.  
  578.       bmbits = new VBYTE[NeedBMPBytes()];    // allocate space
  579.  
  580.       PVBYTE to = bmbits + (height-1)*rowwords*4;   // set to last row of pixel data
  581. //      PVBYTE to = bmbits;                           // set to first row of pixel data
  582.  
  583.       for (int row = 0 ; row < height ; ++row)        // copy by row
  584.       {
  585.         for (int col = 0 ; col < rowwords ; col++)   // do each OS/2 word per row
  586.         {
  587.           VBYTE X = *vbytes++;            // source V-icon byte
  588.           for (int ix = 0 ; ix < 8 ; ++ix)
  589.           {
  590.             VBYTE W = 0;                  // target OS/2 byte
  591.             if (X & Xmask[ix])
  592.               W |= Wmask[ix];
  593.         ix++;
  594.         if (X & Xmask[ix])
  595.           W |= Wmask[ix];
  596.         *to++ = W;             // save the pixel data in the row
  597.           }
  598.         }
  599.     // now jump back to the row previous to the row just written
  600.     // since we are writing rows from back to front
  601.     to -= rowwords*8;
  602.       }
  603.       depth = orgDepth;   // set back to original depth
  604.     }
  605.  
  606.     // Now, create the bitmap
  607.     GpiSetBitmapBits(hdcMem, 0L, pbmi->cy, (PBYTE) bmbits, pbmi);
  608.     // free up resources and we are done
  609.     delete [] bmbits;
  610.     delete [] pbmi;
  611.  
  612.     GpiSetBitmap (hdcMem, NULLHANDLE);
  613.     GpiAssociate (hdcMem, NULLHANDLE);
  614.     GpiDestroyPS (hdcMem);
  615.     DevCloseDC (DevCxtMem);
  616.  
  617.     // Create the transparent bitmap if required by
  618.     // setting the PS background to the requested
  619.     // background color for the dialog (bgColor) and copying the
  620.     // icon to the _hDlgmsk bitmap using the BM_SRCTRANSPARENT option
  621.     // on the PS
  622.     if (iType == Transparent)
  623.     {
  624.       // switch to RGB color mode
  625.       GpiCreateLogColorTable(hdcMsk, 0L, LCOLF_RGB, 0L, 0L, NULL);
  626.  
  627.       // first fill the PS with the desired background color
  628.       RECTL rc = {0,0, width, height};
  629.       WinFillRect(hdcMsk, &rc, bgColor);
  630.  
  631.       // (Note: Target is in World Coords, and Source is in Device Coords)
  632.       POINTL cPoints[4] = {0,0,                   // lower left targ
  633.                width-1, height-1,     // upper right targ
  634.                0, 0,                  // lower left src
  635.                width, height};        // upper right src
  636.  
  637.       // set ownership of bitmap to canvas
  638.       HBITMAP hbmr = GpiSetBitmap(hdcMsk, _hDlgbm);
  639.       // now reset the tranparent bitmap
  640.       GpiSetBitmap(hdcMsk, hbmr);
  641.  
  642.       // for transparent icons, we set the canvas background
  643.       // color to the icon transparent color and then set
  644.       // the background mix mode to BM_SRCTRANSPARENT, OS/2
  645.       // takes care of the rest.
  646.  
  647.       GpiSetBackColor(hdcMsk, _trColor);
  648.       GpiSetBackMix(hdcMsk,BM_SRCTRANSPARENT);
  649.  
  650.       // blit the image to the canvas
  651.       GpiWCBitBlt(hdcMsk, _hDlgbm, 4, cPoints, ROP_SRCCOPY, BBO_IGNORE);
  652.  
  653.       GpiSetBackMix(hdcMsk,BM_DEFAULT);
  654.  
  655.       GpiSetBitmap (hdcMsk, NULLHANDLE);
  656.       GpiAssociate (hdcMsk, NULLHANDLE);
  657.       GpiDestroyPS (hdcMsk);
  658.       DevCloseDC (DevCxtMsk);
  659.       // destroy the source bitmap, we don't need it anymore
  660.  
  661.       if (_hDlgbm != 0)
  662.       {
  663.         GpiDeleteBitmap(_hDlgbm);
  664.         _hDlgbm = 0;
  665.       }
  666.  
  667.       SysDebug2(OS2Dev,"GetIconDLG (transparent) CmdType:%d _hDlgmsk:%x \n", ct, _hDlgmsk)
  668.       return (_hDlgmsk);  // return the transparent version
  669.     }
  670.  
  671.     SysDebug2(OS2Dev,"GetIconDLG CmdType:%d _hDlgbm:%x \n", ct, _hDlgbm)
  672.     return(_hDlgbm);  // return the normal version
  673.   }
  674.  
  675.