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
284
Native/Inject/FontCache.cpp
Normal file
284
Native/Inject/FontCache.cpp
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
// FontCache.cpp : Implementation of cFontCache
|
||||
#include "stdafx.h"
|
||||
#include "Inject.h"
|
||||
#include "FontCache.h"
|
||||
|
||||
#include "Manager.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// cFontCache
|
||||
|
||||
cFontCache::~cFontCache()
|
||||
{
|
||||
cManager::_p->removeFont( this );
|
||||
}
|
||||
|
||||
#define BUFFER_WIDTHCHARS 32
|
||||
#define BUFFER_HEIGHTCHARS 8
|
||||
#define BUFFER_CHARCOUNT (BUFFER_WIDTHCHARS * BUFFER_HEIGHTCHARS)
|
||||
|
||||
bool cFontCache::checkBuffer()
|
||||
{
|
||||
if( m_pBuffer.p )
|
||||
{
|
||||
VARIANT_BOOL bWasLost;
|
||||
m_pBuffer->get_WasLost( &bWasLost );
|
||||
if( bWasLost )
|
||||
m_pBuffer.Release();
|
||||
}
|
||||
|
||||
if( m_pBuffer.p )
|
||||
// The character buff is intact
|
||||
return true;
|
||||
|
||||
// Get a dummy DC from the primary surface
|
||||
CComPtr< ICanvas > pSurf;
|
||||
|
||||
if( FAILED(cManager::_p->GetPrimarySurface( &pSurf )) )
|
||||
return false;
|
||||
|
||||
// Madar: This can happen if you set an edit-text during plugin initialization.
|
||||
if (!pSurf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HDC hdc;
|
||||
pSurf->GetDC( &hdc );
|
||||
|
||||
// Drakier: reset error, try to create font, then check for error.
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
HFONT hfnt = ::CreateFontIndirect( &m_lf );
|
||||
if (GetLastError() != ERROR_SUCCESS)
|
||||
{
|
||||
_ASSERTE(GetLastError());
|
||||
// Drakier: try arial instead
|
||||
strcpy(m_lf.lfFaceName, "Arial");
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
HFONT hfnt = ::CreateFontIndirect( &m_lf );
|
||||
if (GetLastError() != ERROR_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
|
||||
HFONT hfntOld = reinterpret_cast< HFONT >( ::SelectObject( hdc, hfnt ) );
|
||||
|
||||
|
||||
TEXTMETRIC tm;
|
||||
::GetTextMetrics( hdc, &tm );
|
||||
|
||||
m_szCharCell.cy = tm.tmHeight;
|
||||
m_szCharCell.cx = tm.tmMaxCharWidth;
|
||||
|
||||
// Create the buffer
|
||||
SIZE szBuffer = { m_szCharCell.cx * BUFFER_WIDTHCHARS, m_szCharCell.cy * BUFFER_HEIGHTCHARS };
|
||||
cManager::_p->CreateCanvas( &szBuffer, &m_pBuffer );
|
||||
|
||||
INT widths[ BUFFER_CHARCOUNT ];
|
||||
BOOL b = ::GetCharWidth( hdc, 0, ( BUFFER_CHARCOUNT - 1 ), widths );
|
||||
_ASSERTE( b );
|
||||
DWORD dwError = ::GetLastError();
|
||||
|
||||
for( short nChar = 0; nChar < BUFFER_CHARCOUNT; ++ nChar )
|
||||
{
|
||||
// TODO: Render the chars
|
||||
// Figure out the character cell size
|
||||
m_nWidths[ nChar ].m_nWidth = widths[ nChar ];
|
||||
}
|
||||
|
||||
// TODO: Render all the chars into the buffer
|
||||
|
||||
::SelectObject( hdc, hfntOld );
|
||||
::DeleteObject( hfnt );
|
||||
|
||||
pSurf->ReleaseDC();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
STDMETHODIMP cFontCache::DrawText( LPPOINT ppt, BSTR strText, long clr, ICanvas *pCanvas )
|
||||
{
|
||||
/* _ASSERTE( ppt != NULL );
|
||||
_ASSERTE( strText != NULL );
|
||||
_ASSERTE( pCanvas != NULL );
|
||||
|
||||
if( !checkBuffer() )
|
||||
return E_FAIL;
|
||||
|
||||
USES_CONVERSION;
|
||||
|
||||
LPCTSTR szText = OLE2T( strText );
|
||||
|
||||
// TODO: Draw this a lot faster from a cached bitmap value
|
||||
|
||||
HDC hdc;
|
||||
pCanvas->GetDC( &hdc );
|
||||
|
||||
// Draw the text
|
||||
HFONT hfnt = ::CreateFontIndirect( &m_lf ),
|
||||
hfntOld = reinterpret_cast< HFONT >( ::SelectObject( hdc, hfnt ) );
|
||||
|
||||
::SetBkMode( hdc, TRANSPARENT );
|
||||
::SetTextColor( hdc, clr );
|
||||
::SetTextAlign( hdc, TA_TOP | TA_LEFT );
|
||||
|
||||
LPCSTR szAnsi = OLE2A( strText );
|
||||
int cbLength = ::strlen( szAnsi );
|
||||
|
||||
INT *pDeltas = new INT[ cbLength ];
|
||||
|
||||
// Fill in the character deltas
|
||||
const char *i_src = szAnsi;
|
||||
INT *i_end_deltas = pDeltas + cbLength;
|
||||
for( INT *i_delta = pDeltas; i_delta != i_end_deltas; ++ i_delta, ++ i_src )
|
||||
*i_delta = m_nWidths[ *i_src ].m_nWidth;
|
||||
|
||||
if( m_bFontSmoothing )
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING, FALSE, NULL, 0 );
|
||||
|
||||
::ExtTextOut( hdc, ppt->x, ppt->y, 0, NULL, szAnsi, cbLength, pDeltas );
|
||||
|
||||
if( m_bFontSmoothing )
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING, TRUE, NULL, 0 );
|
||||
|
||||
delete[] pDeltas;
|
||||
|
||||
::SelectObject( hdc, hfntOld );
|
||||
::DeleteObject( hfnt );
|
||||
|
||||
pCanvas->ReleaseDC();
|
||||
|
||||
return S_OK;*/
|
||||
return DrawTextEx( ppt, strText, clr, 0, 0, pCanvas );
|
||||
}
|
||||
|
||||
STDMETHODIMP cFontCache::DrawTextEx( LPPOINT ppt, BSTR strText, long clr1, long clr2, long lFlags, ICanvas *pCanvas )
|
||||
{
|
||||
_ASSERTE( ppt != NULL );
|
||||
_ASSERTE( strText != NULL );
|
||||
_ASSERTE( pCanvas != NULL );
|
||||
|
||||
if( !checkBuffer() )
|
||||
return E_FAIL;
|
||||
|
||||
USES_CONVERSION;
|
||||
|
||||
LPCTSTR szText = OLE2T( strText );
|
||||
|
||||
// TODO: Draw this a lot faster from a cached bitmap value
|
||||
|
||||
HDC hdc;
|
||||
pCanvas->GetDC( &hdc );
|
||||
|
||||
// Draw the text
|
||||
// Drakier: reset error, try to create font, then check for error.
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
HFONT hfnt = ::CreateFontIndirect( &m_lf );
|
||||
if (GetLastError() != ERROR_SUCCESS)
|
||||
{
|
||||
_ASSERTE(GetLastError());
|
||||
// Drakier: try arial instead
|
||||
strcpy(m_lf.lfFaceName, "Arial");
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
HFONT hfnt = ::CreateFontIndirect( &m_lf );
|
||||
if (GetLastError() != ERROR_SUCCESS)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HFONT hfntOld = reinterpret_cast< HFONT >( ::SelectObject( hdc, hfnt ) );
|
||||
|
||||
::SetBkMode( hdc, TRANSPARENT );
|
||||
::SetTextAlign( hdc, TA_TOP | TA_LEFT );
|
||||
|
||||
LPCSTR szAnsi = OLE2A( strText );
|
||||
int cbLength = ::strlen( szAnsi );
|
||||
|
||||
INT *pDeltas = new INT[ cbLength ];
|
||||
|
||||
// Fill in the character deltas
|
||||
const char *i_src = szAnsi;
|
||||
INT *i_end_deltas = pDeltas + cbLength;
|
||||
for( INT *i_delta = pDeltas; i_delta != i_end_deltas; ++ i_delta, ++ i_src )
|
||||
*i_delta = m_nWidths[ *i_src ].m_nWidth;
|
||||
|
||||
if( !(lFlags & eAA) )
|
||||
if( m_bFontSmoothing )
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING, FALSE, NULL, 0 );
|
||||
|
||||
if( lFlags & eOutlined )
|
||||
{
|
||||
::SetTextColor( hdc, clr2 );
|
||||
|
||||
::ExtTextOut( hdc, ppt->x - 1, ppt->y - 1, 0, NULL, szAnsi, cbLength, pDeltas );
|
||||
::ExtTextOut( hdc, ppt->x - 1, ppt->y + 1, 0, NULL, szAnsi, cbLength, pDeltas );
|
||||
::ExtTextOut( hdc, ppt->x + 1, ppt->y - 1, 0, NULL, szAnsi, cbLength, pDeltas );
|
||||
::ExtTextOut( hdc, ppt->x + 1, ppt->y + 1, 0, NULL, szAnsi, cbLength, pDeltas );
|
||||
}
|
||||
|
||||
::SetTextColor( hdc, clr1 );
|
||||
::ExtTextOut( hdc, ppt->x, ppt->y, 0, NULL, szAnsi, cbLength, pDeltas );
|
||||
|
||||
if( !(lFlags & eAA) )
|
||||
if( m_bFontSmoothing )
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING, TRUE, NULL, 0 );
|
||||
|
||||
delete[] pDeltas;
|
||||
|
||||
::SelectObject( hdc, hfntOld );
|
||||
::DeleteObject( hfnt );
|
||||
|
||||
pCanvas->ReleaseDC();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cFontCache::MeasureText( BSTR strText, LPSIZE pszExt )
|
||||
{
|
||||
_ASSERTE( strText != NULL );
|
||||
_ASSERTE( pszExt != NULL );
|
||||
|
||||
if( !checkBuffer() )
|
||||
return E_FAIL;
|
||||
|
||||
USES_CONVERSION;
|
||||
|
||||
LPCSTR szText = OLE2T( strText ),
|
||||
i_end_text = szText + strlen( szText );
|
||||
|
||||
pszExt->cy = m_szCharCell.cy;
|
||||
pszExt->cx = 0;
|
||||
|
||||
for( LPCSTR i_text = szText; i_text != i_end_text; ++ i_text )
|
||||
pszExt->cx += m_nWidths[ *i_text ].m_nWidth;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP cFontCache::HitTest(BSTR szText, long nPos, long *nIndex)
|
||||
{
|
||||
_ASSERTE( szText != NULL );
|
||||
_ASSERTE( nIndex != NULL );
|
||||
|
||||
if( !checkBuffer() )
|
||||
return E_FAIL;
|
||||
|
||||
USES_CONVERSION;
|
||||
|
||||
LPCSTR szAText = OLE2T( szText ),
|
||||
i_end_text = szAText + strlen( szAText );
|
||||
|
||||
for( LPCSTR i_text = szAText; i_text != i_end_text; ++ i_text )
|
||||
{
|
||||
short nWidth = m_nWidths[ *i_text ].m_nWidth;
|
||||
if( nPos < nWidth )
|
||||
{
|
||||
*nIndex = ( i_text - szAText );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
nPos -= nWidth;
|
||||
}
|
||||
|
||||
*nIndex = -1;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue