home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / Rop.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  29.8 KB  |  835 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : rop.cpp                                                                //
  10. //  Description: Bitmap raster operation, MaskBlt, PlgBlt, TransparentBlt            //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define WIN32_LEAN_AND_MEAN
  16.  
  17. #include <windows.h>
  18. #include <tchar.h>
  19. #include <assert.h>
  20.  
  21. #include "DIB.h"
  22. #include "Affine.h"
  23. #include "BitmapInfo.h"
  24. #include "DIBsection.h"
  25. #include "GDIObject.h"
  26. #include "Rop.h"
  27.  
  28. typedef struct
  29.   { unsigned long  ropcode;
  30.     char          *formula;
  31.     char          *name;
  32.   } RopItem;
  33.     
  34.    
  35. const RopItem RopDict[256] =
  36. {
  37.     { 0x00000042, "0",          "BLACKNESS"     },
  38.     { 0x00010289, "DPSoon",     NULL            },
  39.     { 0x00020C89, "DPSona",     NULL            },
  40.     { 0x000300AA, "PSon",       NULL            },  
  41.     { 0x00040C88, "SDPona",     NULL            },
  42.     { 0x000500A9, "DPon",       NULL            },
  43.     { 0x00060865, "PDSxnon",    NULL            },
  44.     { 0x000702C5, "PDSaon",     NULL            },
  45.     { 0x00080F08, "SDPnaa",     NULL            },
  46.     { 0x00090245, "PDSxon",     NULL            },
  47.     { 0x000A0329, "DPna",       NULL            },
  48.     { 0x000B0B2A, "PSDnaon",    NULL            },
  49.     { 0x000C0324, "SPna",       NULL            },
  50.     { 0x000D0B25, "PDSnaon",    NULL            },
  51.     { 0x000E08A5, "PDSonon",    NULL            },
  52.     { 0x000F0001, "Pn",         NULL            },
  53.     
  54.     { 0x00100C85, "PDSona",     NULL            },
  55.     { 0x001100A6, "DSon",       "NOTSRCERASE"   },
  56.     { 0x00120868, "SDPxnon",    NULL            },
  57.     { 0x001302C8, "SDPaon",     NULL            },
  58.     { 0x00140869, "DPSxnon",    NULL            },
  59.     { 0x001502C9, "DPSaon",     NULL            },
  60.     { 0x00165CCA, "PSDPSanaxx", NULL            },
  61.     { 0x00171D54, "SSPxDSxaxn", NULL            },
  62.     { 0x00180D59, "SPxPDxa",    NULL            },
  63.     { 0x00191CC8, "SDPSanaxn",  NULL            },
  64.     { 0x001A06C5, "PDSPaox",    NULL            },
  65.     { 0x001B0768, "SDPSxaxn",   NULL            },
  66.     { 0x001C06CA, "PSDPaox",    NULL            },
  67.     { 0x001D0766, "DSPDxaxn",   NULL            },
  68.     { 0x001E01A5, "PDSox",      NULL            },
  69.     { 0x001F0385, "PDSoan",     NULL            },
  70.     
  71.     { 0x00200F09, "DPSnaa",     NULL            },
  72.     { 0x00210248, "SDPxon",     NULL            },
  73.     { 0x00220326, "DSna",       NULL            },
  74.     { 0x00230B24, "SPDnaon",    NULL            },
  75.     { 0x00240D55, "SPxDSxa",    NULL            },
  76.     { 0x00251CC5, "PDSPanaxn",  NULL            },
  77.     { 0x002606C8, "SDPSaox",    NULL            },
  78.     { 0x00271868, "SDPSxnox",   NULL            },
  79.     { 0x00280369, "DPSxa",      NULL            },
  80.     { 0x002916CA, "PSDPSaoxxn", NULL            },
  81.     { 0x002A0CC9, "DPSana",     NULL            },
  82.     { 0x002B1D58, "SSPxPDxaxn", NULL            },
  83.     { 0x002C0784, "SPDSoax",    NULL            },
  84.     { 0x002D060A, "PSDnox",     NULL            },
  85.     { 0x002E064A, "PSDPxox",    NULL            },
  86.     { 0x002F0E2A, "PSDnoan",    NULL            },
  87.  
  88.     
  89.     { 0x0030032A, "PSna",       NULL            },
  90.     { 0x00310B28, "SDPnaon",    NULL            },
  91.     { 0x00320688, "SDPSoox",    NULL            },
  92.     { 0x00330008, "Sn",         "NOTSRCCOPY"    },
  93.     { 0x003406C4, "SPDSaox",    NULL            },
  94.     { 0x00351864, "SPDSxnox",   NULL            },
  95.     { 0x003601A8, "SDPox",      NULL            },
  96.     { 0x00370388, "SDPoan",     NULL            },
  97.     { 0x0038078A, "PSDPoax",    NULL            },
  98.     { 0x00390604, "SPDnox",     NULL            },
  99.     { 0x003A0644, "SPDSxox",    NULL            },
  100.     { 0x003B0E24, "SPDnoan",    NULL            },
  101.     { 0x003C004A, "PSx",        NULL            },
  102.     { 0x003D18A4, "SPDSonox",   NULL            },
  103.     { 0x003E1B24, "SPDSnaox",   NULL            },
  104.     { 0x003F00EA, "PSan",       NULL            },
  105.     
  106.     { 0x00400F0A, "PSDnaa",     NULL            },
  107.     { 0x00410249, "DPSxon",     NULL            },
  108.     { 0x00420D5D, "SDxPDxa",    NULL            },
  109.     { 0x00431CC4, "SPDSanaxn",  NULL            },
  110.     { 0x00440328, "SDna",       "SRCERASE"      },
  111.     { 0x00450B29, "DPSnaon",    NULL            },
  112.     { 0x004606C6, "DSPDaox",    NULL            },
  113.     { 0x0047076A, "PSDPxaxn",   NULL            },
  114.     { 0x00480368, "SDPxa",      NULL            },
  115.     { 0x004916C5, "PDSPDaoxxn", NULL            },
  116.     { 0x004A0789, "DPSDoax",    NULL            },
  117.     { 0x004B0605, "PDSnox",     NULL            },
  118.     { 0x004C0CC8, "SDPana",     NULL            },
  119.     { 0x004D1954, "SSPxDSxoxn", NULL            },
  120.     { 0x004E0645, "PDSPxox",    NULL            },
  121.     { 0x004F0E25, "PDSnoan",    NULL            },
  122.     
  123.     { 0x00500325, "PDna",       NULL            },
  124.     { 0x00510B26, "DSPnaon",    NULL            },
  125.     { 0x005206C9, "DPSDaox",    NULL            },
  126.     { 0x00530764, "SPDSxaxn",   NULL            },
  127.     { 0x005408A9, "DPSonon",    NULL            },
  128.     { 0x00550009, "Dn",         "DSTINVERT"     }, 
  129.     { 0x005601A9, "DPSox",      NULL            },
  130.     { 0x00570389, "DPSoan",     NULL            },
  131.     { 0x00580785, "PDSPoax",    NULL            },
  132.     { 0x00590609, "DPSnox",     NULL            },
  133.     { 0x005A0049, "DPx",        "PATINVERT"     },
  134.     { 0x005B18A9, "DPSDonox",   NULL            },
  135.     { 0x005C0649, "DPSDxox",    NULL            },
  136.     { 0x005D0E29, "DPSnoan",    NULL            },
  137.     { 0x005E1B29, "DPSDnaox",   NULL            },
  138.     { 0x005F00E9, "DPan",       NULL            },
  139.     
  140.     { 0x00600365, "PDSxa",      NULL            },
  141.     { 0x006116C6, "DSPDSaoxxn", NULL            },
  142.     { 0x00620786, "DSPDoax",    NULL            },
  143.     { 0x00630608, "SDPnox",     NULL            },
  144.     { 0x00640788, "SDPSoax",    NULL            },
  145.     { 0x00650606, "DSPnox",     NULL            },
  146.     { 0x00660046, "DSx",        "SRCINVERT"     },
  147.     { 0x006718A8, "SDPSonox",   NULL            },
  148.     { 0x006858A6, "DSPDSonoxxn",NULL            },
  149.     { 0x00690145, "PDSxxn",     NULL            },
  150.     { 0x006A01E9, "DPSax",      NULL            },
  151.     { 0x006B178A, "PSDPSoaxxn", NULL            },
  152.     { 0x006C01E8, "SDPax",      NULL            },
  153.     { 0x006D1785, "PDSPDoaxxn", NULL            },
  154.     { 0x006E1E28, "SDPSnoax",   NULL            },
  155.     { 0x006F0C65, "PDSxnan",    NULL            },
  156.     
  157.     { 0x00700CC5, "PDSana",     NULL            },
  158.     { 0x00711D5C, "SSDxPDxaxn", NULL            },
  159.     { 0x00720648, "SDPSxox",    NULL            },
  160.     { 0x00730E28, "SDPnoan",    NULL            },
  161.     { 0x00740646, "DSPDxox",    NULL            },
  162.     { 0x00750E26, "DSPnoan",    NULL            },
  163.     { 0x00761B28, "SDPSnaox",   NULL            },
  164.     { 0x007700E6, "DSan",       NULL            },
  165.     { 0x007801E5, "PDSax",      NULL            },
  166.     { 0x00791786, "DSPDSoaxxn", NULL            },
  167.     { 0x007A1E29, "DPSDnoax",   NULL            },
  168.     { 0x007B0C68, "SDPxnan",    NULL            },
  169.     { 0x007C1E24, "SPDSnoax",   NULL            },
  170.     { 0x007D0C69, "DPSxnan",    NULL            },
  171.     { 0x007E0955, "SPxDSxo",    NULL            },
  172.     { 0x007F03C9, "DPSaan",     NULL            },
  173.     
  174.     { 0x008003E9, "DPSaa",      NULL            },
  175.     { 0x00810975, "SPxDSxon",   NULL            },
  176.     { 0x00820C49, "DPSxna",     NULL            },
  177.     { 0x00831E04, "SPDSnoaxn",  NULL            },
  178.     { 0x00840C48, "SDPxna",     NULL            },
  179.     { 0x00851E05, "PDSPnoaxn",  NULL            },
  180.     { 0x008617A6, "DSPDSoaxx",  NULL            },
  181.     { 0x008701C5, "PDSaxn",     NULL            },
  182.     { 0x008800C6, "DSa",        "SRCAND"        },
  183.     { 0x00891B08, "SDPSnaoxn",  NULL            },
  184.     { 0x008A0E06, "DSPnoa",     NULL            },
  185.     { 0x008B0666, "DSPDxoxn",   NULL            },
  186.     { 0x008C0E08, "SDPnoa",     NULL            },
  187.     { 0x008D0668, "SDPSxoxn",   NULL            },
  188.     { 0x008E1D7C, "SSDxPDxax",  NULL            },
  189.     { 0x008F0CE5, "PDSanan",    NULL            },
  190.     
  191.     { 0x00900C45, "PDSxna",     NULL            },
  192.     { 0x00911E08, "SDPSnoaxn",  NULL            },
  193.     { 0x009217A9, "DPSDPoaxx",  NULL            },
  194.     { 0x009301C4, "SPDaxn",     NULL            },
  195.     { 0x009417AA, "PSDPSoaxx",  NULL            },
  196.     { 0x009501C9, "DPSaxn",     NULL            },
  197.     { 0x00960169, "DPSxx",      NULL            },
  198.     { 0x0097588A, "PSDPSonoxx", NULL            },
  199.     { 0x00981888, "SDPSonoxn",  NULL            },
  200.     { 0x00990066, "DSxn",       NULL            },
  201.     { 0x009A0709, "DPSnax",     NULL            },
  202.     { 0x009B07A8, "SDPSoaxn",   NULL            },
  203.     { 0x009C0704, "SPDnax",     NULL            },
  204.     { 0x009D07A6, "DSPDoaxn",   NULL            },
  205.     { 0x009E16E6, "DSPDSaoxx",  NULL            },
  206.     { 0x009F0345, "PDSxan",     NULL            },
  207.     { 0x00A000C9, "DPa",        NULL            },
  208.     { 0x00A11B05, "PDSPnaoxn",  NULL            },
  209.     { 0x00A20E09, "DPSnoa",     NULL            },
  210.     { 0x00A30669, "DPSDxoxn",   NULL            },
  211.     { 0x00A41885, "PDSPonoxn",  NULL            },
  212.     { 0x00A50065, "PDxn",       NULL            },
  213.     { 0x00A60706, "DSPnax",     NULL            },
  214.     { 0x00A707A5, "PDSPoaxn",   NULL            },
  215.     { 0x00A803A9, "DPSoa",      NULL            },
  216.     { 0x00A90189, "DPSoxn",     NULL            },
  217.     { 0x00AA0029, "D",          NULL            },
  218.     { 0x00AB0889, "DPSono",     NULL            },
  219.     { 0x00AC0744, "SPDSxax",    NULL            },
  220.     { 0x00AD06E9, "DPSDaoxn",   NULL            },
  221.     { 0x00AE0B06, "DSPnao",     NULL            },
  222.     { 0x00AF0229, "DPno",       NULL            },
  223.     
  224.     { 0x00B00E05, "PDSnoa",     NULL            },
  225.     { 0x00B10665, "PDSPxoxn",   NULL            },
  226.     { 0x00B21974, "SSPxDSxox",  NULL            },
  227.     { 0x00B30CE8, "SDPanan",    NULL            },
  228.     { 0x00B4070A, "PSDnax",     NULL            },
  229.     { 0x00B507A9, "DPSDoaxn",   NULL            },
  230.     { 0x00B616E9, "DPSDPaoxx",  NULL            },
  231.     { 0x00B70348, "SDPxan",     NULL            },
  232.     { 0x00B8074A, "PSDPxax",    NULL            },
  233.     { 0x00B906E6, "DSPDaoxn",   NULL            },
  234.     { 0x00BA0B09, "DPSnao",     NULL            },
  235.     { 0x00BB0226, "DSno",       "MERGEPAINT"    },
  236.     { 0x00BC1CE4, "SPDSanax",   NULL            },
  237.     { 0x00BD0D7D, "SDxPDxan",   NULL            },
  238.     { 0x00BE0269, "DPSxo",      NULL            },
  239.     { 0x00BF08C9, "DPSano",     NULL            },
  240.     
  241.     { 0x00C000CA, "PSa",        "MERGECOPY"     },
  242.     { 0x00C11B04, "SPDSnaoxn",  NULL            },
  243.     { 0x00C21884, "SPDSonoxn",  NULL            },
  244.     { 0x00C3006A, "PSxn",       NULL            },
  245.     { 0x00C40E04, "SPDnoa",     NULL            },
  246.     { 0x00C50664, "SPDSxoxn",   NULL            },
  247.     { 0x00C60708, "SDPnax",     NULL            },
  248.     { 0x00C707AA, "PSDPoaxn",   NULL            },
  249.     { 0x00C803A8, "SDPoa",      NULL            },
  250.     { 0x00C90184, "SPDoxn",     NULL            },
  251.     { 0x00CA0749, "DPSDxax",    NULL            },
  252.     { 0x00CB06E4, "SPDSaoxn",   NULL            },
  253.     { 0x00CC0020, "S",          "SRCCOPY"       },
  254.     { 0x00CD0888, "SDPono",     NULL            },
  255.     { 0x00CE0B08, "SDPnao",     NULL            },
  256.     { 0x00CF0224, "SPno",       NULL            },
  257.     
  258.     { 0x00D00E0A, "PSDnoa",     NULL            },
  259.     { 0x00D1066A, "PSDPxoxn",   NULL            },
  260.     { 0x00D20705, "PDSnax",     NULL            },
  261.     { 0x00D307A4, "SPDSoaxn",   NULL            },
  262.     { 0x00D41D78, "SSPxPDxax",  NULL            },
  263.     { 0x00D50CE9, "DPSanan",    NULL            },
  264.     { 0x00D616EA, "PSDPSaoxx",  NULL            },
  265.     { 0x00D70349, "DPSxan",     NULL            },
  266.     { 0x00D80745, "PDSPxax",    NULL            },
  267.     { 0x00D906E8, "SDPSaoxn",   NULL            },
  268.     { 0x00DA1CE9, "DPSDanax",   NULL            },
  269.     { 0x00DB0D75, "SPxDSxan",   NULL            },
  270.     { 0x00DC0B04, "SPDnao",     NULL            },
  271.     { 0x00DD0228, "SDno",       NULL            },
  272.     { 0x00DE0268, "SDPxo",      NULL            },
  273.     { 0x00DF08C8, "SDPano",     NULL            },
  274.     
  275.     { 0x00E003A5, "PDSoa",      NULL            },
  276.     { 0x00E10185, "PDSoxn",     NULL            },
  277.     { 0x00E20746, "DSPDxax",    NULL            },
  278.     { 0x00E306EA, "PSDPaoxn",   NULL            },
  279.     { 0x00E40748, "SDPSxax",    NULL            },
  280.     { 0x00E506E5, "PDSPaoxn",   NULL            },
  281.     { 0x00E61CE8, "SDPSanax",   NULL            },
  282.     { 0x00E70D79, "SPxPDxan",   NULL            },
  283.     { 0x00E81D74, "SSPxDSxax",  NULL            },
  284.     { 0x00E95CE6, "DSPDSanaxxn",NULL            },
  285.     { 0x00EA02E9, "DPSao",      NULL            },
  286.     { 0x00EB0849, "DPSxno",     NULL            },
  287.     { 0x00EC02E8, "SDPao",      NULL            },
  288.     { 0x00ED0848, "SDPxno",     NULL            },
  289.     { 0x00EE0086, "DSo",        "SRCPAINT"      },
  290.     { 0x00EF0A08, "SDPnoo",     NULL            },
  291.     
  292.     { 0x00F00021, "P",          "PATCOPY"       },
  293.     { 0x00F10885, "PDSono",     NULL            },
  294.     { 0x00F20B05, "PDSnao",     NULL            },
  295.     { 0x00F3022A, "PSno",       NULL            },
  296.     { 0x00F40B0A, "PSDnao",     NULL            },
  297.     { 0x00F50225, "PDno",       NULL            },
  298.     { 0x00F60265, "PDSxo",      NULL            },
  299.     { 0x00F708C5, "PDSano",     NULL            },
  300.     { 0x00F802E5, "PDSao",      NULL            },
  301.     { 0x00F90845, "PDSxno",     NULL            },
  302.     { 0x00FA0089, "DPo",        NULL            },
  303.     { 0x00FB0A09, "DPSnoo",     "PATPAINT"      },
  304.     { 0x00FC008A, "PSo",        NULL            },
  305.     { 0x00FD0A0A, "PSDnoo",     NULL            },
  306.     { 0x00FE02A9, "DPSoo",      NULL            },
  307.     { 0x00FF0062, "1",          "WHITENESS"     }
  308. };
  309.  
  310. DWORD GetRopCode(BYTE ropindex)
  311. {
  312.     return RopDict[ropindex].ropcode;
  313. }
  314.  
  315.  
  316. void ChannelSplit(KDIB & dib, HDC hDC)
  317. {
  318.     KBitmapInfo bmi;
  319.     KDIBSection dibsec;
  320.     int            width, height;
  321.  
  322.     bmi.SetFormat(dib.GetWidth(), dib.GetHeight(), 8, BI_RGB);
  323.     bmi.SetGrayScale(RGB(0xFF, 0, 0));
  324.  
  325.     dibsec.CreateDIBSection(NULL, bmi.GetBMI(), DIB_RGB_COLORS, NULL, NULL);
  326.     
  327.     dibsec.Prepare(width, height);
  328.     dibsec.SetColorTable();
  329.  
  330.     KGDIObject red(hDC, CreateSolidBrush(RGB(0xFF, 0, 0)));
  331.     dib.DrawDIB(dibsec.m_hMemDC, 0, 0, width, height, 0, 0, width, height, MERGECOPY);
  332.  
  333.     RGBQUAD gray[256];
  334.     for (int i=0; i<256; i++)
  335.     {
  336.         gray[i].rgbRed        = i;
  337.         gray[i].rgbGreen    = i;
  338.         gray[i].rgbBlue        = i;
  339.         gray[i].rgbReserved = 0;
  340.     }        
  341.     SetDIBColorTable(dibsec.m_hMemDC, 0, 256, gray);
  342.  
  343.     BitBlt(hDC, 0, 0, width, height, dibsec.m_hMemDC, 0, 0, SRCCOPY);
  344. }
  345.  
  346.  
  347. // Create a grayscale image (DIBSection) from one of the RGB channels in a DIB
  348. // Mask should be RGB(255, 0, 0), RGB(0, 255, 0), or RGB(0, 0, 255)
  349. HBITMAP ChannelSplit(const BITMAPINFO * pBMI, const void * pBits, COLORREF Mask, HDC hMemDC)
  350. {
  351.     typedef struct { BITMAPINFOHEADER bmiHeader;
  352.                      RGBQUAD          bmiColor[256];
  353.     } BMI8BPP;
  354.  
  355.     int width  = pBMI->bmiHeader.biWidth;
  356.     int height = pBMI->bmiHeader.biHeight;
  357.  
  358.     BMI8BPP bmi8bpp;
  359.  
  360.     memset(&bmi8bpp, 0, sizeof(bmi8bpp));
  361.  
  362.     bmi8bpp.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
  363.     bmi8bpp.bmiHeader.biWidth       = width;
  364.     bmi8bpp.bmiHeader.biHeight      = height;
  365.     bmi8bpp.bmiHeader.biPlanes      = 1;
  366.     bmi8bpp.bmiHeader.biBitCount    = 8;
  367.     bmi8bpp.bmiHeader.biCompression = BI_RGB;
  368.  
  369.     for (int i=0; i<256; i++) // color table for one of the RGB channels
  370.     {
  371.         bmi8bpp.bmiColor[i].rgbRed     = i & GetRValue(Mask);
  372.         bmi8bpp.bmiColor[i].rgbGreen = i & GetGValue(Mask);
  373.         bmi8bpp.bmiColor[i].rgbBlue     = i & GetBValue(Mask);
  374.     }        
  375.  
  376.     HBITMAP hRslt = CreateDIBSection(NULL, (BITMAPINFO *) & bmi8bpp, NULL, DIB_RGB_COLORS, NULL, NULL);
  377.     
  378.     if ( hRslt==NULL )
  379.         return NULL;
  380.  
  381.     SelectObject(hMemDC, hRslt);
  382.     
  383.     HBRUSH hBrush = CreateSolidBrush(Mask);            // solid red, green, or blue
  384.     HGDIOBJ hOld  = SelectObject(hMemDC, hBrush);
  385.     
  386.     StretchDIBits(hMemDC, 0, 0, width, height, 0, 0, width, height, pBits, pBMI, DIB_RGB_COLORS, MERGECOPY);
  387.  
  388.     for (i=0; i<256; i++)    // convert to real grayscale color table
  389.     {
  390.         bmi8bpp.bmiColor[i].rgbRed     = i;
  391.         bmi8bpp.bmiColor[i].rgbGreen = i;
  392.         bmi8bpp.bmiColor[i].rgbBlue     = i;
  393.     }
  394.     SetDIBColorTable(hMemDC, 0, 256, bmi8bpp.bmiColor);
  395.  
  396.     SelectObject(hMemDC, hOld);
  397.     DeleteObject(hBrush);
  398.  
  399.     return hRslt;
  400. }
  401.  
  402. // Gradually display a DIB on a destination surface in 4 steps
  403. void FadeIn(HDC hDC, int x, int y, int w, int h, const BITMAPINFO * pBMI, const void * pBits)
  404. {
  405.     const WORD Mask11[8] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  406.     const WORD Mask22[8] = { 0x88, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00 };
  407.     const WORD Mask44[8] = { 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0x00 };
  408.     const WORD Mask88[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  409.     
  410.     const WORD * Mask[4] = { Mask11, Mask22, Mask44, Mask88 };
  411.  
  412.     for (int i=0; i<4; i++)
  413.     {
  414.         HBITMAP hMask = CreateBitmap(8, 8, 1, 1, Mask[i]);
  415.         HBRUSH  hBrush= CreatePatternBrush(hMask);
  416.         DeleteObject(hMask);
  417.  
  418.         HGDIOBJ hOld  = SelectObject(hDC, hBrush);
  419.         // D^(P&(S^D)), if P then S else D
  420.         StretchDIBits(hDC, x, y, w, h, 0, 0, w, h, pBits, pBMI, DIB_RGB_COLORS, 0xCA07A9);
  421.                 
  422.         SelectObject(hDC, hOld);
  423.         DeleteObject(hBrush);
  424.     }
  425. }
  426.  
  427. // dx, dy, dw, dh defines a destination rectangle
  428. // sw, sh is the dimension of source rectangle
  429. // sx, sy is the starting point winthin the source bitmap, which will be tiled to sw x sh in size
  430. BOOL StretchTile(HDC      hDC, int dx, int dy, int dw, int dh, 
  431.                  HBITMAP hSrc, int sx, int sy, int sw, int sh, 
  432.                  DWORD rop)
  433. {
  434.     BITMAP bmp;
  435.  
  436.     if ( ! GetObject(hSrc, sizeof(BITMAP), & bmp) )
  437.         return FALSE;
  438.     
  439.     HDC   hMemDC = CreateCompatibleDC(NULL);
  440.     HGDIOBJ hOld = SelectObject(hMemDC, hSrc);
  441.     
  442.     int sy0 = sy % bmp.bmHeight;                        // current tile y origin
  443.     
  444.     for (int y=0; y<sh; y+=(bmp.bmHeight - sy0))
  445.     {
  446.         int height = min(bmp.bmHeight - sy0, sh - y);    // current tile height
  447.         int sx0    = sx % bmp.bmWidth;                    // current tile x origin
  448.         
  449.         for (int x=0; x<sw; x+=(bmp.bmWidth  - sx0))
  450.         {
  451.             int width = min(bmp.bmWidth - sx0, sw - x); // current tile width
  452.         
  453.             StretchBlt(hDC,    dx+x*dw/sw, dy+y*dh/sh, dw*width/sw, dh*height/sh, 
  454.                        hMemDC, sx0,        sy0,        width,       height, 
  455.                        rop);
  456.             sx0 = 0;    // after the first tile in a row, change to full tile width
  457.         }
  458.         sy0 = 0; // after the the first row, change to full tile height
  459.     }
  460.  
  461.     SelectObject(hMemDC, hOld);
  462.     DeleteObject(hMemDC);
  463.         
  464.     return TRUE;
  465. }
  466.  
  467.  
  468. BOOL G_PlgBlt(HDC hdcDest, const POINT * pPoint, 
  469.             HDC hdcSrc, int nXSrc, int nYSrc, int nWidth, int nHeight, 
  470.             HBITMAP hbmMask, int xMask, int yMask)
  471. {
  472.     KReverseAffine map(pPoint);
  473.  
  474.     if ( map.Simple() ) // no shear and rotation
  475.     {
  476.         int x = pPoint[0].x;
  477.         int y = pPoint[0].y;
  478.         int w = pPoint[1].x-pPoint[0].x;
  479.         int h = pPoint[2].y-pPoint[0].y;
  480.  
  481.         if ( hbmMask ) // has a mask bitmap, if (M) the S else D, S ^ (~M & (S^D))
  482.         {
  483.              StretchBlt(hdcDest, x, y, w, h, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, SRCINVERT);
  484.           StretchTile(hdcDest, x, y, w, h,  hbmMask, xMask, yMask, nWidth, nHeight, 0x220326);
  485.             return StretchBlt(hdcDest, x, y, w, h, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, SRCINVERT);
  486.         }
  487.         else
  488.             return StretchBlt(hdcDest, x, y, w, h, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, SRCCOPY);
  489.     }
  490.  
  491.     map.Setup(nXSrc, nYSrc, nWidth, nHeight);
  492.  
  493.     HDC hdcMask   = NULL;
  494.     int maskwidth = 0;
  495.     int maskheight= 0;
  496.  
  497.     if ( hbmMask )
  498.     {
  499.         BITMAP bmp;
  500.         GetObject(hbmMask, sizeof(bmp), & bmp);
  501.     
  502.         maskwidth  = bmp.bmWidth;
  503.         maskheight = bmp.bmHeight;
  504.  
  505.         hdcMask = CreateCompatibleDC(NULL);
  506.         SelectObject(hdcMask, hbmMask);
  507.     }
  508.  
  509.     for (int dy=map.miny; dy<=map.maxy; dy++)
  510.     for (int dx=map.minx; dx<=map.maxx; dx++)
  511.     {
  512.         float sx, sy;
  513.         map.Map(dx, dy, sx, sy);
  514.  
  515.         if ( (sx>=nXSrc) && (sx<=(nXSrc+nWidth))  )
  516.         if ( (sy>=nYSrc) && (sy<=(nYSrc+nHeight)) )
  517.             if ( hbmMask )
  518.             {
  519.                 if ( GetPixel(hdcMask, ((int)sx+xMask) % maskwidth, ((int)sy+yMask) % maskheight) )
  520.                     SetPixel(hdcDest, dx, dy, GetPixel(hdcSrc, (int)sx, (int)sy));
  521.             }
  522.             else
  523.                 SetPixel(hdcDest, dx, dy, GetPixel(hdcSrc, (int)sx, (int)sy));
  524.     }
  525.  
  526.     if ( hdcMask )
  527.         DeleteObject(hdcMask);
  528.  
  529.     return TRUE;
  530. }
  531.  
  532.  
  533. BOOL AffineBlt(HDC hdcDest, const POINT * pPoint, 
  534.                HDC hdcSrc, int nXSrc, int nYSrc, int nWidth, int nHeight, DWORD rop)
  535. {
  536.     KReverseAffine map(pPoint);
  537.  
  538.     if ( map.Simple() ) // no shear and rotation
  539.         return StretchBlt(hdcDest, pPoint[0].x, pPoint[0].y, 
  540.                    pPoint[1].x-pPoint[0].x, pPoint[2].y-pPoint[0].y, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, rop);
  541.     else
  542.     {
  543.         map.Setup(nXSrc, nYSrc, nWidth, nHeight);
  544.  
  545.         for (int dy=map.miny; dy<=map.maxy; dy++)
  546.         for (int dx=map.minx; dx<=map.maxx; dx++)
  547.         {
  548.             float sx, sy;
  549.             map.Map(dx, dy, sx, sy);
  550.  
  551.             if ( (sx>=nXSrc) && (sx<=(nXSrc+nWidth))  )
  552.             if ( (sy>=nYSrc) && (sy<=(nYSrc+nHeight)) )
  553.             {
  554.                 COLORREF s = GetPixel(hdcSrc, (int)sx, (int)sy);
  555.  
  556.                 switch ( rop )
  557.                 {
  558.                     case SRCCOPY: 
  559.                         SetPixel(hdcDest, dx, dy, s); break;
  560.  
  561.                     case SRCAND:
  562.                         SetPixel(hdcDest, dx, dy, s & GetPixel(hdcDest, dx, dy) ); break;
  563.  
  564.                     case SRCINVERT:
  565.                         SetPixel(hdcDest, dx, dy, s ^ GetPixel(hdcDest, dx, dy) ); break;
  566.                     
  567.                     default:
  568.                         return FALSE;
  569.                 }
  570.             }
  571.         }
  572.  
  573.         return TRUE;
  574.     }
  575. }
  576.  
  577.  
  578. BOOL AffineTile(HDC hdcDest, const POINT * pPoint, 
  579.                 HBITMAP hSrc, int xMask, int yMask, int nWidth, int nHeight, DWORD rop)
  580. {
  581.     KReverseAffine map(pPoint);
  582.  
  583.     if ( map.Simple() ) // no shear and rotation
  584.         return StretchTile(hdcDest, pPoint[0].x, pPoint[0].y, 
  585.                    pPoint[1].x-pPoint[0].x, pPoint[2].y-pPoint[0].y, hSrc, xMask, yMask, nWidth, nHeight, rop);
  586.     else
  587.     {
  588.         map.Setup(0, 0, nWidth, nHeight);
  589.  
  590.         BITMAP bmp;
  591.         GetObject(hSrc, sizeof(bmp), & bmp);
  592.         
  593.         HDC hdcSrc = CreateCompatibleDC(NULL);
  594.         SelectObject(hdcSrc, hSrc);
  595.  
  596.         for (int dy=map.miny; dy<=map.maxy; dy++)
  597.         for (int dx=map.minx; dx<=map.maxx; dx++)
  598.         {
  599.             float sx, sy;
  600.             map.Map(dx, dy, sx, sy);
  601.  
  602.             if ( (sx>=0) && (sx<=nWidth)  )
  603.             if ( (sy>=0) && (sy<=nHeight) )
  604.             {
  605.                 COLORREF s = GetPixel(hdcSrc, ((int)sx+xMask) % bmp.bmWidth, 
  606.                                               ((int)sy+yMask) % bmp.bmHeight);
  607.  
  608.                 switch ( rop )
  609.                 {
  610.                     case SRCAND:
  611.                         SetPixel(hdcDest, dx, dy, s & GetPixel(hdcDest, dx, dy) ); break;
  612.  
  613.                     case 0x220326: // ~S & D
  614.                         if ( s==RGB(0xFF, 0xFF, 0xFF) )
  615.                             SetPixel(hdcDest, dx, dy, RGB(0, 0, 0));
  616.                         else if ( s!=0 )
  617.                             SetPixel(hdcDest, dx, dy, (~s & GetPixel(hdcDest, dx, dy)) & 0xFFFFFF ); 
  618.                         break;
  619.  
  620.                     default:
  621.                         DeleteObject(hdcSrc);
  622.                         return FALSE;
  623.                 }
  624.             }
  625.         }
  626.         
  627.         DeleteObject(hdcSrc);
  628.         return TRUE;
  629.     }
  630. }
  631.  
  632. BOOL C_PlgBlt(HDC hdcDest, const POINT * pPoint, 
  633.             HDC hdcSrc, int nXSrc, int nYSrc, int nWidth, int nHeight, 
  634.             HBITMAP hbmMask, int xMask, int yMask)
  635. {
  636.     if ( hbmMask )    // has a mask bitmap, if (M) the S else D, S ^ (~M & (S^D))
  637.     {
  638.                 AffineBlt(hdcDest, pPoint, hdcSrc,  nXSrc, nYSrc, nWidth, nHeight, SRCINVERT);
  639.                AffineTile(hdcDest, pPoint, hbmMask, xMask, yMask, nWidth, nHeight, 0x220326);
  640.         return  AffineBlt(hdcDest, pPoint, hdcSrc,  nXSrc, nYSrc, nWidth, nHeight, SRCINVERT);
  641.     }
  642.     else
  643.         return AffineBlt(hdcDest, pPoint, hdcSrc, nXSrc, nYSrc, nWidth, nHeight, SRCCOPY);
  644. }
  645.  
  646.  
  647. void DrawCube(HDC hDC, int x, int y, int dh, int dx, int dy, HDC hMemDC, int w, int h, HBITMAP hMask, bool bSimulate)
  648. {
  649.     SetStretchBltMode(hDC, HALFTONE);
  650.  
  651.     //         6
  652.     //    0         4
  653.     //         1
  654.     //    2         5
  655.     //         3 
  656.     POINT P[3] = { { x - dx, y - dy }, { x, y }, { x - dx, y - dy + dh } }; // 012
  657.     POINT Q[3] = { { x, y }, { x + dx, y - dy }, { x, y + dh } };            // 143
  658.     POINT R[3] = { { x - dx, y - dy }, { x, y - dy - dy }, { x, y } };        // 061
  659.  
  660.     if ( bSimulate )
  661.     {
  662.         G_PlgBlt(hDC, P, hMemDC, 0, 0, w, h, hMask, 0, 0);
  663.         G_PlgBlt(hDC, Q, hMemDC, 0, 0, w, h, hMask, 0, 0);
  664.         G_PlgBlt(hDC, R, hMemDC, 0, 0, w, h, hMask, 0, 0);
  665.     }
  666.     else
  667.     {
  668.         PlgBlt(hDC, P, hMemDC, 0, 0, w, h, hMask, 0, 0);
  669.         PlgBlt(hDC, Q, hMemDC, 0, 0, w, h, hMask, 0, 0);
  670.         PlgBlt(hDC, R, hMemDC, 0, 0, w, h, hMask, 0, 0);
  671.     }
  672. }
  673.  
  674. void MaskCube(HDC hDC, int size, int x, int y, int w, int h, HBITMAP hBmp, HDC hMemDC, bool mask, bool bSimulate)
  675. {
  676.     HBITMAP hMask = NULL;
  677.     
  678.     if ( mask )
  679.     {
  680.         hMask = CreateBitmap(w, h, 1, 1, NULL);
  681.         SelectObject(hMemDC, hMask);
  682.         PatBlt(hMemDC, 0, 0, w, h, BLACKNESS);
  683.         RoundRect(hMemDC, 0, 0, w, h, w/2, h/2); // white
  684.     }
  685.  
  686.     int dx  = size * 94 / 100; // cos(20)
  687.     int dy  = size * 34 / 100; // sin(20)
  688.     SelectObject(hMemDC, hBmp);
  689.     DrawCube(hDC, x+dx, y+size, size, dx, dy, hMemDC, w, h, hMask, bSimulate);
  690.     
  691.     if ( hMask )
  692.         DeleteObject(hMask);
  693. }
  694.  
  695.  
  696. BOOL TriBitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, 
  697.                HDC hdcSrc, int nXSrc, int nYSrc,
  698.                HBITMAP hbmMask, int xMask, int yMask, 
  699.                DWORD rop1, DWORD rop2, DWORD rop3)
  700. {
  701.     HDC hMemDC = CreateCompatibleDC(hdcDest);
  702.     SelectObject(hMemDC, hbmMask);
  703.  
  704.     if ( (rop1>>16)!=0xAA ) // not D
  705.         BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, rop1);
  706.  
  707.     BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hMemDC, xMask, yMask, rop2);
  708.  
  709.     DeleteObject(hMemDC);
  710.  
  711.     if ( (rop3>>16)!=0xAA ) // not D
  712.         return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, rop3);
  713.     else
  714.         return TRUE;
  715. }
  716.  
  717.  
  718. BOOL G_MaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
  719.              HDC hdcSrc,  int nXSrc,  int nYSrc, 
  720.              HBITMAP hbmMask, int xMask, int yMask,
  721.              DWORD dwRop
  722. )
  723. {
  724.     DWORD back = (dwRop >> 24) & 0xFF;
  725.     DWORD fore = (dwRop >> 16) & 0xFF;
  726.  
  727.     if ( back==fore ) // foreground=background, hbmMask not needed
  728.         return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop & 0xFFFFFF);
  729.  
  730.     // if (M) D=fore(P,S,D) else D=back(P,S,D)
  731.     
  732.     if ( D_independent(back) )    // back independent of D
  733.         return TriBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, hbmMask, xMask, yMask,
  734.             fore^back << 16,    // ( fore^back, fore^back )
  735.             SRCAND,                // ( fore^back, 0 )
  736.             (back^0xAA) << 16); // { fore, back }
  737.  
  738.     if ( D_independent(fore) )  // fore independent of D
  739.         return TriBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, hbmMask, xMask, yMask,
  740.             (fore^back) << 16,  // ( fore^back, fore^back )
  741.             0x22 << 16,            // ( 0, fore^back )
  742.             (fore^0xAA) << 16); // { fore, back }
  743.  
  744.     // both foreground and background depend on D
  745.     if ( S_independent(back) && S_independent(fore) )
  746.         return TriBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, NULL, 0, 0, hbmMask, xMask, yMask,
  747.             0xAA << 16,            // ( D, D )
  748.             ( (fore & 0xCC) || (back & 0x33) ) << 16,
  749.             0xAA << 16);
  750.     
  751.     // both foreground and background depend on D
  752.     // either foregounr or background depends on S
  753.     HBITMAP hTemp  = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
  754.     HDC     hMemDC = CreateCompatibleDC(hdcDest);
  755.     SelectObject(hMemDC, hTemp);
  756.     BitBlt(hMemDC, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
  757.     SelectObject(hMemDC, GetCurrentObject(hdcDest, OBJ_BRUSH));
  758.     BitBlt(hMemDC, 0, 0, nWidth, nHeight, hdcSrc,  nXSrc, nYSrc, back << 16); // hMemDC contains final background image
  759.  
  760.     BitBlt(hdcDest, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, fore << 16);  // foreground image
  761.  
  762.     TriBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hMemDC, 0, 0, hbmMask, xMask, yMask,
  763.             SRCINVERT,    // ( fore^back, fore^back )
  764.             SRCAND,        // ( fore^back, 0 )
  765.             SRCINVERT); // { fore, back }
  766.  
  767.     DeleteObject(hMemDC);
  768.     DeleteObject(hTemp);
  769.     
  770.     return TRUE;
  771. }
  772.  
  773. // Use TransparentBlt to draw Icon
  774. /*
  775. void TransparentBltDrawIcon(HDC hDC, int x, int y, HICON hIcon)
  776. {
  777.     ICONINFO iconinfo;
  778.     GetIconInfo(hIcon, & iconinfo);
  779.  
  780.     BITMAP bmp;
  781.     GetObject(iconinfo.hbmMask, sizeof(bmp), & bmp);
  782.  
  783.     HDC hMemDC = CreateCompatibleDC(NULL);
  784.     HGDIOBJ hOld = SelectObject(hMemDC, iconinfo.hbmColor);
  785.  
  786.     COLORREF crTrans = GetPixel(hMemDC, 0, 0);
  787.  
  788.     TransparentBlt(hDC,    x, y, bmp.bmWidth, bmp.bmHeight, 
  789.                    hMemDC, 0, 0, bmp.bmWidth, bmp.bmHeight,
  790.                    crTrans);
  791.  
  792.     SelectObject(hMemDC, hOld);
  793.     DeleteObject(iconinfo.hbmMask);
  794.     DeleteObject(iconinfo.hbmColor);
  795.     DeleteObject(hMemDC);
  796. }
  797. */
  798.  
  799. // big pattern brush
  800. void MaskBitmapNT(HDC hDC, int x, int y, int width, int height, HBITMAP hMask, HDC hMemDC)
  801. {
  802.     HBRUSH hBrush = CreatePatternBrush(hMask);
  803.     HGDIOBJ hOld  = SelectObject(hDC, hBrush);
  804.  
  805.     POINT org = { x, y };
  806.     LPtoDP(hDC, &org, 1);
  807.     SetBrushOrgEx(hDC, org.x, org.y, NULL);
  808.  
  809.     BitBlt(hDC, x, y, width, height, hMemDC, 0, 0, 0x6C01E8); // S^(P&D)
  810.  
  811.     SelectObject(hDC, hOld);
  812.     DeleteObject(hBrush);
  813. }
  814.  
  815. void MaskBltDrawIcon(HDC hDC, int x, int y, HICON hIcon)
  816. {
  817.     ICONINFO iconinfo;
  818.     GetIconInfo(hIcon, & iconinfo);
  819.  
  820.     BITMAP bmp;
  821.     GetObject(iconinfo.hbmMask, sizeof(bmp), & bmp);
  822.  
  823.     HDC hMemDC = CreateCompatibleDC(NULL);
  824.     HGDIOBJ hOld = SelectObject(hMemDC, iconinfo.hbmColor);
  825.  
  826.     MaskBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0, 
  827.         iconinfo.hbmMask, 0, 0, MAKEROP4(SRCINVERT, SRCCOPY));
  828.  
  829.     SelectObject(hMemDC, hOld);
  830.     DeleteObject(iconinfo.hbmMask);
  831.     DeleteObject(iconinfo.hbmColor);
  832.     DeleteObject(hMemDC);
  833. }
  834.  
  835.