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