DragonNest/Common/EternityEngine/D3DDevice9/EtSystemFont.cpp

195 lines
6.2 KiB
C++
Raw Permalink Normal View History

#include "StdAfx.h"
#include "EtSystemFont.h"
#include "EtTexture.h"
#include "EtType.h"
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
CEtSystemFont::CEtSystemFont(void)
{
memset(m_nCharHeight, 0, sizeof(m_nCharHeight));
memset(m_nCharWidth, 0, sizeof(m_nCharWidth));
}
CEtSystemFont::~CEtSystemFont(void)
{
SAFE_RELEASE_SPTR( m_hTexture );
}
void CEtSystemFont::Initialize( int nFontHeight, const char *pFonrName )
{
HFONT hFont;
HDC hDC;
HBITMAP hBM;
HFONT hOldFont;
HBITMAP hOldBM;
hDC = ::CreateCompatibleDC( NULL );
hFont = CreateFont (nFontHeight , 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
FF_DONTCARE | DEFAULT_PITCH, pFonrName);
hBM = ::CreateBitmap(16, 16, 1, 1, NULL);
hOldFont = (HFONT)::SelectObject( hDC, hFont );
int nCharMaxWidth = 0;
int nCharMaxHeight = 0;
for( int ch = 0; ch < 256; ch++) {
char szText[2] = {ch, '\0' };
SIZE size;
::GetTextExtentPoint(hDC, szText, 1, (LPSIZE)&size);
nCharMaxWidth = EtMax( size.cx , nCharMaxWidth );
nCharMaxHeight = EtMax( size.cy , nCharMaxHeight );
m_nCharWidth[ ch ] = size.cx;
m_nCharHeight[ ch ] = size.cy;
}
hOldBM = (HBITMAP)::SelectObject( hDC, hBM );
nCharMaxWidth = CEtTexture::CalcTextureSize( nCharMaxWidth );
nCharMaxHeight = CEtTexture::CalcTextureSize( nCharMaxHeight );
ASSERT( nCharMaxWidth == 16 && nCharMaxHeight == 16 );
m_hTexture = CEtTexture::CreateNormalTexture( nCharMaxWidth * 16, nCharMaxHeight * 16, FMT_A8R8G8B8, USAGE_DEFAULT, POOL_MANAGED );
int nStride = 0;
BYTE *pPtr = (BYTE*)m_hTexture->Lock( nStride, true);
for( int y = 0; y < nCharMaxHeight* 16; y++)
for( int x = 0; x < nCharMaxHeight* 16; x++)
{
pPtr[ nStride * y + x * 4 + 0 ] = 255;
pPtr[ nStride * y + x * 4 + 1 ] = 255;
pPtr[ nStride * y + x * 4 + 2 ] = 255;
pPtr[ nStride * y + x * 4 + 3 ] = 0;
}
::SetBkColor(hDC, RGB(0,0,0));
::SetTextColor(hDC, RGB(255,255,255));
::SetBkMode(hDC, OPAQUE);
int nTotalBytes = 16 * 16 / 8;
BYTE *pBits = new BYTE[ nTotalBytes ];
for( int ch= 0; ch < 256; ch++) {
char szText[2] = {ch, '\0' };
::TextOut( hDC, 0, 0, szText, 1 );
memset(pBits, 0, nTotalBytes );
::GetBitmapBits(hBM, nTotalBytes, pBits );
for( int y = 0; y < m_nCharHeight[ ch ]; y++)
{
for( int x = 0; x < 2; x++)
{
int addr = (16 * 16) * (y+(ch/16)*16) + ((x*8)+(ch%16)*16);
for( int bit = 0; bit < 8; bit++)
{
if( bit + x * 8 >= m_nCharWidth[ ch ] )
break;
if( (pBits[x + y * 2 ] & (1<<(7 - bit) )) != 0 ) {
pPtr[ (addr+bit) * 4 + 3 ] = 0xFF;
}
}
}
}
}
SAFE_DELETEA( pBits );
m_hTexture->Unlock();
::SelectObject( hDC, hOldFont );
::SelectObject( hDC, hOldBM );
::DeleteDC( hDC );
::DeleteObject( hBM );
::DeleteObject( hFont );
}
void CEtSystemFont::DrawText( LPCSTR pString, LPRECT pRect, D3DCOLOR Color )
{
int nLength = (int)strlen( pString );
if( nLength <= 0 ) return;
if( !m_hTexture || !m_hTexture->GetTexturePtr() ) return;
GetEtDevice()->SetFVF( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 );
GetEtDevice()->SetPixelShader( NULL );
GetEtDevice()->SetVertexShader( NULL );
DWORD dwWidth = GetEtDevice()->Width();
DWORD dwHeight = GetEtDevice()->Height();
SUICoord ScreenCoord;
ScreenCoord.fX = (float)pRect->left - 0.5f ;
ScreenCoord.fY = (float)pRect->top - 0.5f;
float fZValue = 0.f;
if( (int)m_Indices.size() < nLength * 6 )
m_Indices.resize( nLength * 6 );
if( (int)m_Vertices.size() < nLength * 4)
m_Vertices.resize( nLength * 4);
for( int i = 0; i < nLength; i++) {
BYTE ch = pString[ i ];
ScreenCoord.fWidth = 16.0f;
ScreenCoord.fHeight = 16.0f;
m_Vertices[ i * 4 + 0 ].Position = EtVector4( ScreenCoord.fX , ScreenCoord.fY, fZValue, 1.0f );
m_Vertices[ i * 4 + 1 ].Position = EtVector4( (ScreenCoord.fX+ScreenCoord.fWidth), ScreenCoord.fY , fZValue, 1.0f );
m_Vertices[ i * 4 + 2 ].Position = EtVector4( (ScreenCoord.fX+ScreenCoord.fWidth) , (ScreenCoord.fY+ScreenCoord.fHeight), fZValue, 1.0f );
m_Vertices[ i * 4 + 3 ].Position = EtVector4( ScreenCoord.fX , (ScreenCoord.fY+ScreenCoord.fHeight) , fZValue, 1.0f );
SUICoord UVCoord;
UVCoord.fX = (ch % 16) / 16.0f;
UVCoord.fY = (ch / 16) / 16.0f;
UVCoord.fWidth = 1 / 16.0f;
UVCoord.fHeight = 1 / 16.0f;
m_Vertices[ i * 4 + 0 ].TexCoordinate = EtVector2( UVCoord.fX, UVCoord.fY );
m_Vertices[ i * 4 + 1 ].TexCoordinate = EtVector2( UVCoord.fX+UVCoord.fWidth, UVCoord.fY );
m_Vertices[ i * 4 + 2 ].TexCoordinate = EtVector2( UVCoord.fX+UVCoord.fWidth, UVCoord.fY + UVCoord.fHeight );
m_Vertices[ i * 4 + 3 ].TexCoordinate = EtVector2( UVCoord.fX, UVCoord.fY + UVCoord.fHeight );
ScreenCoord.fX += (m_nCharWidth[ch]);
m_Vertices[ i * 4 + 0 ].Color = Color;
m_Vertices[ i * 4 + 1 ].Color = Color;
m_Vertices[ i * 4 + 2 ].Color = Color;
m_Vertices[ i * 4 + 3 ].Color = Color;
m_Indices[ 6 * i + 0 ] = 0 + i * 4;
m_Indices[ 6 * i + 1 ] = 1 + i * 4;
m_Indices[ 6 * i + 2 ] = 3 + i * 4;
m_Indices[ 6 * i + 3 ] = 1 + i * 4;
m_Indices[ 6 * i + 4 ] = 3 + i * 4;
m_Indices[ 6 * i + 5 ] = 2 + i * 4;
}
GetEtDevice()->SetTexture( 0, m_hTexture->GetTexturePtr() );
bool bAlphaBlend = GetEtDevice()->EnableAlphaBlend( true );
GetEtDevice()->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
GetEtDevice()->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
GetEtDevice()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
GetEtDevice()->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
GetEtDevice()->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
GetEtDevice()->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
GetEtDevice()->SetRenderState( D3DRS_LIGHTING, FALSE );
GetEtDevice()->DrawIndexedPrimitiveUP( PT_TRIANGLELIST, 0, 4 * nLength, 2 * nLength, &m_Indices.front(), FMT_INDEX16, &m_Vertices.front(), sizeof(STextureDiffuseVertex2D) );
GetEtDevice()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
GetEtDevice()->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
GetEtDevice()->EnableAlphaBlend( bAlphaBlend );
}
CEtSystemFont* CEtSystemFont::Create( int nHeight, const char *pFontName )
{
CEtSystemFont *pResultFont = new CEtSystemFont;
pResultFont->Initialize( nHeight, pFontName );
return pResultFont;
}