ddsurf.cpp
来自「Windows 图形编程 书籍」· C++ 代码 · 共 674 行 · 第 1/2 页
CPP
674 行
if ( pDIB )
{
HRESULT hr = CreateBitmapSurface(pDD, pDIB, mem);
delete [] (BYTE *) pDIB;
return hr;
}
else
return E_FAIL;
}
// Return first Z-buffer format found
HRESULT WINAPI EnumZBufferCallBack(DDPIXELFORMAT * pddpf, void * pResult)
{
if ( pddpf->dwFlags == DDPF_ZBUFFER )
{
memcpy(pResult, pddpf, sizeof(DDPIXELFORMAT));
return D3DENUMRET_CANCEL;
}
else
return D3DENUMRET_OK;
}
HRESULT KOffScreenSurface::CreateZBuffer(IDirect3D7 * pD3D, IDirectDraw7 * pDD, REFCLSID riidDevice,
int width, int height)
{
memset(& m_ddsd.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT));
pD3D->EnumZBufferFormats(riidDevice, EnumZBufferCallBack, & m_ddsd.ddpfPixelFormat);
if ( m_ddsd.ddpfPixelFormat.dwSize==sizeof(DDPIXELFORMAT) )
{
m_ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
m_ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
m_ddsd.dwWidth = width;
m_ddsd.dwHeight = height;
return pDD->CreateSurface(& m_ddsd, & m_pSurface, NULL);
}
else
return E_FAIL;
}
/////////////////////////////////////////////
HRESULT KDDSurface::SetClipper(IDirectDraw7 * pDD, HWND hWnd)
{
IDirectDrawClipper * pClipper;
HRESULT hr = pDD->CreateClipper(0, & pClipper, NULL);
if ( FAILED( hr ) )
return hr;
pClipper->SetHWnd(0, hWnd);
m_pSurface->SetClipper(pClipper);
return pClipper->Release();
}
HRESULT KDDSurface::FillColor(int x0, int y0, int x1, int y1, DWORD fillcolor)
{
DDBLTFX fx;
fx.dwSize = sizeof(fx);
fx.dwFillColor = fillcolor;
RECT rc = { x0, y0, x1, y1 };
return m_pSurface->Blt(& rc, NULL, NULL, DDBLT_COLORFILL, & fx);
}
DWORD KDDSurface::ColorMatch(BYTE red, BYTE green, BYTE blue)
{
if ( m_ddsd.ddpfPixelFormat.dwSize==0 ) // not initialized
GetSurfaceDesc(); // get surface description with pixelformat
const DDPIXELFORMAT & pf = m_ddsd.ddpfPixelFormat;
if ( pf.dwFlags & DDPF_RGB )
{
// x-5-5-5
if ( (pf.dwRBitMask == 0x7C00) && (pf.dwGBitMask == 0x03E0) && (pf.dwBBitMask==0x001F) )
return ((red>>3)<<10) | ((green>>3)<<5) | (blue>>3);
// 0-5-6-5
if ( (pf.dwRBitMask == 0xF800) && (pf.dwGBitMask == 0x07E0) && (pf.dwBBitMask==0x001F) )
return ((red>>3)<<11) | ((green>>2)<<5) | (blue>>3);
// x-8-8-8
if ( (pf.dwRBitMask == 0xFF0000) && (pf.dwGBitMask == 0xFF00) && (pf.dwBBitMask==0xFF) )
return (red<<16) | (green<<8) | blue;
}
DWORD rslt = 0;
if ( SUCCEEDED(GetDC()) ) // get GDI DC
{
int typ = GetObjectType(m_hDC);
HBITMAP hBmp = (HBITMAP) GetCurrentObject(m_hDC, OBJ_BITMAP);
DIBSECTION dibsec;
GetObject(hBmp, sizeof(dibsec), & dibsec);
COLORREF old = ::GetPixel(m_hDC, 0, 0); // save original pixel
::SetPixel(m_hDC, 0, 0, RGB(red, green, blue)); // put RGB pixel
ReleaseDC();
const DWORD * pSurface = (DWORD *) LockSurface(); // lock surface
if ( pSurface )
{
rslt = * pSurface; // read first DWORD
if ( pf.dwRGBBitCount < 32 )
rslt &= (1 << pf.dwRGBBitCount) - 1; // truncate to its bpp
Unlock(); // unlock surface
}
else
assert(false);
GetDC();
::SetPixel(m_hDC, 0, 0, old); // put original pixel back
ReleaseDC(); // release GDI DC
}
else
assert(false);
return rslt;
}
HRESULT KDDSurface::BitBlt(int x, int y, int w, int h, IDirectDrawSurface7 * pSrc, DWORD flag)
{
RECT rc = { x, y, x+w, y+h };
return m_pSurface->Blt(& rc, pSrc, NULL, flag, NULL);
}
HRESULT KDDSurface::SetSourceColorKey(DWORD color)
{
DDCOLORKEY key;
key.dwColorSpaceLowValue = color;
key.dwColorSpaceHighValue = color;
return m_pSurface->SetColorKey(DDCKEY_SRCBLT, & key);
}
DWORD KDDSurface::GetPixel(int x, int y)
{
KLockedSurface frame;
if ( frame.Initialize(* this) )
{
DWORD rslt = frame.GetPixel(x, y);
Unlock();
return rslt;
}
else
return 0;
}
BOOL KDDSurface::SetPixel(int x, int y, DWORD color)
{
KLockedSurface frame;
if ( frame.Initialize(* this) )
{
frame.SetPixel(x, y, color);
Unlock();
return TRUE;
}
else
return FALSE;
}
void KLockedSurface::Line(int x0, int y0, int x1, int y1, DWORD color)
{
int bps = (bpp+7) / 8; // bytes-per-pixel
BYTE * pPixel = pSurface + pitch * y0 + bps * x0; // first pixel address
int error; // error
int d_pixel_pos, d_error_pos; // adjustment to pixel address and error when error>=0
int d_pixel_neg, d_error_neg; // adjustment to pixel address and error when error<0
int dots; // number of dots to draw
{
int dx, dy, inc_x, inc_y;
if ( x1 > x0 )
{ dx = x1 - x0; inc_x = bps; }
else
{ dx = x0 - x1; inc_x = -bps; }
if ( y1 > y0 )
{ dy = y1 - y0; inc_y = pitch; }
else
{ dy = y0 - y1; inc_y = -pitch; }
d_pixel_pos = inc_x + inc_y; // move x and y
d_error_pos = (dy - dx) * 2;
if ( d_error_pos < 0 ) // x dominant
{
dots = dx;
error = dy*2 - dx;
d_pixel_neg = inc_x; // move x only
d_error_neg = dy * 2;
}
else
{
dots = dy;
error = dx*2 - dy;
d_error_pos = - d_error_pos;
d_pixel_neg = inc_y; // move y only
d_error_neg = dx * 2;
}
}
switch ( bps )
{
case 1:
for (; dots>=0; dots--) // 8-bpp pixel loop
{
pPixel[0] = (BYTE) color; // draw 8-bpp pixel
if ( error>=0 )
{ pPixel += d_pixel_pos; error += d_error_pos; }
else
{ pPixel += d_pixel_neg; error += d_error_neg; }
}
break;
case 2:
for (; dots>=0; dots--) // 16-bpp pixel loop
{
* (WORD *) pPixel = (WORD) color; // draw 16-bpp pixel
if ( error>=0 )
{ pPixel += d_pixel_pos; error += d_error_pos; }
else
{ pPixel += d_pixel_neg; error += d_error_neg; }
}
break;
case 3:
for (; dots>=0; dots--) // 24-bpp pixel loop
{
* (RGBTRIPLE *) pPixel = * (RGBTRIPLE *) & color; // draw 24-bpp pixel
if ( error>=0 )
{ pPixel += d_pixel_pos; error += d_error_pos; }
else
{ pPixel += d_pixel_neg; error += d_error_neg; }
}
break;
case 4:
for (; dots>=0; dots--) // 32-bpp pixel loop
{
* (DWORD *) pPixel = color; // draw 32-bpp pixel
if ( error>=0 )
{ pPixel += d_pixel_pos; error += d_error_pos; }
else
{ pPixel += d_pixel_neg; error += d_error_neg; }
}
break;
}
}
// 32-bpp Line drawing
/* eax : color
ebx : dots
ecx : error
edx : pPixel
esi : d_error_pos
edi : d_error_neg
ebp : d_pixel_neg
test ebx, ebx if ( dots<0 ) goto _finish;
jl _finish
mov eax, color eax = color
inc ebx dots ++;
_repeat: test ecx, ecx
mov [edx], eax * (DWORD *) pPixel = color;
jl _elsepart if ( error < 0 ) goto _elsepart
add edx, d_pixel_pos pPixel += d_pixel_pos
add ecx, esi error += d_error_pos
jmp _next goto _next
_elsepart: add edx, ebp pPixel += d_pixel_neg
add ecx, edi error += d_error_neg
_next: dec ebx dots --;
jne _repeat if ( dots!=0 ) goto _repeat
_finish:
*/
// Bresenham algorithm
BOOL KDDSurface::Line(int x0, int y0, int x1, int y1, DWORD color)
{
KLockedSurface frame;
if ( frame.Initialize(* this) )
{
frame.Line(x0, y0, x1, y1, color);
Unlock();
return TRUE;
}
else
return FALSE;
}
BOOL KDDSurface::FillRgn(HRGN hRgn, DWORD color)
{
RGNDATA * pRegion = GetClipRegionData(hRgn);
if ( pRegion==NULL )
return FALSE;
const RECT * pRect = (const RECT *) pRegion->Buffer;
for (unsigned i=0; i<pRegion->rdh.nCount; i++)
{
FillColor(pRect->left, pRect->top, pRect->right, pRect->bottom, color);
pRect ++;
}
delete [] (BYTE *) pRegion;
return TRUE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?