0001:
0002:
0003:
0004:
0005:
0006: #define STRICT
0007: #include <stdio.h>
0008: #include <tchar.h>
0009: #include <D3DX9.h>
0010: #include "D3DFont.h"
0011: #include "D3DUtil.h"
0012: #include "DXUtil.h"
0013:
0014:
0015:
0016:
0017:
0018:
0019:
0020: #define MAX_NUM_VERTICES 50*6
0021:
0022: struct FONT2DVERTEX { D3DXVECTOR4 p; DWORD color; FLOAT tu, tv; };
0023: struct FONT3DVERTEX { D3DXVECTOR3 p; D3DXVECTOR3 n; FLOAT tu, tv; };
0024:
0025: #define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
0026: #define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
0027:
0028: inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color,
0029: FLOAT tu, FLOAT tv )
0030: {
0031: FONT2DVERTEX v; v.p = p; v.color = color; v.tu = tu; v.tv = tv;
0032: return v;
0033: }
0034:
0035: inline FONT3DVERTEX InitFont3DVertex( const D3DXVECTOR3& p, const D3DXVECTOR3& n,
0036: FLOAT tu, FLOAT tv )
0037: {
0038: FONT3DVERTEX v; v.p = p; v.n = n; v.tu = tu; v.tv = tv;
0039: return v;
0040: }
0041:
0042:
0043:
0044:
0045:
0046:
0047:
0048:
0049: CD3DFont::CD3DFont( const TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags )
0050: {
0051: _tcsncpy( m_strFontName, strFontName, sizeof(m_strFontName) / sizeof(TCHAR) );
0052: m_strFontName[sizeof(m_strFontName) / sizeof(TCHAR) - 1] = _T('\0');
0053: m_dwFontHeight = dwHeight;
0054: m_dwFontFlags = dwFlags;
0055: m_dwSpacing = 0;
0056:
0057: m_pd3dDevice = NULL;
0058: m_pTexture = NULL;
0059: m_pVB = NULL;
0060:
0061: m_pStateBlockSaved = NULL;
0062: m_pStateBlockDrawText = NULL;
0063: }
0064:
0065:
0066:
0067:
0068:
0069:
0070:
0071:
0072: CD3DFont::~CD3DFont()
0073: {
0074: InvalidateDeviceObjects();
0075: DeleteDeviceObjects();
0076: }
0077:
0078:
0079:
0080:
0081:
0082:
0083:
0084:
0085:
0086: HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
0087: {
0088: HRESULT hr;
0089:
0090:
0091: m_pd3dDevice = pd3dDevice;
0092:
0093:
0094: m_fTextScale = 1.0f;
0095:
0096:
0097: if( m_dwFontHeight > 60 )
0098: m_dwTexWidth = m_dwTexHeight = 2048;
0099: else if( m_dwFontHeight > 30 )
0100: m_dwTexWidth = m_dwTexHeight = 1024;
0101: else if( m_dwFontHeight > 15 )
0102: m_dwTexWidth = m_dwTexHeight = 512;
0103: else
0104: m_dwTexWidth = m_dwTexHeight = 256;
0105:
0106:
0107:
0108: D3DCAPS9 d3dCaps;
0109: m_pd3dDevice->GetDeviceCaps( &d3dCaps );
0110:
0111: if( m_dwTexWidth > d3dCaps.MaxTextureWidth )
0112: {
0113: m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth;
0114: m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth;
0115: }
0116:
0117:
0118: hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1,
0119: 0, D3DFMT_A4R4G4B4,
0120: D3DPOOL_MANAGED, &m_pTexture, NULL );
0121: if( FAILED(hr) )
0122: return hr;
0123:
0124:
0125: DWORD* pBitmapBits;
0126: BITMAPINFO bmi;
0127: ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
0128: bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
0129: bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
0130: bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
0131: bmi.bmiHeader.biPlanes = 1;
0132: bmi.bmiHeader.biCompression = BI_RGB;
0133: bmi.bmiHeader.biBitCount = 32;
0134:
0135:
0136: HDC hDC = CreateCompatibleDC( NULL );
0137: HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
0138: (void**)&pBitmapBits, NULL, 0 );
0139: SetMapMode( hDC, MM_TEXT );
0140:
0141:
0142:
0143: INT nHeight = -MulDiv( m_dwFontHeight,
0144: (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
0145: DWORD dwBold = (m_dwFontFlags&D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL;
0146: DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE : FALSE;
0147: HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic,
0148: FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
0149: CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
0150: VARIABLE_PITCH, m_strFontName );
0151: if( NULL==hFont )
0152: return E_FAIL;
0153:
0154: HGDIOBJ hbmOld = SelectObject( hDC, hbmBitmap );
0155: HGDIOBJ hFontOld = SelectObject( hDC, hFont );
0156:
0157:
0158: SetTextColor( hDC, RGB(255,255,255) );
0159: SetBkColor( hDC, 0x00000000 );
0160: SetTextAlign( hDC, TA_TOP );
0161:
0162:
0163:
0164: DWORD x = 0;
0165: DWORD y = 0;
0166: TCHAR str[2] = _T("x");
0167: SIZE size;
0168:
0169:
0170: GetTextExtentPoint32( hDC, TEXT(" "), 1, &size );
0171: x = m_dwSpacing = (DWORD) ceil(size.cy * 0.3f);
0172:
0173: for( TCHAR c=32; c<127; c++ )
0174: {
0175: str[0] = c;
0176: GetTextExtentPoint32( hDC, str, 1, &size );
0177:
0178: if( (DWORD)(x + size.cx + m_dwSpacing) > m_dwTexWidth )
0179: {
0180: x = m_dwSpacing;
0181: y += size.cy+1;
0182: }
0183:
0184: ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL );
0185:
0186: m_fTexCoords[c-32][0] = ((FLOAT)(x + 0 - m_dwSpacing))/m_dwTexWidth;
0187: m_fTexCoords[c-32][1] = ((FLOAT)(y + 0 + 0 ))/m_dwTexHeight;
0188: m_fTexCoords[c-32][2] = ((FLOAT)(x + size.cx + m_dwSpacing))/m_dwTexWidth;
0189: m_fTexCoords[c-32][3] = ((FLOAT)(y + size.cy + 0 ))/m_dwTexHeight;
0190:
0191: x += size.cx + (2 * m_dwSpacing);
0192: }
0193:
0194:
0195: D3DLOCKED_RECT d3dlr;
0196: m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
0197: BYTE* pDstRow = (BYTE*)d3dlr.pBits;
0198: WORD* pDst16;
0199: BYTE bAlpha;
0200:
0201: for( y=0; y < m_dwTexHeight; y++ )
0202: {
0203: pDst16 = (WORD*)pDstRow;
0204: for( x=0; x < m_dwTexWidth; x++ )
0205: {
0206: bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
0207: if (bAlpha > 0)
0208: {
0209: *pDst16++ = (WORD) ((bAlpha << 12) | 0x0fff);
0210: }
0211: else
0212: {
0213: *pDst16++ = 0x0000;
0214: }
0215: }
0216: pDstRow += d3dlr.Pitch;
0217: }
0218:
0219:
0220: m_pTexture->UnlockRect(0);
0221: SelectObject( hDC, hbmOld );
0222: SelectObject( hDC, hFontOld );
0223: DeleteObject( hbmBitmap );
0224: DeleteObject( hFont );
0225: DeleteDC( hDC );
0226:
0227: return S_OK;
0228: }
0229:
0230:
0231:
0232:
0233:
0234:
0235:
0236:
0237: HRESULT CD3DFont::RestoreDeviceObjects()
0238: {
0239: HRESULT hr;
0240:
0241:
0242: int vertexSize = max( sizeof(FONT2DVERTEX), sizeof(FONT3DVERTEX ) );
0243: if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( MAX_NUM_VERTICES * vertexSize,
0244: D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
0245: D3DPOOL_DEFAULT, &m_pVB, NULL ) ) )
0246: {
0247: return hr;
0248: }
0249:
0250:
0251: for( UINT which=0; which<2; which++ )
0252: {
0253: m_pd3dDevice->BeginStateBlock();
0254: m_pd3dDevice->SetTexture( 0, m_pTexture );
0255:
0256: if ( D3DFONT_ZENABLE & m_dwFontFlags )
0257: m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
0258: else
0259: m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
0260:
0261: m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
0262: m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
0263: m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
0264: m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
0265: m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 );
0266: m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
0267: m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
0268: m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
0269: m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE );
0270: m_pd3dDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
0271: m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, FALSE );
0272: m_pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, D3DVBF_DISABLE );
0273: m_pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
0274: m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
0275: m_pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE,
0276: D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN |
0277: D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA );
0278: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
0279: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0280: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
0281: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
0282: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
0283: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
0284: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
0285: m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
0286: m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
0287: m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
0288: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
0289: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
0290: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE );
0291:
0292: if( which==0 )
0293: m_pd3dDevice->EndStateBlock( &m_pStateBlockSaved );
0294: else
0295: m_pd3dDevice->EndStateBlock( &m_pStateBlockDrawText );
0296: }
0297:
0298: return S_OK;
0299: }
0300:
0301:
0302:
0303:
0304:
0305:
0306:
0307:
0308: HRESULT CD3DFont::InvalidateDeviceObjects()
0309: {
0310: SAFE_RELEASE( m_pVB );
0311: SAFE_RELEASE( m_pStateBlockSaved );
0312: SAFE_RELEASE( m_pStateBlockDrawText );
0313:
0314: return S_OK;
0315: }
0316:
0317:
0318:
0319:
0320:
0321:
0322:
0323:
0324: HRESULT CD3DFont::DeleteDeviceObjects()
0325: {
0326: SAFE_RELEASE( m_pTexture );
0327: m_pd3dDevice = NULL;
0328:
0329: return S_OK;
0330: }
0331:
0332:
0333:
0334:
0335:
0336:
0337:
0338:
0339: HRESULT CD3DFont::GetTextExtent( const TCHAR* strText, SIZE* pSize )
0340: {
0341: if( NULL==strText || NULL==pSize )
0342: return E_FAIL;
0343:
0344: FLOAT fRowWidth = 0.0f;
0345: FLOAT fRowHeight = (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
0346: FLOAT fWidth = 0.0f;
0347: FLOAT fHeight = fRowHeight;
0348:
0349: while( *strText )
0350: {
0351: TCHAR c = *strText++;
0352:
0353: if( c == _T('\n') )
0354: {
0355: fRowWidth = 0.0f;
0356: fHeight += fRowHeight;
0357: }
0358:
0359: if( (c-32) < 0 || (c-32) >= 128-32 )
0360: continue;
0361:
0362: FLOAT tx1 = m_fTexCoords[c-32][0];
0363: FLOAT tx2 = m_fTexCoords[c-32][2];
0364:
0365: fRowWidth += (tx2-tx1)*m_dwTexWidth - 2*m_dwSpacing;
0366:
0367: if( fRowWidth > fWidth )
0368: fWidth = fRowWidth;
0369: }
0370:
0371: pSize->cx = (int)fWidth;
0372: pSize->cy = (int)fHeight;
0373:
0374: return S_OK;
0375: }
0376:
0377:
0378:
0379:
0380:
0381:
0382:
0383:
0384:
0385:
0386:
0387:
0388: HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
0389: FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
0390: const TCHAR* strText, DWORD dwFlags )
0391: {
0392: if( m_pd3dDevice == NULL )
0393: return E_FAIL;
0394:
0395:
0396: m_pStateBlockSaved->Capture();
0397: m_pStateBlockDrawText->Apply();
0398: m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX );
0399: m_pd3dDevice->SetPixelShader( NULL );
0400: m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
0401:
0402:
0403: if( dwFlags & D3DFONT_FILTERED )
0404: {
0405: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
0406: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
0407: }
0408:
0409: D3DVIEWPORT9 vp;
0410: m_pd3dDevice->GetViewport( &vp );
0411: FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight;
0412:
0413:
0414: if( dwFlags & D3DFONT_CENTERED_X )
0415: {
0416: const TCHAR* strTextTmp = strText;
0417: float xFinal = 0.0f;
0418:
0419: while( *strTextTmp )
0420: {
0421: TCHAR c = *strTextTmp++;
0422:
0423: if( c == _T('\n') )
0424: break;
0425: if( (c-32) < 0 || (c-32) >= 128-32 )
0426: continue;
0427:
0428: FLOAT tx1 = m_fTexCoords[c-32][0];
0429: FLOAT tx2 = m_fTexCoords[c-32][2];
0430:
0431: FLOAT w = (tx2-tx1)*m_dwTexWidth;
0432:
0433: w *= (fXScale*vp.Height)/fLineHeight;
0434:
0435: xFinal += w - (2 * m_dwSpacing) * (fXScale*vp.Height)/fLineHeight;
0436: }
0437:
0438: x = -xFinal/vp.Width;
0439: }
0440: if( dwFlags & D3DFONT_CENTERED_Y )
0441: {
0442: y = -fLineHeight/vp.Height;
0443: }
0444:
0445: FLOAT sx = (x+1.0f)*vp.Width/2;
0446: FLOAT sy = (y+1.0f)*vp.Height/2;
0447: FLOAT sz = z;
0448: FLOAT rhw = 1.0f;
0449:
0450:
0451: sx -= m_dwSpacing * (fXScale*vp.Height)/fLineHeight;
0452: FLOAT fStartX = sx;
0453:
0454:
0455: FONT2DVERTEX* pVertices;
0456: DWORD dwNumTriangles = 0L;
0457: m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
0458:
0459: while( *strText )
0460: {
0461: TCHAR c = *strText++;
0462:
0463: if( c == _T('\n') )
0464: {
0465: sx = fStartX;
0466: sy += fYScale*vp.Height;
0467: }
0468:
0469: if( (c-32) < 0 || (c-32) >= 128-32 )
0470: continue;
0471:
0472: FLOAT tx1 = m_fTexCoords[c-32][0];
0473: FLOAT ty1 = m_fTexCoords[c-32][1];
0474: FLOAT tx2 = m_fTexCoords[c-32][2];
0475: FLOAT ty2 = m_fTexCoords[c-32][3];
0476:
0477: FLOAT w = (tx2-tx1)*m_dwTexWidth;
0478: FLOAT h = (ty2-ty1)*m_dwTexHeight;
0479:
0480: w *= (fXScale*vp.Height)/fLineHeight;
0481: h *= (fYScale*vp.Height)/fLineHeight;
0482:
0483: if( c != _T(' ') )
0484: {
0485: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx1, ty2 );
0486: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 );
0487: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 );
0488: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx2, ty1 );
0489: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 );
0490: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 );
0491: dwNumTriangles += 2;
0492:
0493: if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
0494: {
0495:
0496: m_pVB->Unlock();
0497: m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
0498: m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
0499: dwNumTriangles = 0L;
0500: }
0501: }
0502:
0503: sx += w - (2 * m_dwSpacing) * (fXScale*vp.Height)/fLineHeight;
0504: }
0505:
0506:
0507: m_pVB->Unlock();
0508: if( dwNumTriangles > 0 )
0509: m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
0510:
0511:
0512: m_pStateBlockSaved->Apply();
0513:
0514: return S_OK;
0515: }
0516:
0517:
0518:
0519:
0520:
0521:
0522:
0523:
0524: HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
0525: const TCHAR* strText, DWORD dwFlags )
0526: {
0527: if( m_pd3dDevice == NULL )
0528: return E_FAIL;
0529:
0530:
0531: m_pStateBlockSaved->Capture();
0532: m_pStateBlockDrawText->Apply();
0533: m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX );
0534: m_pd3dDevice->SetPixelShader( NULL );
0535: m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
0536:
0537:
0538: if( dwFlags & D3DFONT_FILTERED )
0539: {
0540: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
0541: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
0542: }
0543:
0544:
0545: if( dwFlags & D3DFONT_CENTERED_X )
0546: {
0547: D3DVIEWPORT9 vp;
0548: m_pd3dDevice->GetViewport( &vp );
0549: const TCHAR* strTextTmp = strText;
0550: float xFinal = 0.0f;
0551:
0552: while( *strTextTmp )
0553: {
0554: TCHAR c = *strTextTmp++;
0555:
0556: if( c == _T('\n') )
0557: break;
0558: if( (c-32) < 0 || (c-32) >= 128-32 )
0559: continue;
0560:
0561: FLOAT tx1 = m_fTexCoords[c-32][0];
0562: FLOAT tx2 = m_fTexCoords[c-32][2];
0563:
0564: FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale;
0565:
0566: xFinal += w - (2 * m_dwSpacing);
0567: }
0568:
0569: sx = (vp.Width-xFinal)/2.0f;
0570: }
0571: if( dwFlags & D3DFONT_CENTERED_Y )
0572: {
0573: D3DVIEWPORT9 vp;
0574: m_pd3dDevice->GetViewport( &vp );
0575: float fLineHeight = ((m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight);
0576: sy = (vp.Height-fLineHeight)/2;
0577: }
0578:
0579:
0580: sx -= m_dwSpacing;
0581: FLOAT fStartX = sx;
0582:
0583:
0584: FONT2DVERTEX* pVertices = NULL;
0585: DWORD dwNumTriangles = 0;
0586: m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
0587:
0588: while( *strText )
0589: {
0590: TCHAR c = *strText++;
0591:
0592: if( c == _T('\n') )
0593: {
0594: sx = fStartX;
0595: sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
0596: }
0597:
0598: if( (c-32) < 0 || (c-32) >= 128-32 )
0599: continue;
0600:
0601: FLOAT tx1 = m_fTexCoords[c-32][0];
0602: FLOAT ty1 = m_fTexCoords[c-32][1];
0603: FLOAT tx2 = m_fTexCoords[c-32][2];
0604: FLOAT ty2 = m_fTexCoords[c-32][3];
0605:
0606: FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale;
0607: FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale;
0608:
0609: if( c != _T(' ') )
0610: {
0611: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 );
0612: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
0613: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
0614: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 );
0615: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
0616: *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
0617: dwNumTriangles += 2;
0618:
0619: if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
0620: {
0621:
0622: m_pVB->Unlock();
0623: m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
0624: pVertices = NULL;
0625: m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
0626: dwNumTriangles = 0L;
0627: }
0628: }
0629:
0630: sx += w - (2 * m_dwSpacing);
0631: }
0632:
0633:
0634: m_pVB->Unlock();
0635: if( dwNumTriangles > 0 )
0636: m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
0637:
0638:
0639: m_pStateBlockSaved->Apply();
0640:
0641: return S_OK;
0642: }
0643:
0644:
0645:
0646:
0647:
0648:
0649:
0650:
0651: HRESULT CD3DFont::Render3DText( const TCHAR* strText, DWORD dwFlags )
0652: {
0653: if( m_pd3dDevice == NULL )
0654: return E_FAIL;
0655:
0656:
0657: m_pStateBlockSaved->Capture();
0658: m_pStateBlockDrawText->Apply();
0659: m_pd3dDevice->SetFVF( D3DFVF_FONT3DVERTEX );
0660: m_pd3dDevice->SetPixelShader( NULL );
0661: m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT3DVERTEX) );
0662:
0663:
0664: if( dwFlags & D3DFONT_FILTERED )
0665: {
0666: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
0667: m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
0668: }
0669:
0670:
0671: FLOAT x = 0.0f;
0672: FLOAT y = 0.0f;
0673:
0674:
0675: if( dwFlags & D3DFONT_CENTERED_X )
0676: {
0677: SIZE sz;
0678: GetTextExtent( strText, &sz );
0679: x = -(((FLOAT)sz.cx)/10.0f)/2.0f;
0680: }
0681: if( dwFlags & D3DFONT_CENTERED_Y )
0682: {
0683: SIZE sz;
0684: GetTextExtent( strText, &sz );
0685: y = -(((FLOAT)sz.cy)/10.0f)/2.0f;
0686: }
0687:
0688:
0689: if( dwFlags & D3DFONT_TWOSIDED )
0690: m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
0691:
0692:
0693: x -= m_dwSpacing / 10.0f;
0694: FLOAT fStartX = x;
0695: TCHAR c;
0696:
0697:
0698: FONT3DVERTEX* pVertices;
0699: DWORD dwNumTriangles = 0L;
0700: m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
0701:
0702: while( (c = *strText++) != 0 )
0703: {
0704: if( c == '\n' )
0705: {
0706: x = fStartX;
0707: y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f;
0708: }
0709:
0710: if( (c-32) < 0 || (c-32) >= 128-32 )
0711: continue;
0712:
0713: FLOAT tx1 = m_fTexCoords[c-32][0];
0714: FLOAT ty1 = m_fTexCoords[c-32][1];
0715: FLOAT tx2 = m_fTexCoords[c-32][2];
0716: FLOAT ty2 = m_fTexCoords[c-32][3];
0717:
0718: FLOAT w = (tx2-tx1) * m_dwTexWidth / ( 10.0f * m_fTextScale );
0719: FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale );
0720:
0721: if( c != _T(' ') )
0722: {
0723: *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+0,0), D3DXVECTOR3(0,0,-1), tx1, ty2 );
0724: *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
0725: *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 );
0726: *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+h,0), D3DXVECTOR3(0,0,-1), tx2, ty1 );
0727: *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 );
0728: *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
0729: dwNumTriangles += 2;
0730:
0731: if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
0732: {
0733:
0734: m_pVB->Unlock();
0735: m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
0736: m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
0737: dwNumTriangles = 0L;
0738: }
0739: }
0740:
0741: x += w - (2 * m_dwSpacing) / 10.0f;
0742: }
0743:
0744:
0745: m_pVB->Unlock();
0746: if( dwNumTriangles > 0 )
0747: m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
0748:
0749:
0750: m_pStateBlockSaved->Apply();
0751:
0752: return S_OK;
0753: }
0754:
0755:
0756:
0757:
0758: