Initial commit: Complete open-source Decal rebuild
All 5 phases of the open-source Decal rebuild: Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil) Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters - Decal.Core, DecalControls, DecalRender, D3DService Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL Phase 4: DenAgent WinForms tray application Phase 5: WiX installer and build script 25 C# projects building with 0 errors. Native C++ projects require VS 2022 + Windows SDK (x86). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
d1442e3747
1382 changed files with 170725 additions and 0 deletions
748
Native/Inject/Canvas.cpp
Normal file
748
Native/Inject/Canvas.cpp
Normal file
|
|
@ -0,0 +1,748 @@
|
|||
// Canvas.cpp : Implementation of cCanvas
|
||||
#include "stdafx.h"
|
||||
#include "Inject.h"
|
||||
#include "Canvas.h"
|
||||
|
||||
#include "Manager.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// cCanvas
|
||||
|
||||
cCanvas::~cCanvas()
|
||||
{
|
||||
_ASSERTE( m_hdc == NULL );
|
||||
|
||||
if( m_rgn != NULL )
|
||||
::DeleteObject( m_rgn );
|
||||
}
|
||||
|
||||
void cCanvas::testSurface()
|
||||
{
|
||||
if( m_pSurface.p == NULL )
|
||||
cManager::_p->createSurface( &m_sz, &m_pSurface );
|
||||
else if( m_pSurface->IsLost() != DD_OK )
|
||||
m_pSurface->Restore();
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::PushClipRect(LPRECT prc, VARIANT_BOOL *pbVisible)
|
||||
{
|
||||
_ASSERTE( prc != NULL );
|
||||
_ASSERTE( prc->right >= prc->left && prc->bottom >= prc->top );
|
||||
_ASSERTE( pbVisible != NULL );
|
||||
|
||||
ClipParams ¤t = m_clipping.top();
|
||||
|
||||
if( !current.visible )
|
||||
{
|
||||
// Not visible means just push and hope for a pop
|
||||
m_clipping.push( current );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int nChildLeft = prc->left + current.window.left - current.org.x,
|
||||
nChildTop = prc->top + current.window.top - current.org.y,
|
||||
nChildWidth = prc->right - prc->left,
|
||||
nChildHeight = prc->bottom - prc->top;
|
||||
|
||||
ClipParams p = {
|
||||
{ nChildLeft, nChildTop, nChildLeft + nChildWidth, nChildTop + nChildHeight },
|
||||
{ 0, 0 },
|
||||
VARIANT_TRUE };
|
||||
|
||||
// Clip the four sides of the rectangle
|
||||
if( p.window.left < current.window.left )
|
||||
{
|
||||
// Clip left edge
|
||||
p.org.x += current.window.left - p.window.left;
|
||||
p.window.left = current.window.left;
|
||||
}
|
||||
|
||||
if( p.window.top < current.window.top )
|
||||
{
|
||||
// Clip top edge
|
||||
p.org.y += current.window.top - p.window.top;
|
||||
p.window.top = current.window.top;
|
||||
}
|
||||
|
||||
if( p.window.right > current.window.right )
|
||||
// Clip right edge
|
||||
p.window.right = current.window.right;
|
||||
|
||||
if( p.window.bottom > current.window.bottom )
|
||||
// Clip bottom edge
|
||||
p.window.bottom = current.window.bottom;
|
||||
|
||||
// Check for clipping out of existance
|
||||
if( p.window.left >= p.window.right || p.window.top >= p.window.bottom )
|
||||
// This rectangle is no longer visible
|
||||
p.visible = VARIANT_FALSE;
|
||||
|
||||
// Return the remainder of the rectangle
|
||||
*pbVisible = p.visible;
|
||||
|
||||
m_clipping.push( p );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::PopClipRect()
|
||||
{
|
||||
_ASSERTE( m_clipping.size() > 1 );
|
||||
|
||||
m_clipping.pop();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::GetDC(HDC *pdc)
|
||||
{
|
||||
_ASSERTE( pdc != NULL );
|
||||
|
||||
testSurface();
|
||||
|
||||
if( m_hdc != NULL )
|
||||
// Already checked out
|
||||
return E_FAIL;
|
||||
|
||||
m_pSurface->GetDC( &m_hdc );
|
||||
|
||||
// Create a clipping region
|
||||
ClipParams ¶m = m_clipping.top();
|
||||
|
||||
if( m_rgn == NULL )
|
||||
m_rgn = ::CreateRectRgnIndirect( ¶m.window );
|
||||
else
|
||||
::SetRectRgn( m_rgn, param.window.left, param.window.top, param.window.right, param.window.bottom );
|
||||
|
||||
::SelectObject( m_hdc, m_rgn );
|
||||
|
||||
// Set the origin
|
||||
::SetWindowOrgEx( m_hdc, -param.window.left + param.org.x, -param.window.top + param.org.y, NULL );
|
||||
|
||||
*pdc = m_hdc;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::ReleaseDC()
|
||||
{
|
||||
if( m_hdc == NULL )
|
||||
return E_FAIL;
|
||||
|
||||
m_pSurface->ReleaseDC( m_hdc );
|
||||
m_hdc = NULL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::GetSurface(REFIID iid, void **ppvItf)
|
||||
{
|
||||
_ASSERTE( iid == IID_IDirectDrawSurface4 );
|
||||
_ASSERTE( ppvItf != NULL );
|
||||
|
||||
testSurface();
|
||||
|
||||
return m_pSurface->QueryInterface( iid, ppvItf );
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::GetClipParams(ClipParams *pParams)
|
||||
{
|
||||
_ASSERTE( pParams != NULL );
|
||||
|
||||
*pParams = m_clipping.top();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::Fill(LPRECT prc, long nRGB)
|
||||
{
|
||||
_ASSERTE( prc != NULL );
|
||||
_ASSERTE( prc->right > prc->left && prc->bottom > prc->top );
|
||||
|
||||
testSurface();
|
||||
|
||||
VARIANT_BOOL bVisible;
|
||||
PushClipRect( prc, &bVisible );
|
||||
|
||||
if( bVisible )
|
||||
{
|
||||
DDBLTFX fx;
|
||||
::memset( &fx, 0, sizeof( DDBLTFX ) );
|
||||
|
||||
fx.dwSize = sizeof( DDBLTFX );
|
||||
|
||||
DownMixRGB((BYTE)nRGB, (BYTE)(nRGB >> 8), (BYTE)(nRGB >> 16), (WORD *)&fx.dwFillColor);
|
||||
|
||||
m_pSurface->Blt( &m_clipping.top().window, NULL, NULL, DDBLT_COLORFILL, &fx );
|
||||
}
|
||||
|
||||
PopClipRect();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::Frame(LPRECT prc, long nRGB)
|
||||
{
|
||||
_ASSERTE( prc != NULL );
|
||||
_ASSERTE( prc->right > prc->left && prc->bottom > prc->top );
|
||||
|
||||
testSurface();
|
||||
|
||||
// TODO: Add your implementation code here
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::get_WasLost(VARIANT_BOOL *pVal)
|
||||
{
|
||||
_ASSERTE( pVal != NULL );
|
||||
|
||||
*pVal = VARIANT_FALSE;
|
||||
|
||||
if( m_pSurface.p != NULL )
|
||||
{
|
||||
if( m_pSurface->IsLost() != DD_OK )
|
||||
*pVal = VARIANT_TRUE;
|
||||
}
|
||||
else
|
||||
*pVal = VARIANT_TRUE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::get_Size(LPSIZE pVal)
|
||||
{
|
||||
_ASSERTE( pVal != NULL );
|
||||
|
||||
*pVal = m_sz;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::put_Size(LPSIZE newVal)
|
||||
{
|
||||
_ASSERTE( newVal->cx > 0 && newVal->cy > 0 );
|
||||
_ASSERTE( m_clipping.size() == 1 );
|
||||
|
||||
if( m_sz.cx != newVal->cx || m_sz.cy != newVal->cy )
|
||||
{
|
||||
m_sz = *newVal;
|
||||
if( m_pSurface.p )
|
||||
// Next frame this'll be marked as lost
|
||||
m_pSurface.Release();
|
||||
|
||||
// Reset the bounds in the root clip rectangle
|
||||
ClipParams &clip = m_clipping.top();
|
||||
clip.window.right = clip.window.left + newVal->cx;
|
||||
clip.window.bottom = clip.window.top + newVal->cy;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::Blt(LPRECT prcSrc, ICanvas *pSrc, LPPOINT pptDest)
|
||||
{
|
||||
_ASSERTE( pSrc != NULL );
|
||||
_ASSERTE( prcSrc != NULL );
|
||||
_ASSERTE( prcSrc->right > prcSrc->left && prcSrc->bottom > prcSrc->top );
|
||||
_ASSERTE( pptDest != NULL );
|
||||
|
||||
testSurface();
|
||||
|
||||
// Ok, first, make up the clip rect
|
||||
RECT rc = { pptDest->x, pptDest->y, pptDest->x + ( prcSrc->right - prcSrc->left ),
|
||||
pptDest->y + ( prcSrc->bottom - prcSrc->top ) };
|
||||
VARIANT_BOOL bVisible;
|
||||
|
||||
PushClipRect( &rc, &bVisible );
|
||||
if( bVisible )
|
||||
{
|
||||
CComPtr< IDirectDrawSurface4 > pSurf;
|
||||
pSrc->GetSurface( IID_IDirectDrawSurface4, reinterpret_cast< void ** >( &pSurf ) );
|
||||
|
||||
_ASSERTE( pSurf.p != NULL );
|
||||
_ASSERTE( pSurf->IsLost() == DD_OK );
|
||||
|
||||
// Calculate the metrics
|
||||
#ifdef _DEBUG
|
||||
SIZE sz;
|
||||
pSrc->get_Size( &sz );
|
||||
|
||||
_ASSERTE( prcSrc->left >= 0 && prcSrc->top >= 0 && prcSrc->right <= sz.cx && prcSrc->bottom <= sz.cy );
|
||||
#endif
|
||||
|
||||
ClipParams ¤t = m_clipping.top();
|
||||
|
||||
RECT rcSrcClipped = { prcSrc->left + current.org.x, prcSrc->top + current.org.y,
|
||||
prcSrc->left + current.org.x + ( current.window.right - current.window.left ),
|
||||
prcSrc->top + current.org.y + ( current.window.bottom - current.window.top ) };
|
||||
|
||||
HRESULT hRes = S_OK;
|
||||
|
||||
if ( sourceAlpha < 255) {
|
||||
|
||||
if( cManager::_p->m_eAlphaBlendMode == eAlphaBlendSoftware )
|
||||
{
|
||||
|
||||
// Software alpha blending
|
||||
// It's actually plausible to implement this entirely using D3D and thus get hardware acceleration
|
||||
// Perhaps we should detect device caps and use a suitable method?
|
||||
// This should work on every Decal configuration though (except bank switched video cards, but who has them? :)
|
||||
|
||||
//Lock and calculate metrics for destination
|
||||
|
||||
DDSURFACEDESC2 ddsd;
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
int left = current.window.left;
|
||||
int top = current.window.top;
|
||||
int width = rcSrcClipped.right - rcSrcClipped.left;
|
||||
int height = rcSrcClipped.bottom - rcSrcClipped.top;
|
||||
|
||||
if (FAILED(m_pSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL)))
|
||||
_ASSERTE("Failed to destination lock surface!");
|
||||
|
||||
WORD *dest = (WORD *)ddsd.lpSurface;
|
||||
|
||||
int iPitch = ddsd.lPitch / 2;
|
||||
int initialJump = (top * iPitch) + left;
|
||||
int jump = (iPitch - (width + left)) + left + width;
|
||||
|
||||
//Lock and calculate metrics for source
|
||||
|
||||
DDSURFACEDESC2 srcddsd;
|
||||
memset(&srcddsd, 0, sizeof(srcddsd));
|
||||
srcddsd.dwSize = sizeof(srcddsd);
|
||||
|
||||
if (FAILED(pSurf->Lock(NULL, &srcddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL)))
|
||||
_ASSERTE("Failed to lock source surface!");
|
||||
|
||||
WORD *src = (WORD *)srcddsd.lpSurface;
|
||||
|
||||
//Do it
|
||||
|
||||
int iSrcPitch = srcddsd.lPitch / 2;
|
||||
int alpha = sourceAlpha;
|
||||
int ialpha = 255 - alpha;
|
||||
|
||||
WORD *srcLine = new WORD[width];
|
||||
WORD *destLine = new WORD[width];
|
||||
|
||||
WORD sB, dB, sG, dG, sR, dR;
|
||||
|
||||
dest += initialJump;
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
// We'll read 1 line at a time - 80% of the speed decrease here is reading/writing against the surface
|
||||
|
||||
memcpy((void *)srcLine, src, width * 2);
|
||||
memcpy((void *)destLine, dest, width * 2);
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
// This method is very fast, but assumes a constant 128 alpha
|
||||
// destLine[x] = ( (srcLine[x] & 0xF7DE) >> 1) + ( (destLine[x] & 0xF7DE) >> 1);
|
||||
|
||||
// Basically ((alpha * (src - dest) / MAXALPHA) + dest) for each component
|
||||
// There's some significant room for MMX parrallelism here (~20% more FPS, methinks), but do we want to
|
||||
// be writing ASM?
|
||||
|
||||
sB = srcLine[x] & ddsd.ddpfPixelFormat.dwBBitMask;
|
||||
dB = destLine[x] & ddsd.ddpfPixelFormat.dwBBitMask;
|
||||
sG = srcLine[x] & ddsd.ddpfPixelFormat.dwGBitMask;
|
||||
dG = destLine[x] & ddsd.ddpfPixelFormat.dwGBitMask;
|
||||
sR = srcLine[x] & ddsd.ddpfPixelFormat.dwRBitMask;
|
||||
dR = destLine[x] & ddsd.ddpfPixelFormat.dwRBitMask;
|
||||
|
||||
destLine[x] = ddsd.ddpfPixelFormat.dwBBitMask & ((alpha * (sB - dB) >> 8) + dB) |
|
||||
ddsd.ddpfPixelFormat.dwGBitMask & (((alpha * (sG - dG) >> 8) + dG)) |
|
||||
ddsd.ddpfPixelFormat.dwRBitMask & (((alpha * (sR - dR) >> 8) + dR));
|
||||
|
||||
// The below is eversoslightly faster by assuming RGB 565 surface exposure. Some stupid old cards
|
||||
// blow up however. Fiddle if you like, YMMV. I'm sticking with something that works :)
|
||||
|
||||
//sB = srcLine[x] & 0x1f;
|
||||
//dB = destLine[x] & 0x1f;
|
||||
//sG = (srcLine[x] >> 5) & 0x3f;
|
||||
//dG = (destLine[x] >> 5) & 0x3f;
|
||||
//sR = (srcLine[x] >> 11) & 0x1f;
|
||||
//dR = (destLine[x] >> 11) & 0x1f;
|
||||
|
||||
//destLine[x] = ((alpha * (sB - dB) >> 8) + dB) |
|
||||
// (((alpha * (sG - dG) >> 8) + dG) << 5) |
|
||||
// (((alpha * (sR - dR) >> 8) + dR) << 11);*/
|
||||
}
|
||||
|
||||
memcpy(dest, destLine, width * 2);
|
||||
|
||||
src += iSrcPitch;
|
||||
dest += jump;
|
||||
}
|
||||
|
||||
//Release
|
||||
|
||||
delete srcLine;
|
||||
delete destLine;
|
||||
|
||||
if (FAILED(pSurf->Unlock(NULL)))
|
||||
_ASSERTE("Failed to unlock source surface!");
|
||||
|
||||
if (FAILED(m_pSurface->Unlock(NULL)))
|
||||
_ASSERTE("Failed to unlock destination surface!");
|
||||
}
|
||||
else if ((cManager::_p->m_eAlphaBlendMode == eAlphaBlendGDIPlus) && (AlphaBlendF!=NULL))
|
||||
{
|
||||
HDC hdcd;
|
||||
HDC hdcs;
|
||||
GetDC(&hdcd);
|
||||
pSrc->GetDC(&hdcs);
|
||||
|
||||
hRes = AlphaBlendF(hdcd, current.org.x, current.org.y, rcSrcClipped.right-rcSrcClipped.left, rcSrcClipped.bottom-rcSrcClipped.top, hdcs, current.org.x, current.org.y, rcSrcClipped.right-rcSrcClipped.left, rcSrcClipped.bottom-rcSrcClipped.top, m_bf);
|
||||
|
||||
pSrc->ReleaseDC();
|
||||
ReleaseDC();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hRes = m_pSurface->BltFast( current.window.left, current.window.top, pSurf, &rcSrcClipped, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
|
||||
}
|
||||
|
||||
|
||||
/* if(!SUCCEEDED(hRes))
|
||||
{
|
||||
POINT pt = { 0, 0 };
|
||||
ClientToScreen(cManager::_p->m_hMain, &pt);
|
||||
|
||||
/*if((pt.x==0) || (pt.y==0))
|
||||
MessageBox(0,"asd","asd",0);*/
|
||||
//RECT rcd = {pt.x, pt.y, rcSrcClipped.right-rcSrcClipped.left, rcSrcClipped.bottom-rcSrcClipped.top};
|
||||
//m_pSurface->Blt(&rcd,pSurf,&rcSrcClipped,DDBLT_WAIT,NULL);
|
||||
// RECT rcd = {0, 0, 640, 480};
|
||||
|
||||
/* rcSrcClipped.left+=current.window.left+pt.x;
|
||||
rcSrcClipped.right+=current.window.left+pt.x;
|
||||
rcSrcClipped.top+=current.window.top+pt.y+28;
|
||||
rcSrcClipped.bottom+=current.window.top+pt.y+28;
|
||||
/*
|
||||
DDBLTFX ddbltfx;
|
||||
|
||||
ddbltfx.dwSize=sizeof(ddbltfx);
|
||||
ddbltfx.dwFillColor=5;
|
||||
|
||||
m_pSurface->Blt(&rcSrcClipped,NULL,NULL,DDBLT_COLORFILL,&ddbltfx);*/
|
||||
|
||||
/* CComPtr< ICanvas > pCan;
|
||||
cManager::_p->GetPrimarySurface(&pCan);
|
||||
CComPtr< IDirectDrawSurface4 > pDDS4;
|
||||
pCan->GetSurface( IID_IDirectDrawSurface4, reinterpret_cast< void ** >( &pDDS4 ) );
|
||||
|
||||
// if(m_pSurface.p==pDDS4.p)
|
||||
|
||||
|
||||
if(cManager::_p->m_lpSurface!=NULL)
|
||||
{
|
||||
MessageBeep(0);
|
||||
DDSURFACEDESC2 ddesc;
|
||||
ddesc.dwSize=sizeof(DDSURFACEDESC2);
|
||||
|
||||
pSurf->Lock(&rcSrcClipped, &ddesc, DDLOCK_SURFACEMEMORYPTR , NULL);
|
||||
|
||||
//m_pSurface->Blt(&rcSrcClipped,pSurf,NULL,DDBLT_KEYSRC | DDBLT_WAIT ,NULL);
|
||||
memcpy(cManager::_p->m_lpSurface, ddesc.lpSurface, 1000);
|
||||
|
||||
pSurf->Unlock(&rcSrcClipped);
|
||||
|
||||
SetEvent(cManager::_p->m_hDrawSync);
|
||||
|
||||
}
|
||||
|
||||
//m_pSurface->Blt(&rcSrcClipped,pSurf,NULL,DDBLT_KEYSRC | DDBLT_WAIT ,NULL);
|
||||
|
||||
|
||||
/* RECT rc;
|
||||
::GetWindowRect( cManager::_p->m_hMain, &rc );*/
|
||||
/*
|
||||
HDC hdcd;
|
||||
HDC hdcs;
|
||||
m_pSurface->GetDC(&hdcd);
|
||||
pSurf->GetDC(&hdcs);
|
||||
BitBlt(hdcd, pt.x+current.window.left, pt.y+28+current.window.top, 332, current.window.bottom-current.window.top, hdcs, rcSrcClipped.left, rcSrcClipped.top, SRCCOPY);
|
||||
pSurf->ReleaseDC(hdcs);
|
||||
m_pSurface->ReleaseDC(hdcd);*/
|
||||
|
||||
/* hRes=0;
|
||||
}
|
||||
|
||||
/*if(!SUCCEEDED(hRes))
|
||||
SetEvent(cManager::_p->m_hDrawSync);*/
|
||||
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
}
|
||||
|
||||
PopClipRect();
|
||||
|
||||
_ASSERTMEM( _CrtCheckMemory() );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::HitTest(LPPOINT ppt, VARIANT_BOOL *pbHit)
|
||||
{
|
||||
_ASSERTE( ppt != NULL );
|
||||
_ASSERTE( pbHit != NULL );
|
||||
|
||||
// Assuming we're in screen coords
|
||||
ClipParams &clip = m_clipping.top();
|
||||
|
||||
if( ppt->x >= clip.window.left && ppt->y >= clip.window.top &&
|
||||
ppt->x <= clip.window.right && ppt->y <= clip.window.bottom )
|
||||
{
|
||||
*pbHit = VARIANT_TRUE;
|
||||
}
|
||||
else
|
||||
*pbHit = VARIANT_FALSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::ToClient(LPPOINT pt)
|
||||
{
|
||||
_ASSERTE( pt != NULL );
|
||||
|
||||
ClipParams &clip = m_clipping.top();
|
||||
pt->x -= clip.window.left - clip.org.x;
|
||||
pt->y -= clip.window.top - clip.org.y;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::ToScreen(LPPOINT ppt)
|
||||
{
|
||||
_ASSERTE( ppt != NULL );
|
||||
|
||||
ClipParams &clip = m_clipping.top();
|
||||
ppt->x += clip.window.left - clip.org.x;
|
||||
ppt->y += clip.window.top - clip.org.y;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::OffsetOrg(LPPOINT ppt, VARIANT_BOOL *pbVisible)
|
||||
{
|
||||
_ASSERTE( ppt != NULL );
|
||||
_ASSERTE( pbVisible != NULL );
|
||||
_ASSERTE( m_clipping.size() != 1 );
|
||||
|
||||
ClipParams &clip = m_clipping.top();
|
||||
clip.org.x += ppt->x;
|
||||
clip.org.y += ppt->y;
|
||||
|
||||
*pbVisible = clip.visible;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::SetClipRect(LPRECT prc, VARIANT_BOOL *pbVisible)
|
||||
{
|
||||
_ASSERTE( prc != NULL );
|
||||
_ASSERTE( prc->right >= prc->left && prc->bottom >= prc->top );
|
||||
_ASSERTE( pbVisible != NULL );
|
||||
_ASSERTE( m_clipping.size() != 1 );
|
||||
|
||||
ClipParams ¤t = m_clipping.top();
|
||||
|
||||
int nChildLeft = prc->left + current.window.left - current.org.x,
|
||||
nChildTop = prc->top + current.window.top - current.org.y,
|
||||
nChildWidth = prc->right - prc->left,
|
||||
nChildHeight = prc->bottom - prc->top;
|
||||
|
||||
ClipParams p = {
|
||||
{ nChildLeft, nChildTop, nChildLeft + nChildWidth, nChildTop + nChildHeight },
|
||||
{ 0, 0 },
|
||||
VARIANT_TRUE };
|
||||
|
||||
// Clip the four sides of the rectangle
|
||||
if( p.window.left < current.window.left )
|
||||
{
|
||||
// Clip left edge
|
||||
p.org.x += current.window.left - p.window.left;
|
||||
p.window.left = current.window.left;
|
||||
}
|
||||
|
||||
if( p.window.top < current.window.top )
|
||||
{
|
||||
// Clip top edge
|
||||
p.org.y += current.window.top - p.window.top;
|
||||
p.window.top = current.window.top;
|
||||
}
|
||||
|
||||
if( p.window.right > current.window.right )
|
||||
// Clip right edge
|
||||
p.window.right = current.window.right;
|
||||
|
||||
if( p.window.bottom > current.window.bottom )
|
||||
// Clip bottom edge
|
||||
p.window.bottom = current.window.bottom;
|
||||
|
||||
// Check for clipping out of existance
|
||||
if( p.window.left >= p.window.right || p.window.top >= p.window.bottom )
|
||||
// This rectangle is no longer visible
|
||||
p.visible = VARIANT_FALSE;
|
||||
|
||||
// Return the remainder of the rectangle
|
||||
*pbVisible = p.visible;
|
||||
|
||||
m_clipping.top() = p;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::put_Alpha(long Alpha)
|
||||
{
|
||||
m_bf.SourceConstantAlpha = sourceAlpha = Alpha;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// processMask - Support function for DownMixRGB
|
||||
|
||||
void cCanvas::processMask(WORD bitMask, WORD *loBit, WORD *bitCount) {
|
||||
_ASSERTE(loBit);
|
||||
_ASSERTE(bitCount);
|
||||
|
||||
WORD mask = 1;
|
||||
|
||||
for (*loBit = 0; *loBit < 16; (*loBit)++) {
|
||||
if (bitMask & mask)
|
||||
break;
|
||||
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
for (*bitCount = 1; *bitCount < 32; (*bitCount)++) {
|
||||
mask <<= 1;
|
||||
|
||||
if (!(bitMask & mask))
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// DownMixRGB - Returns a 16 bit RGB value suitable for this canvas from a standard R, G, B set
|
||||
|
||||
STDMETHODIMP cCanvas::DownMixRGB(WORD wRed, WORD wGreen, WORD wBlue, WORD *wDMRGB) {
|
||||
_ASSERTE(wDMRGB);
|
||||
|
||||
if (wRBitCount == 0) {
|
||||
// We've never obtained surface information before for this canvas
|
||||
DDSURFACEDESC2 desc;
|
||||
desc.dwSize = sizeof( DDSURFACEDESC2 );
|
||||
|
||||
if (FAILED(m_pSurface->GetSurfaceDesc(&desc)))
|
||||
return S_FALSE;
|
||||
|
||||
processMask(desc.ddpfPixelFormat.dwRBitMask, &wRLoBit, &wRBitCount);
|
||||
processMask(desc.ddpfPixelFormat.dwGBitMask, &wGLoBit, &wGBitCount);
|
||||
processMask(desc.ddpfPixelFormat.dwBBitMask, &wBLoBit, &wBBitCount);
|
||||
}
|
||||
|
||||
// Transparent color handling
|
||||
if (wRed == 0 && wGreen == 255 && wBlue == 255) {
|
||||
// We are a transparent colour - The downmix would've destroyed it
|
||||
*wDMRGB = 0x07FF;
|
||||
} else {
|
||||
// Safe for a normal mix
|
||||
*wDMRGB = ((wRed * (1 << wRBitCount)) / 256) << wRLoBit |
|
||||
((wGreen * (1 << wGBitCount)) / 256) << wGLoBit |
|
||||
((wBlue * (1 << wBBitCount)) / 256) << wBLoBit;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::GetDCLong(long *DC)
|
||||
{
|
||||
HDC pdc;
|
||||
GetDC(&pdc);
|
||||
*DC = reinterpret_cast< long >( pdc );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::SetTransparentColor(long TransColor)
|
||||
{
|
||||
unsigned short wDownmix;
|
||||
|
||||
DownMixRGB((BYTE)TransColor, (BYTE)(TransColor >> 8), (BYTE)(TransColor >> 16), &wDownmix );
|
||||
|
||||
_DDCOLORKEY colorkey;
|
||||
|
||||
colorkey.dwColorSpaceHighValue = wDownmix;
|
||||
colorkey.dwColorSpaceLowValue = wDownmix;
|
||||
|
||||
m_pSurface->SetColorKey( DDCKEY_SRCBLT, &colorkey );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cCanvas::StretchBlt(LPRECT prcSrc, ICanvas *pSrc, LPRECT prcDest)
|
||||
{
|
||||
_ASSERTE( pSrc != NULL );
|
||||
_ASSERTE( prcSrc != NULL );
|
||||
_ASSERTE( prcSrc->right > prcSrc->left && prcSrc->bottom > prcSrc->top );
|
||||
//_ASSERTE( pptDest != NULL );
|
||||
|
||||
testSurface();
|
||||
|
||||
//RECT rc = { pptDest->x, pptDest->y, pptDest->x + ( prcSrc->right - prcSrc->left ), pptDest->y + ( prcSrc->bottom - prcSrc->top ) };
|
||||
|
||||
// Ok, first, make up the clip rect
|
||||
RECT rc = { prcDest->left, prcDest->top, prcDest->right, prcDest->bottom };
|
||||
|
||||
VARIANT_BOOL bVisible = TRUE;
|
||||
|
||||
PushClipRect( &rc, &bVisible );
|
||||
|
||||
//if( bVisible )
|
||||
{
|
||||
CComPtr< IDirectDrawSurface4 > pSurf;
|
||||
pSrc->GetSurface( IID_IDirectDrawSurface4, reinterpret_cast< void ** >( &pSurf ) );
|
||||
|
||||
_ASSERTE( pSurf.p != NULL );
|
||||
_ASSERTE( pSurf->IsLost() == DD_OK );
|
||||
|
||||
// Calculate the metrics
|
||||
#ifdef _DEBUG
|
||||
SIZE sz;
|
||||
pSrc->get_Size( &sz );
|
||||
|
||||
_ASSERTE( prcSrc->left >= 0 && prcSrc->top >= 0 && prcSrc->right <= sz.cx && prcSrc->bottom <= sz.cy );
|
||||
#endif
|
||||
|
||||
ClipParams ¤t = m_clipping.top();
|
||||
|
||||
RECT rcSrcClipped = {
|
||||
prcSrc->left,
|
||||
prcSrc->top,
|
||||
prcSrc->right,// + ( current.window.right - current.window.left ),
|
||||
prcSrc->bottom// + ( current.window.bottom - current.window.top )
|
||||
};
|
||||
|
||||
RECT rcDestClipped = {
|
||||
prcDest->left + current.org.x + current.window.left,
|
||||
prcDest->top + current.org.y + current.window.top,
|
||||
prcDest->left + prcDest->right + current.org.x,
|
||||
prcDest->top + prcDest->bottom + current.org.y
|
||||
};
|
||||
|
||||
HRESULT hRes = m_pSurface->Blt( &rcDestClipped, pSurf, &rcSrcClipped, DDBLT_KEYSRC | DDBLT_WAIT, NULL );
|
||||
|
||||
_ASSERTE( SUCCEEDED( hRes ) );
|
||||
}
|
||||
|
||||
PopClipRect();
|
||||
|
||||
_ASSERTMEM( _CrtCheckMemory() );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue