📄 font.cpp
字号:
#include "HEADERS.H"
#include "FONT.H"
USING NAMESPACE CGE::FONT;
#define MAX_NUM_VERTICES 50*6
//////////////////////////////////////////////////////////////
EnFont::EnFont()
{
this->m_dyEnFontCache = NULL;
this->m_dyEnFontVB = NULL;
this->m_dyEnFontDevice = NULL;
this->m_dwTexHeight = 0;
this->m_fTextScale = 1.0f;
this->m_dwTexWidth = 0;
}
EnFont::~EnFont()
{
}
VOID EnFont::Text2DOut(const TCHAR *strText, LONG sx, LONG sy, DWORD rgbFontColour)
{
if( m_dyEnFontDevice == NULL )
return;
FLOAT fStartX = sx;
CARD2DVERTEX* PV = NULL;
DWORD dwNumTriangles = 0;
m_dyEnFontVB->Lock( 0, 0, (BYTE**)&PV, D3DLOCK_DISCARD );
while( *strText )
{
TCHAR c = *strText++;
if( c == _T('\n') )
{
sx = fStartX;
sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
}
if( c < _T(' ') )
continue;
FLOAT tx1 = m_fTexCoords[c-32][0];
FLOAT ty1 = m_fTexCoords[c-32][1];
FLOAT tx2 = m_fTexCoords[c-32][2];
FLOAT ty2 = m_fTexCoords[c-32][3];
FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale;
FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale;
if( c != _T(' ') )
{
*PV++ = CARD2DVERTEX( D3DXVECTOR3(sx+0-0.5f,sy+h-0.5f,0.9f),1.0f, rgbFontColour, tx1, ty2 );
*PV++ = CARD2DVERTEX( D3DXVECTOR3(sx+0-0.5f,sy+0-0.5f,0.9f),1.0f, rgbFontColour, tx1, ty1 );
*PV++ = CARD2DVERTEX( D3DXVECTOR3(sx+w-0.5f,sy+h-0.5f,0.9f),1.0f, rgbFontColour, tx2, ty2 );
*PV++ = CARD2DVERTEX( D3DXVECTOR3(sx+w-0.5f,sy+0-0.5f,0.9f),1.0f, rgbFontColour, tx2, ty1 );
*PV++ = CARD2DVERTEX( D3DXVECTOR3(sx+w-0.5f,sy+h-0.5f,0.9f),1.0f, rgbFontColour, tx2, ty2 );
*PV++ = CARD2DVERTEX( D3DXVECTOR3(sx+0-0.5f,sy+0-0.5f,0.9f),1.0f, rgbFontColour, tx1, ty1 );
dwNumTriangles += 2;
if( (dwNumTriangles * 3) > (MAX_NUM_VERTICES - 6) )
{
m_dyEnFontVB->Unlock();
m_dyEnFontDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
PV = NULL;
m_dyEnFontVB->Lock( 0, 0, (BYTE**)&PV, D3DLOCK_DISCARD );
dwNumTriangles = 0L;
}
}
sx += w;
}
m_dyEnFontVB->Unlock();
if( dwNumTriangles > 0 )
m_dyEnFontDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
}
CardFont::CardFont()
{
m_pD3DDevice = NULL;
m_CardFontMap = NULL;
m_Buffer = NULL;
m_strFileName = NULL;
m_sx = m_sy = 0;
m_CardWidth = 0;
m_CardHeight = 0;
m_Align = 0;
m_CardBufferPtr = 0;
m_CardMapWidth = 0;
m_CardMapHeight = 0;
m_CardOffsetSX = 0;
m_CardOffsetSY = 0;
m_CardNumberToRender = 0;
}
CardFont::~CardFont()
{
SAFE_RELEASE(m_pD3DDevice);
SAFE_RELEASE(m_CardFontMap);
SAFE_RELEASE(m_Buffer);
SAFE_DELETE_ARRAY(m_strFileName);
}
BOOL CardFont::CreateCardFont(LPDIRECT3DDEVICE8 device,DWORD clrKey)
{
HRESULT hr;
if ( device == NULL )
return FALSE;
m_pD3DDevice = device;
hr = D3DXCreateTextureFromFileEx(device, m_strFileName,
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A1R5G5B5,
D3DPOOL_DEFAULT, D3DX_FILTER_TRIANGLE, D3DX_FILTER_TRIANGLE,
clrKey, NULL, NULL, &m_CardFontMap);
if ( FAILED(hr) )
return FALSE;
hr = device->CreateVertexBuffer( FONT_NUM_IN_LINE * 6 * sizeof(FONT::CARD2DVERTEX),
0,0,D3DPOOL_MANAGED,&m_Buffer);
if ( FAILED(hr) )
return FALSE;
return TRUE;
}
VOID CardFont::SetfreeContext()
{
SAFE_RELEASE(m_pD3DDevice);
SAFE_RELEASE(m_CardFontMap);
SAFE_RELEASE(m_Buffer);
}
VOID CardFont::SetOut2DCard(LONG sx, LONG sy, LONG cx,LONG cy,UINT nAlign)
{
m_sx = sx;m_sy = sy;
m_Align = nAlign;
m_CardWidth = cx; m_CardHeight = cy;
}
VOID CardFont::Out2DCard(LONG x, LONG y,FLOAT fSize,DWORD clr)
{
D3DXVECTOR3 billboardx = D3DXVECTOR3(1,0,0);
D3DXVECTOR3 billboardy = D3DXVECTOR3(0,1,0);
FLOAT TU = (FLOAT)(x * m_CardWidth + m_CardOffsetSX) / m_CardMapWidth;
FLOAT TV = (FLOAT)(y * m_CardHeight + m_CardOffsetSY) / m_CardMapHeight;
FLOAT TDU = (FLOAT)m_CardWidth / (m_CardMapWidth);
FLOAT TDV = (FLOAT)m_CardHeight / (m_CardMapHeight);
D3DXVECTOR3 coords(m_sx,m_sy,0.9f);
coords = coords - billboardx * (0.5f * fSize)
+ billboardy * (0.5f * fSize);
*m_CardBufferPtr = CARD2DVERTEX(coords,1.0f,clr,TU,TV+TDV);m_CardBufferPtr++;
coords = coords + billboardx * fSize;
*m_CardBufferPtr = CARD2DVERTEX(coords,1.0f,clr,TU+TDU,TV+TDV);m_CardBufferPtr++;
coords = coords - billboardx * fSize
- billboardy * fSize;
*m_CardBufferPtr = CARD2DVERTEX(coords,1.0f,clr,TU,TV);m_CardBufferPtr++;
*m_CardBufferPtr = CARD2DVERTEX(coords,1.0f,clr,TU,TV);m_CardBufferPtr++;
coords = coords + billboardx * fSize
+ billboardy * fSize;
*m_CardBufferPtr = CARD2DVERTEX(coords,1.0f,clr,TU+TDU,TV+TDV);m_CardBufferPtr++;
coords = coords - billboardy * fSize;
*m_CardBufferPtr = CARD2DVERTEX(coords,1.0f,clr,TU+TDU,TV);m_CardBufferPtr++;
if ( m_Align == ALIGN_ACROSS )
m_sx += fSize;
else
m_sy += fSize;
m_CardNumberToRender++;
CHECK_RANGE(m_CardNumberToRender,0,FONT_NUM_IN_LINE);
}
VOID CardFont::SetCardFile(TCHAR *strFileName,LONG wsize,LONG hsize)
{
if ( strFileName != NULL)
{
SAFE_DELETE_ARRAY(m_strFileName);
m_strFileName = new TCHAR[_tcslen(strFileName)+1];
_tcscpy(m_strFileName,strFileName);
m_CardMapWidth = wsize;
m_CardMapHeight = hsize;
}
}
BOOL CardFont::LockCardBuffer()
{
HRESULT hr;
hr = m_Buffer->Lock( 0,0,(BYTE**)&m_CardBufferPtr,0);
if(FAILED(hr))
return FALSE;
return TRUE;
}
VOID CardFont::UnlockCardBuffer()
{
m_Buffer->Unlock();
}
VOID CardFont::CardInScene()
{
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE ,TRUE);
m_pD3DDevice->SetRenderState(D3DRS_ALPHAREF ,0x08);
m_pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL);
m_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE,TRUE);
m_pD3DDevice->SetTexture(0,m_CardFontMap);
m_pD3DDevice->SetStreamSource(0,m_Buffer,sizeof(FONT::CARD2DVERTEX));
m_pD3DDevice->SetVertexShader(CARD2DVERTEX::FVF_CARD2DVERTEX);
m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,m_CardNumberToRender * 2);
m_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE,FALSE);
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE ,FALSE);
m_pD3DDevice->SetTexture(0,0);
}
VOID CardFont::SetCardOffSet(LONG sx, LONG sy)
{
m_CardOffsetSX = sx;
m_CardOffsetSY = sy;
}
VOID EnFont::SetfreeContext()
{
SAFE_RELEASE(m_dyEnFontVB);
m_dwSavedStateBlock = 0L;
m_dwDrawTextStateBlock = 0L;
}
BOOL EnFont::SetEnFont(LPDIRECT3DDEVICE8 device,TCHAR *strFontface, LONG dwFontHeight, LONG dwBold, BOOL bItalic, BOOL bUnderline)
{
HRESULT hr;
if (device == NULL) return FALSE;
m_dyEnFontDevice = device;
m_fTextScale = 1.0f;
m_dwFontHeight = dwFontHeight;
if( m_dwFontHeight > 40 )
m_dwTexWidth = m_dwTexHeight = 1024;
else if( m_dwFontHeight > 20 )
m_dwTexWidth = m_dwTexHeight = 512;
else
m_dwTexWidth = m_dwTexHeight = 256;
D3DCAPS8 d3dCaps;
m_dyEnFontDevice->GetDeviceCaps( &d3dCaps );
if( m_dwTexWidth > d3dCaps.MaxTextureWidth )
{
m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth;
m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth;
}
hr = m_dyEnFontDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1,
0, D3DFMT_A4R4G4B4,
D3DPOOL_MANAGED, &m_dyEnFontCache );
if( FAILED(hr) )
return FALSE;
BITMAPINFO bmi;
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;
HDC hDC = CreateCompatibleDC( NULL );
DWORD* dyEnBitMaps = NULL;
HBITMAP hBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
(VOID**)&dyEnBitMaps, NULL, 0 );
SetMapMode( hDC, MM_TEXT );
LONG nHeight = -MulDiv( m_dwFontHeight,
(LONG)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
HFONT hEnFont = CreateFont( nHeight, 0, 0, 0, dwBold, bItalic,
bUnderline, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, strFontface );
if( NULL == hEnFont )
{
DeleteObject(hBitmap);
DeleteDC(hDC);
return FALSE;
}
SelectObject( hDC, hBitmap );
SelectObject( hDC, hEnFont );
SetTextColor( hDC, RGB(255,255,255) );
SetBkColor( hDC, 0x00000000 );
SetTextAlign( hDC, TA_TOP );
DWORD x = 0;
DWORD y = 0;
TCHAR str[2] = _T("x");
SIZE size;
for( TCHAR c=32; c<127; c++ )
{
str[0] = c;
GetTextExtentPoint32( hDC, str, 1, &size );
if( (DWORD)(x+size.cx+1) > m_dwTexWidth )
{
x = 0;
y += size.cy+1;
}
ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL );
m_fTexCoords[c-32][0] = ((FLOAT)(x+0))/m_dwTexWidth;
m_fTexCoords[c-32][1] = ((FLOAT)(y+0))/m_dwTexHeight;
m_fTexCoords[c-32][2] = ((FLOAT)(x+0+size.cx))/m_dwTexWidth;
m_fTexCoords[c-32][3] = ((FLOAT)(y+0+size.cy))/m_dwTexHeight;
x += size.cx+1;
}
D3DLOCKED_RECT d3dlr;
m_dyEnFontCache->LockRect( 0, &d3dlr, 0, 0 );
BYTE* pDstRow = (BYTE*)d3dlr.pBits;
WORD* pDst16;
BYTE bAlpha;
for( y=0; y < m_dwTexHeight; y++ )
{
pDst16 = (WORD*)pDstRow;
for( x=0; x < m_dwTexWidth; x++ )
{
bAlpha = (BYTE)((dyEnBitMaps[m_dwTexWidth*y + x] & 0xff) >> 4);
if (bAlpha > 0)
{
*pDst16++ = (bAlpha << 12) | 0x0fff;
}
else
{
*pDst16++ = 0x0000;
}
}
pDstRow += d3dlr.Pitch;
}
m_dyEnFontCache->UnlockRect(0);
DeleteObject( hBitmap );
DeleteDC( hDC );
DeleteObject( hEnFont );
return TRUE;
}
VOID EnFont::BeginTextOut()
{
m_dyEnFontDevice->CaptureStateBlock( m_dwSavedStateBlock );
m_dyEnFontDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
m_dyEnFontDevice->SetVertexShader( CARD2DVERTEX::FVF_CARD2DVERTEX );
m_dyEnFontDevice->SetPixelShader( NULL );
m_dyEnFontDevice->SetStreamSource( 0, m_dyEnFontVB, sizeof(CARD2DVERTEX) );
}
VOID EnFont::EndTextOut()
{
m_dyEnFontDevice->ApplyStateBlock( m_dwSavedStateBlock );
}
BOOL EnFont::CreateContext(LPDIRECT3DDEVICE8 device)
{
HRESULT hr;
hr = m_dyEnFontDevice->CreateVertexBuffer( MAX_NUM_VERTICES * sizeof(CARD2DVERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
D3DPOOL_DEFAULT, &m_dyEnFontVB );
if(FAILED(hr)) return FALSE;
// 创建2块
for( UINT which=0; which<2; which++ )
{
m_dyEnFontDevice->BeginStateBlock();
m_dyEnFontDevice->SetTexture( 0, m_dyEnFontCache );
m_dyEnFontDevice->SetRenderState( D3DRS_ZENABLE,FALSE);
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_dyEnFontDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_dyEnFontDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_dyEnFontDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
m_dyEnFontDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
m_dyEnFontDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 );
m_dyEnFontDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
m_dyEnFontDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
m_dyEnFontDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
m_dyEnFontDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE );
m_dyEnFontDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
m_dyEnFontDevice->SetRenderState( D3DRS_EDGEANTIALIAS, FALSE );
m_dyEnFontDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, FALSE );
m_dyEnFontDevice->SetRenderState( D3DRS_VERTEXBLEND, FALSE );
m_dyEnFontDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
m_dyEnFontDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_POINT );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_POINT );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
m_dyEnFontDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
m_dyEnFontDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
m_dyEnFontDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
if( which==0 )
m_dyEnFontDevice->EndStateBlock( &m_dwSavedStateBlock );
else
m_dyEnFontDevice->EndStateBlock( &m_dwDrawTextStateBlock );
}
return TRUE;
}
VOID CardFont::BeginCardOut()
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -