home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / ddsurf.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-12  |  17.4 KB  |  674 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   : ddsurf.cpp                                                             //
  10. //  Description: DirectDraw surface wrapper                                          //
  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 <stdio.h>
  19. #include <assert.h>
  20. #include <ddraw.h>
  21. #include <d3d.h>
  22.  
  23. #include "basicdib.h"
  24. #include "ddsurf.h"
  25. #include "ddwrap.h"
  26.  
  27. KDDSurface::KDDSurface()
  28. {
  29.     m_pSurface = NULL;
  30.     m_hDC      = NULL;
  31.  
  32.     memset(& m_ddsd, 0, sizeof(m_ddsd));
  33.        m_ddsd.dwSize = sizeof(m_ddsd);
  34. }
  35.  
  36. void KDDSurface::Discharge(void) // release before destructor
  37. {
  38.     ReleaseDC();
  39.     SAFE_RELEASE(m_pSurface);
  40. }
  41.  
  42.  
  43. BYTE * KDDSurface::LockSurface(RECT * pRect)
  44. {
  45.     if ( FAILED(m_pSurface->Lock(pRect, & m_ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)) )
  46.         return NULL;
  47.     else
  48.         return (BYTE *) m_ddsd.lpSurface;
  49. }
  50.  
  51. const DDSURFACEDESC2 * KDDSurface::GetSurfaceDesc(void)
  52. {
  53.     if ( SUCCEEDED(m_pSurface->GetSurfaceDesc(& m_ddsd)) )
  54.         return & m_ddsd;
  55.     else
  56.         return NULL;
  57. }
  58.  
  59. HRESULT KDDSurface::Unlock(RECT * pRect)
  60. {
  61.     m_ddsd.lpSurface = NULL;  // make it unavailable
  62.  
  63.     return m_pSurface->Unlock(pRect);
  64. }
  65.  
  66.  
  67. HRESULT KDDSurface::RestoreSurface(void) // restore if lost
  68. {
  69.     if ( m_pSurface )
  70.         if ( m_pSurface->IsLost() )
  71.             return m_pSurface->Restore();
  72.         else
  73.             return DD_OK;
  74.     else
  75.         return E_FAIL;
  76. }
  77.  
  78.  
  79. HRESULT KDDSurface::GetDC(void)
  80. {
  81.     return m_pSurface->GetDC(&m_hDC);
  82. }
  83.  
  84.  
  85. HRESULT KDDSurface::ReleaseDC(void)
  86. {
  87.     if ( m_hDC==NULL )
  88.         return S_OK;
  89.     
  90.     HRESULT hr = m_pSurface->ReleaseDC(m_hDC);
  91.     m_hDC = NULL;
  92.     return hr;
  93. }
  94.  
  95. HRESULT KDDSurface::CreatePrimarySurface(IDirectDraw7 * pDD, int nBufferCount)
  96. {
  97.     if ( nBufferCount==0 )
  98.     {
  99.         m_ddsd.dwFlags             = DDSD_CAPS;
  100.         m_ddsd.ddsCaps.dwCaps     = DDSCAPS_PRIMARYSURFACE;
  101.     }
  102.     else
  103.     {
  104.         m_ddsd.dwFlags           = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  105.         m_ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX |
  106.                                    DDSCAPS_VIDEOMEMORY;
  107.         m_ddsd.dwBackBufferCount = nBufferCount;
  108.     }
  109.     
  110.     return pDD->CreateSurface(& m_ddsd, & m_pSurface, NULL);
  111. }
  112.  
  113. HRESULT SetPixelFormat(DDPIXELFORMAT & pixelformat, int bpp)
  114. {
  115.     memset(& pixelformat, 0, sizeof(pixelformat));
  116.  
  117.     pixelformat.dwSize  = sizeof(pixelformat);
  118.  
  119.     switch ( bpp )
  120.     {
  121.         case 1 : 
  122.             pixelformat.dwFlags                = DDPF_RGB | DDPF_PALETTEINDEXED1; 
  123.             pixelformat.dwRGBBitCount        = 1;
  124.             break;
  125.         
  126.         case 2 : 
  127.             pixelformat.dwFlags                = DDPF_RGB | DDPF_PALETTEINDEXED2; 
  128.             pixelformat.dwRGBBitCount        = 2;
  129.             break;
  130.         
  131.         case 4 : 
  132.             pixelformat.dwFlags                = DDPF_RGB | DDPF_PALETTEINDEXED4; 
  133.             pixelformat.dwRGBBitCount        = 4;
  134.             break;
  135.         
  136.         case 8 : 
  137.             pixelformat.dwFlags                = DDPF_RGB | DDPF_PALETTEINDEXED8; 
  138.             pixelformat.dwRGBBitCount        = 8;
  139.             break;
  140.     
  141.         case 15: // 1-5-5-5
  142.             pixelformat.dwFlags                = DDPF_RGB | DDPF_ALPHAPIXELS;
  143.             pixelformat.dwRGBBitCount        = 16;
  144.             pixelformat.dwRGBAlphaBitMask   = 0x00008000;
  145.             pixelformat.dwRBitMask            = 0x00007C00;
  146.             pixelformat.dwGBitMask            = 0x000003E0;
  147.             pixelformat.dwBBitMask            = 0x0000001F;
  148.             break;
  149.  
  150.         case 16: // 0-5-6-5
  151.             pixelformat.dwFlags                = DDPF_RGB;
  152.             pixelformat.dwRGBBitCount        = 16;
  153.             pixelformat.dwRGBAlphaBitMask   = 0x00000000;
  154.             pixelformat.dwRBitMask            = 0x0000F800;
  155.             pixelformat.dwGBitMask            = 0x000007E0;
  156.             pixelformat.dwBBitMask            = 0x0000001F;
  157.             break;
  158.         
  159.         case 24: // 0-8-8-8
  160.             pixelformat.dwFlags                = DDPF_RGB;
  161.             pixelformat.dwRGBBitCount        = 24;
  162.             pixelformat.dwRGBAlphaBitMask   = 0x00000000;
  163.             pixelformat.dwRBitMask            = 0x00FF0000;
  164.             pixelformat.dwGBitMask            = 0x0000FF00;
  165.             pixelformat.dwBBitMask            = 0x000000FF;
  166.             break;
  167.  
  168.         case 32: // 8-8-8-8
  169.             pixelformat.dwFlags                = DDPF_RGB | DDPF_ALPHAPIXELS;
  170.             pixelformat.dwRGBBitCount        = 32;
  171.             pixelformat.dwRGBAlphaBitMask   = 0xFF000000;
  172.             pixelformat.dwRBitMask            = 0x00FF0000;
  173.             pixelformat.dwGBitMask            = 0x0000FF00;
  174.             pixelformat.dwBBitMask            = 0x000000FF;
  175.             break;
  176.  
  177.         default:
  178.             return E_FAIL;
  179.     }
  180.  
  181.     return S_OK;
  182. }
  183.  
  184. const DWORD MEMFLAGS[] =
  185. {
  186.     0,
  187.     DDSCAPS_SYSTEMMEMORY,
  188.     DDSCAPS_NONLOCALVIDMEM | DDSCAPS_VIDEOMEMORY,
  189.     DDSCAPS_LOCALVIDMEM    | DDSCAPS_VIDEOMEMORY
  190. };
  191.  
  192. HRESULT KOffScreenSurface::CreateOffScreenSurfaceBpp(IDirectDraw7 * pDD, int width, int height, int bpp, int mem)
  193. {
  194.     m_ddsd.dwFlags        = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
  195.     m_ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | MEMFLAGS[mem];
  196.     m_ddsd.dwWidth        = width;
  197.     m_ddsd.dwHeight       = height;
  198.  
  199.     if ( SUCCEEDED(SetPixelFormat(m_ddsd.ddpfPixelFormat, bpp)) )
  200.         return pDD->CreateSurface(& m_ddsd, & m_pSurface, NULL);
  201.     else
  202.         return E_FAIL;
  203. }
  204.  
  205.  
  206. HRESULT KOffScreenSurface::CreateOffScreenSurface(IDirectDraw7 * pDD, int width, int height, int mem)
  207. {
  208.     m_ddsd.dwFlags        = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  209.     m_ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | MEMFLAGS[mem];
  210.     m_ddsd.dwWidth        = width;
  211.     m_ddsd.dwHeight       = height;
  212.  
  213.     return pDD->CreateSurface(& m_ddsd, & m_pSurface, NULL);
  214. }
  215.  
  216.  
  217. HRESULT CALLBACK TextureCallback(DDPIXELFORMAT* pddpf, void * param)
  218. {
  219.     // find a simple >=16-bpp texture format
  220.     if ( (pddpf->dwFlags & (DDPF_LUMINANCE|DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV|DDPF_ALPHAPIXELS))==0 )
  221.     if ( (pddpf->dwFourCC == 0) && (pddpf->dwRGBBitCount>=16) )
  222.     {
  223.         memcpy(param, pddpf, sizeof(DDPIXELFORMAT) );
  224.         return DDENUMRET_CANCEL; // stop search
  225.     }
  226.  
  227.     return DDENUMRET_OK; // continue
  228. }
  229.  
  230.  
  231. HRESULT KOffScreenSurface::CreateTextureSurface(IDirect3DDevice7 * pD3DDevice, IDirectDraw7 * pDD, unsigned width, unsigned height)
  232. {
  233.     // query device caps
  234.     D3DDEVICEDESC7 ddDesc;
  235.  
  236.     HRESULT hr = pD3DDevice->GetCaps(&ddDesc);
  237.     if ( FAILED(hr) )
  238.         return hr;
  239.  
  240.     m_ddsd.dwFlags         = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH |
  241.                              DDSD_PIXELFORMAT | DDSD_TEXTURESTAGE;
  242.     m_ddsd.ddsCaps.dwCaps  = DDSCAPS_TEXTURE;
  243.     m_ddsd.dwWidth         = width;
  244.     m_ddsd.dwHeight        = height;
  245.  
  246.     // Turn on texture management for hardware devices
  247.     if ( (ddDesc.deviceGUID == IID_IDirect3DHALDevice) || 
  248.          (ddDesc.deviceGUID == IID_IDirect3DTnLHalDevice) )
  249.         m_ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
  250.     else
  251.         m_ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  252.  
  253.     // Adjust width and height, if the driver requires it
  254.     if ( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
  255.     {
  256.         for ( m_ddsd.dwWidth=1;  width  > m_ddsd.dwWidth;   m_ddsd.dwWidth<<=1 );
  257.         for ( m_ddsd.dwHeight=1; height > m_ddsd.dwHeight; m_ddsd.dwHeight<<=1 );
  258.     }
  259.     
  260.     if ( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
  261.     {
  262.         if ( m_ddsd.dwWidth > m_ddsd.dwHeight ) 
  263.             m_ddsd.dwHeight = m_ddsd.dwWidth;
  264.         else
  265.             m_ddsd.dwWidth  = m_ddsd.dwHeight;
  266.     }
  267.  
  268.     memset(& m_ddsd.ddpfPixelFormat, 0, sizeof(m_ddsd.ddpfPixelFormat));
  269.     pD3DDevice->EnumTextureFormats(TextureCallback, & m_ddsd.ddpfPixelFormat);
  270.     
  271.     if ( m_ddsd.ddpfPixelFormat.dwRGBBitCount )
  272.         return pDD->CreateSurface( & m_ddsd, & m_pSurface, NULL );
  273.     else
  274.         return E_FAIL;
  275. }
  276.  
  277. HRESULT KDDSurface::DrawBitmap(const BITMAPINFO * pDIB, int x, int y, int w, int h)
  278. {
  279.     if ( SUCCEEDED(GetDC()) )
  280.     {
  281.         StretchDIBits(m_hDC, x, y, w, h,
  282.             0, 0, pDIB->bmiHeader.biWidth, pDIB->bmiHeader.biHeight, 
  283.             & pDIB->bmiColors[GetDIBColorCount(pDIB)], pDIB, DIB_RGB_COLORS, SRCCOPY);
  284.  
  285.         return ReleaseDC();
  286.     }
  287.     else
  288.         return E_FAIL;
  289. }
  290.  
  291. HRESULT KOffScreenSurface::CreateTextureSurface(IDirect3DDevice7 * pD3DDevice, IDirectDraw7 * pDD, const BITMAPINFO * pDIB)
  292. {
  293.     if ( pDIB==NULL )
  294.         return E_FAIL;
  295.  
  296.     HRESULT hr = CreateTextureSurface(pD3DDevice, pDD, pDIB->bmiHeader.biWidth, pDIB->bmiHeader.biHeight);
  297.     if ( FAILED(hr) )
  298.         return hr;
  299.  
  300.     return DrawBitmap(pDIB, 0, 0, m_ddsd.dwWidth, m_ddsd.dwHeight);
  301. }
  302.  
  303.  
  304. HRESULT KOffScreenSurface::CreateTextureSurface(IDirect3DDevice7 * pD3DDevice, IDirectDraw7 * pDD, const TCHAR * pFileName)
  305. {
  306.     BITMAPINFO * pDIB = LoadBMPFile(pFileName);
  307.  
  308.     if ( pDIB )
  309.     {
  310.         HRESULT hr = CreateTextureSurface(pD3DDevice, pDD, pDIB);
  311.     
  312.         delete [] (BYTE *) pDIB;
  313.  
  314.         return hr;
  315.     }
  316.     else
  317.         return E_FAIL;
  318. }
  319.  
  320.  
  321. HRESULT KOffScreenSurface::CreateBitmapSurface(IDirectDraw7 * pDD, const BITMAPINFO * pDIB, int mem)
  322. {
  323.     if ( pDIB==NULL )
  324.         return E_FAIL;
  325.  
  326.     HRESULT hr = CreateOffScreenSurface(pDD, pDIB->bmiHeader.biWidth, abs(pDIB->bmiHeader.biHeight), mem);
  327.     if ( FAILED(hr) )
  328.         return hr;
  329.  
  330.     return DrawBitmap(pDIB, 0, 0, m_ddsd.dwWidth, m_ddsd.dwHeight);
  331. }
  332.  
  333.  
  334. HRESULT KOffScreenSurface::CreateBitmapSurface(IDirectDraw7 * pDD, const TCHAR * pFileName, int mem)
  335. {
  336.     BITMAPINFO * pDIB = LoadBMPFile(pFileName);
  337.  
  338.     if ( pDIB )
  339.     {
  340.         HRESULT hr = CreateBitmapSurface(pDD, pDIB, mem);
  341.     
  342.         delete [] (BYTE *) pDIB;
  343.  
  344.         return hr;
  345.     }
  346.     else
  347.         return E_FAIL;
  348. }
  349.  
  350.  
  351. // Return first Z-buffer format found
  352. HRESULT WINAPI EnumZBufferCallBack(DDPIXELFORMAT * pddpf, void * pResult)
  353. {
  354.     if ( pddpf->dwFlags == DDPF_ZBUFFER )
  355.     {
  356.         memcpy(pResult, pddpf, sizeof(DDPIXELFORMAT));
  357.         return D3DENUMRET_CANCEL;
  358.     }
  359.     else
  360.         return D3DENUMRET_OK;
  361. }
  362.  
  363.  
  364. HRESULT KOffScreenSurface::CreateZBuffer(IDirect3D7 * pD3D, IDirectDraw7 * pDD, REFCLSID riidDevice,
  365.              int width, int height)
  366. {
  367.     memset(& m_ddsd.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT));
  368.  
  369.     pD3D->EnumZBufferFormats(riidDevice, EnumZBufferCallBack, & m_ddsd.ddpfPixelFormat);
  370.  
  371.     if ( m_ddsd.ddpfPixelFormat.dwSize==sizeof(DDPIXELFORMAT) )
  372.     {
  373.         m_ddsd.dwFlags        = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
  374.         m_ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
  375.         m_ddsd.dwWidth        = width;
  376.         m_ddsd.dwHeight       = height;
  377.  
  378.         return pDD->CreateSurface(& m_ddsd, & m_pSurface, NULL);
  379.     }
  380.     else
  381.         return E_FAIL;
  382. }
  383.  
  384. /////////////////////////////////////////////
  385.  
  386. HRESULT KDDSurface::SetClipper(IDirectDraw7 * pDD, HWND hWnd)
  387. {
  388.     IDirectDrawClipper * pClipper;
  389.  
  390.     HRESULT hr = pDD->CreateClipper(0, & pClipper, NULL);
  391.     if ( FAILED( hr ) )
  392.         return hr;
  393.  
  394.     pClipper->SetHWnd(0, hWnd);
  395.     
  396.     m_pSurface->SetClipper(pClipper);
  397.  
  398.     return pClipper->Release();
  399. }
  400.  
  401.  
  402. HRESULT KDDSurface::FillColor(int x0, int y0, int x1, int y1, DWORD fillcolor)
  403. {
  404.     DDBLTFX fx;
  405.     fx.dwSize       = sizeof(fx);
  406.     fx.dwFillColor = fillcolor;
  407.  
  408.     RECT rc  = { x0, y0, x1, y1 };
  409.             
  410.     return m_pSurface->Blt(& rc, NULL, NULL, DDBLT_COLORFILL, & fx);
  411. }
  412.  
  413.  
  414. DWORD KDDSurface::ColorMatch(BYTE red, BYTE green, BYTE blue)
  415. {
  416.     if ( m_ddsd.ddpfPixelFormat.dwSize==0 ) // not initialized
  417.         GetSurfaceDesc();                    // get surface description with pixelformat
  418.  
  419.     const DDPIXELFORMAT & pf = m_ddsd.ddpfPixelFormat;
  420.  
  421.     if ( pf.dwFlags & DDPF_RGB ) 
  422.     {
  423.         // x-5-5-5
  424.         if ( (pf.dwRBitMask    == 0x7C00) && (pf.dwGBitMask == 0x03E0) && (pf.dwBBitMask==0x001F) )
  425.             return ((red>>3)<<10) | ((green>>3)<<5) | (blue>>3);
  426.  
  427.         // 0-5-6-5
  428.         if ( (pf.dwRBitMask    == 0xF800) && (pf.dwGBitMask == 0x07E0) && (pf.dwBBitMask==0x001F) )
  429.             return ((red>>3)<<11) | ((green>>2)<<5) | (blue>>3);
  430.  
  431.         // x-8-8-8
  432.         if ( (pf.dwRBitMask    == 0xFF0000) && (pf.dwGBitMask == 0xFF00) && (pf.dwBBitMask==0xFF) )
  433.             return (red<<16) | (green<<8) | blue;
  434.     }
  435.  
  436.     DWORD rslt = 0;
  437.  
  438.     if ( SUCCEEDED(GetDC()) )                                // get GDI DC
  439.     {
  440.         int typ      = GetObjectType(m_hDC);
  441.         HBITMAP hBmp = (HBITMAP) GetCurrentObject(m_hDC, OBJ_BITMAP);
  442.         DIBSECTION dibsec;
  443.         GetObject(hBmp, sizeof(dibsec), & dibsec);
  444.  
  445.         COLORREF old = ::GetPixel(m_hDC, 0, 0);                // save original pixel
  446.         ::SetPixel(m_hDC, 0, 0, RGB(red, green, blue));        // put RGB pixel
  447.         ReleaseDC();
  448.  
  449.         const DWORD * pSurface = (DWORD *) LockSurface();   // lock surface
  450.  
  451.         if ( pSurface )
  452.         {
  453.             rslt = * pSurface;                                // read first DWORD
  454.             if ( pf.dwRGBBitCount < 32 )
  455.                 rslt &=  (1 << pf.dwRGBBitCount) - 1;        // truncate to its bpp
  456.             Unlock();                                        // unlock surface
  457.         }
  458.         else
  459.             assert(false);
  460.     
  461.         GetDC();
  462.         ::SetPixel(m_hDC, 0, 0, old);                            // put original pixel back
  463.         ReleaseDC();                                        // release GDI DC
  464.     }
  465.     else
  466.         assert(false);
  467.  
  468.     return rslt;
  469. }
  470.  
  471. HRESULT KDDSurface::BitBlt(int x, int y, int w, int h, IDirectDrawSurface7 * pSrc, DWORD flag)
  472. {
  473.     RECT rc = { x, y, x+w, y+h };
  474.  
  475.     return m_pSurface->Blt(& rc, pSrc, NULL, flag, NULL);
  476. }
  477.  
  478.  
  479. HRESULT KDDSurface::SetSourceColorKey(DWORD color)
  480. {
  481.     DDCOLORKEY key;
  482.  
  483.     key.dwColorSpaceLowValue  = color;
  484.     key.dwColorSpaceHighValue = color;
  485.     
  486.     return m_pSurface->SetColorKey(DDCKEY_SRCBLT, & key);
  487. }
  488.  
  489. DWORD KDDSurface::GetPixel(int x, int y)
  490. {
  491.     KLockedSurface frame;
  492.         
  493.     if ( frame.Initialize(* this) )
  494.     {
  495.         DWORD rslt = frame.GetPixel(x, y);
  496.         Unlock();
  497.         return rslt;
  498.     }
  499.     else
  500.         return 0;
  501. }
  502.  
  503.  
  504. BOOL KDDSurface::SetPixel(int x, int y, DWORD color)
  505. {
  506.     KLockedSurface frame;
  507.     
  508.     if ( frame.Initialize(* this) )
  509.     {
  510.         frame.SetPixel(x, y, color);
  511.         Unlock();
  512.         return TRUE;
  513.     }
  514.     else
  515.         return FALSE;
  516. }
  517.  
  518.  
  519. void KLockedSurface::Line(int x0, int y0, int x1, int y1, DWORD color)
  520. {
  521.     int bps       = (bpp+7) / 8;                      // bytes-per-pixel
  522.     BYTE * pPixel = pSurface + pitch * y0 + bps * x0; // first pixel address
  523.  
  524.     int error;                        // error
  525.     int d_pixel_pos, d_error_pos;   // adjustment to pixel address and error when error>=0
  526.     int d_pixel_neg, d_error_neg;    // adjustment to pixel address and error when error<0
  527.     int dots;                        // number of dots to draw
  528.  
  529.     {
  530.         int dx, dy, inc_x, inc_y;
  531.  
  532.         if ( x1 > x0 )
  533.         {     dx = x1 - x0; inc_x =  bps; }
  534.         else
  535.         {    dx = x0 - x1; inc_x = -bps; }
  536.  
  537.         if ( y1 > y0 )
  538.         {     dy = y1 - y0; inc_y =  pitch; }
  539.         else
  540.         {    dy = y0 - y1; inc_y = -pitch; }
  541.  
  542.         d_pixel_pos = inc_x + inc_y;    // move x and y
  543.         d_error_pos = (dy - dx) * 2;
  544.     
  545.         if ( d_error_pos < 0 ) // x dominant
  546.         {
  547.             dots        = dx;
  548.             error       = dy*2 - dx;
  549.             d_pixel_neg = inc_x;        // move x only
  550.             d_error_neg = dy * 2;
  551.         }
  552.         else
  553.         {
  554.             dots        = dy;
  555.             error       = dx*2 - dy;
  556.             d_error_pos = - d_error_pos;
  557.             d_pixel_neg = inc_y;        // move y only
  558.             d_error_neg = dx * 2;
  559.         }
  560.     }
  561.  
  562.     switch ( bps )
  563.     {
  564.         case 1:
  565.             for (; dots>=0; dots--)            // 8-bpp pixel loop
  566.             {
  567.                 pPixel[0] = (BYTE) color;    // draw 8-bpp pixel
  568.             
  569.                 if ( error>=0 )
  570.                 {  pPixel += d_pixel_pos; error  += d_error_pos; }
  571.                 else
  572.                 {  pPixel += d_pixel_neg; error  += d_error_neg; }
  573.             }
  574.             break;
  575.  
  576.         case 2:
  577.             for (; dots>=0; dots--)            // 16-bpp pixel loop
  578.             {
  579.                 * (WORD *) pPixel = (WORD) color;    // draw 16-bpp pixel
  580.             
  581.                 if ( error>=0 )
  582.                 {  pPixel += d_pixel_pos; error  += d_error_pos; }
  583.                 else
  584.                 {  pPixel += d_pixel_neg; error  += d_error_neg; }
  585.             }
  586.             break;
  587.  
  588.         case 3:
  589.             for (; dots>=0; dots--)            // 24-bpp pixel loop
  590.             {
  591.                 * (RGBTRIPLE *) pPixel = * (RGBTRIPLE *) & color;    // draw 24-bpp pixel
  592.             
  593.                 if ( error>=0 )
  594.                 {  pPixel += d_pixel_pos; error  += d_error_pos; }
  595.                 else
  596.                 {  pPixel += d_pixel_neg; error  += d_error_neg; }
  597.             }
  598.             break;
  599.  
  600.         case 4:
  601.             for (; dots>=0; dots--)            // 32-bpp pixel loop
  602.             {
  603.                 * (DWORD *) pPixel = color;    // draw 32-bpp pixel
  604.             
  605.                 if ( error>=0 )
  606.                 {  pPixel += d_pixel_pos; error  += d_error_pos; }
  607.                 else
  608.                 {  pPixel += d_pixel_neg; error  += d_error_neg; }
  609.             }
  610.             break;
  611.     }
  612. }
  613.  
  614. // 32-bpp Line drawing
  615. /*         eax : color
  616.          ebx : dots
  617.          ecx : error
  618.          edx : pPixel
  619.          esi : d_error_pos
  620.          edi : d_error_neg
  621.          ebp : d_pixel_neg
  622.              
  623.             test    ebx, ebx            if ( dots<0 ) goto _finish;
  624.             jl        _finish
  625.             mov        eax, color            eax = color
  626.             inc        ebx                    dots ++;
  627. _repeat:    test    ecx, ecx            
  628.             mov        [edx], eax            * (DWORD *) pPixel = color;
  629.             jl        _elsepart            if ( error < 0 ) goto _elsepart
  630.             add        edx, d_pixel_pos    pPixel += d_pixel_pos
  631.             add        ecx, esi            error  += d_error_pos
  632.             jmp        _next                goto _next
  633. _elsepart:    add        edx, ebp            pPixel += d_pixel_neg
  634.             add        ecx, edi            error  += d_error_neg
  635. _next:        dec        ebx                 dots --;
  636.             jne        _repeat             if ( dots!=0 ) goto _repeat
  637. _finish:
  638. */
  639.  
  640. // Bresenham algorithm
  641. BOOL KDDSurface::Line(int x0, int y0, int x1, int y1, DWORD color)
  642. {
  643.     KLockedSurface frame;
  644.         
  645.     if ( frame.Initialize(* this) )
  646.     {
  647.         frame.Line(x0, y0, x1, y1, color);
  648.         Unlock();
  649.         return TRUE;
  650.     }
  651.     else
  652.         return FALSE;
  653. }
  654.  
  655. BOOL KDDSurface::FillRgn(HRGN hRgn, DWORD color)
  656. {
  657.     RGNDATA * pRegion = GetClipRegionData(hRgn);
  658.  
  659.     if ( pRegion==NULL )
  660.         return FALSE;
  661.  
  662.     const RECT * pRect = (const RECT *) pRegion->Buffer;
  663.     
  664.     for (unsigned i=0; i<pRegion->rdh.nCount; i++)
  665.     {
  666.         FillColor(pRect->left, pRect->top, pRect->right, pRect->bottom, color);
  667.         pRect ++;
  668.     }
  669.  
  670.     delete [] (BYTE *) pRegion;
  671.  
  672.     return TRUE;
  673. }
  674.