CD3DFont corrupting the heap |:

Posts 1–15 of 16 · Page 1 of 2
CD3DFont corrupting the heap |:
I found this appearingly excellent font class from who knows where, but it's all over the internet... (CD3DFont), which has simplified everything for me... except... I can't use it when I compiled the file.

I've narrowed my error down to one single line of code:
[php]fontSegoe = new CD3DFont((TCHAR*)"Segoe UI", 10, NULL);[/php]'

The error is...

First-chance exception at 0x6a1a34a2 (testLibrary.dll) in freedompeace DirectX9 Sample Environment.exe: 0xC0000005: Access violation writing location 0x04a11000.

Now why why why?! And how do I fix it? --"

I've had a real bad day today, so yeah /:

The header and source for the CD3DFont class are below:

Code:
#ifndef D3DFONT_H 
#define D3DFONT_H 
#include <tchar.h> 
#include <D3D9.h> 


// Font creation flags 
#define D3DFONT_BOLD        0x0001 
#define D3DFONT_ITALIC      0x0002 
#define D3DFONT_ZENABLE     0x0004 

// Font rendering flags 
#define D3DFONT_CENTERED_X  0x0001 
#define D3DFONT_CENTERED_Y  0x0002 
#define D3DFONT_TWOSIDED    0x0004 
#define D3DFONT_FILTERED    0x0008 


//----------------------------------------------------------------------------- 
// Name: class CD3DFont 
// Desc: Texture-based font class for doing text in a 3D scene. 
//----------------------------------------------------------------------------- 
class CD3DFont 
{ 
    TCHAR   m_strFontName[80];            // Font properties 
    //DWORD   m_dwFontHeight;  -- moved to public
    DWORD   m_dwFontFlags; 

    LPDIRECT3DDEVICE9       m_pd3dDevice; // A D3DDevice used for rendering 
    LPDIRECT3DTEXTURE9      m_pTexture;   // The d3d texture for this font 
    LPDIRECT3DVERTEXBUFFER9 m_pVB;        // VertexBuffer for rendering text 
    DWORD   m_dwTexWidth;                 // Texture dimensions 
    DWORD   m_dwTexHeight; 
    FLOAT   m_fTextScale; 
    FLOAT   m_fTexCoords[128-32][4]; 
    DWORD   m_dwSpacing;                  // Character pixel spacing per side 

    // Stateblocks for setting and restoring render states 
    LPDIRECT3DSTATEBLOCK9 m_pStateBlockSaved; 
    LPDIRECT3DSTATEBLOCK9 m_pStateBlockDrawText; 

    HRESULT   CreateGDIFont( HDC hDC, HFONT* pFont ); 
    HRESULT   PaintAlphabet( HDC hDC, BOOL bMeasureOnly=FALSE ); 

public: 
	DWORD   m_dwFontHeight; 


    // 2D and 3D text drawing functions 
    HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor,  
                      TCHAR* strText, DWORD dwFlags=0L ); 
    HRESULT DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,  
                            FLOAT fXScale, FLOAT fYScale, DWORD dwColor,  
                            TCHAR* strText, DWORD dwFlags=0L ); 
    HRESULT Render3DText( TCHAR* strText, DWORD dwFlags=0L ); 
     
    // Function to get extent of text 
    HRESULT GetTextExtent( TCHAR* strText, SIZE* pSize ); 

    // Initializing and destroying device-dependent objects 
    HRESULT InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice ); 
    HRESULT RestoreDeviceObjects(); 
    HRESULT InvalidateDeviceObjects(); 
    HRESULT DeleteDeviceObjects(); 

    // Constructor / destructor 
    CD3DFont(  TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags=0L ); 
    ~CD3DFont(); 
}; 




#endif
Code:
//#define _CRT_SECURE_NO_DEPRECATE 
#include "stdafx.h" 
#include <d3dx9.h> 
#include "d3dfont9.h"
#define SAFE_RELEASE(p) { if(p) {(p)->Release();(p)=NULL;} } 

//----------------------------------------------------------------------------- 
// Custom vertex types for rendering text 
//----------------------------------------------------------------------------- 
#define MAX_NUM_VERTICES 50*6 

struct FONT2DVERTEX { D3DXVECTOR4 p;  DWORD color;    FLOAT tu, tv; }; 
struct FONT3DVERTEX { D3DXVECTOR3 p;   D3DXVECTOR3 n;   FLOAT tu, tv; }; 

#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) 
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1) 

inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color, 
                                      FLOAT tu, FLOAT tv ) 
{ 
    FONT2DVERTEX v;   v.p = p;   v.color = color;   v.tu = tu;   v.tv = tv; 
    return v; 
} 

inline FONT3DVERTEX InitFont3DVertex( const D3DXVECTOR3& p, const D3DXVECTOR3& n, 
                                      FLOAT tu, FLOAT tv ) 
{ 
    FONT3DVERTEX v;   v.p = p;   v.n = n;   v.tu = tu;   v.tv = tv; 
    return v; 
} 




//----------------------------------------------------------------------------- 
// Name: CD3DFont() 
// Desc: Font class constructor 
//----------------------------------------------------------------------------- 
CD3DFont::CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags ) 
{ 
    _***ncpy_s( m_strFontName, strFontName, sizeof(m_strFontName) / sizeof(TCHAR) ); 
    m_strFontName[sizeof(m_strFontName) / sizeof(TCHAR) - 1] = _T('\0'); 
    m_dwFontHeight         = dwHeight; 
    m_dwFontFlags          = dwFlags; 
    m_dwSpacing            = 0; 

    m_pd3dDevice           = NULL; 
    m_pTexture             = NULL; 
    m_pVB                  = NULL; 

    m_pStateBlockSaved     = NULL; 
    m_pStateBlockDrawText  = NULL; 
} 

//----------------------------------------------------------------------------- 
// Name: ~CD3DFont() 
// Desc: Font class destructor 
//----------------------------------------------------------------------------- 
CD3DFont::~CD3DFont() 
{ 
    InvalidateDeviceObjects(); 
    DeleteDeviceObjects(); 
} 




//----------------------------------------------------------------------------- 
// Name: CreateGDIFont 
// Desc: Create a font based on the current state of related member variables 
//       and return the handle (or null on error) 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::CreateGDIFont( HDC hDC, HFONT* pFont ) 
{ 
    // Create a font.  By specifying ANTIALIASED_QUALITY, we might get an 
    // antialiased font, but this is not guaranteed. 
    INT nHeight    = -MulDiv( m_dwFontHeight,  
                              (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale),  
                              72 ); 
    DWORD dwBold   = (m_dwFontFlags & D3DFONT_BOLD)   ? FW_BOLD : FW_NORMAL; 
    DWORD dwItalic = (m_dwFontFlags & D3DFONT_ITALIC) ? TRUE    : FALSE; 
    *pFont         = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic, 
                                 FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 
                                 CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, 
                                 VARIABLE_PITCH, m_strFontName ); 

    if( *pFont == NULL ) 
        return E_FAIL; 

    return S_OK; 
} 




//----------------------------------------------------------------------------- 
// Name: PaintAlphabet 
// Desc: Paint the printable characters for the given GDI font onto the 
//       provided device context. If the bMeasureOnly flag is set, no drawing  
//       will occur. 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::PaintAlphabet( HDC hDC, BOOL bMeasureOnly ) 
{ 
    SIZE size; 
    TCHAR str[2] = _T("x"); // One-character, null-terminated string 
     
    // Calculate the spacing between characters based on line height 
    if( 0 == GetTextExtentPoint32( hDC, str, 1, &size ) ) 
        return E_FAIL; 
    m_dwSpacing = (DWORD) ceil(size.cy * 0.3f); 

    // Set the starting point for the drawing 
    DWORD x = m_dwSpacing; 
    DWORD y = 0; 
     
    // For each character, draw text on the DC and advance the current position 
    for( char c = 32; c < 127; c++ ) 
    { 
        str[0] = c; 
        if( 0 == GetTextExtentPoint32( hDC, str, 1, &size ) ) 
            return E_FAIL; 

        if( (DWORD)(x + size.cx + m_dwSpacing) > m_dwTexWidth ) 
        { 
            x  = m_dwSpacing; 
            y += size.cy + 1; 
        } 

        // Check to see if there's room to write the character here 
        if( y + size.cy > m_dwTexHeight ) 
            return D3DERR_MOREDATA; 
            
        if( !bMeasureOnly ) 
        { 
            // Perform the actual drawing 
            if( 0 == ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL ) ) 
                return E_FAIL; 

            m_fTexCoords[c-32][0] = ((FLOAT)(x + 0       - m_dwSpacing))/m_dwTexWidth; 
            m_fTexCoords[c-32][1] = ((FLOAT)(y + 0       + 0          ))/m_dwTexHeight; 
            m_fTexCoords[c-32][2] = ((FLOAT)(x + size.cx + m_dwSpacing))/m_dwTexWidth; 
            m_fTexCoords[c-32][3] = ((FLOAT)(y + size.cy + 0          ))/m_dwTexHeight; 
        } 

        x += size.cx + (2 * m_dwSpacing); 
    } 

    return S_OK; 
} 





//----------------------------------------------------------------------------- 
// Name: InitDeviceObjects() 
// Desc: Initializes device-dependent objects, including the vertex buffer used 
//       for rendering text and the texture map which stores the font image. 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice ) 
{ 
    HRESULT hr = S_OK; 
    HFONT hFont = NULL; 
    HFONT hFontOld = NULL; 
    HDC hDC = NULL; 
    HBITMAP hbmBitmap = NULL; 
    HGDIOBJ hbmOld = NULL; 

    // Keep a local copy of the device 
    m_pd3dDevice = pd3dDevice; 

    // Assume we will draw fonts into texture without scaling unless the 
    // required texture size is found to be larger than the device max 
    m_fTextScale  = 1.0f;  

    hDC = CreateCompatibleDC( NULL ); 
    SetMapMode( hDC, MM_TEXT ); 

    hr = CreateGDIFont( hDC, &hFont ); 
    if( FAILED(hr) ) 
        goto LCleanReturn; 

    hFontOld = (HFONT) SelectObject( hDC, hFont ); 

    // Calculate the dimensions for the smallest power-of-two texture which 
    // can hold all the printable characters 
    m_dwTexWidth = m_dwTexHeight = 128; 
    while( D3DERR_MOREDATA == ( hr = PaintAlphabet( hDC, true ) ) ) 
    { 
        m_dwTexWidth *= 2; 
        m_dwTexHeight *= 2; 
    } 

    if( FAILED(hr) ) 
        goto LCleanReturn; 
     
    // If requested texture is too big, use a smaller texture and smaller font, 
    // and scale up when rendering. 
    D3DCAPS9 d3dCaps; 
    m_pd3dDevice->GetDeviceCaps( &d3dCaps ); 

    if( m_dwTexWidth > d3dCaps.MaxTextureWidth ) 
    { 
        m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth; 
        m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth; 
    
        bool bFirstRun = true; // Flag clear after first run 

        do 
        { 
            // If we've already tried fitting the new text, the scale is still  
            // too large. Reduce and try again. 
            if( !bFirstRun) 
                m_fTextScale *= 0.9f; 

            // The font has to be scaled to fit on the maximum texture size; our 
            // current font is too big and needs to be recreated to scale. 
            DeleteObject( SelectObject( hDC, hFontOld ) ); 

            hr = CreateGDIFont( hDC, &hFont ); 
            if( FAILED(hr) ) 
                goto LCleanReturn; 

            hFontOld = (HFONT) SelectObject( hDC, hFont ); 

            bFirstRun = false; 
        }  
        while( D3DERR_MOREDATA == ( hr = PaintAlphabet( hDC, true ) ) ); 
    } 

     
    // Create a new texture for the font 
    hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, 
                                      0, D3DFMT_A4R4G4B4, 
                                      D3DPOOL_MANAGED, &m_pTexture, NULL ); 
    if( FAILED(hr) ) 
        goto LCleanReturn; 

    // Prepare to create a bitmap 
    DWORD*      pBitmapBits; 
    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; 

    // Create a bitmap for the font 
    hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, 
                                  (void**)&pBitmapBits, NULL, 0 ); 

    hbmOld = SelectObject( hDC, hbmBitmap ); 
     
    // Set text properties 
    SetTextColor( hDC, RGB(255,255,255) ); 
    SetBkColor(   hDC, 0x00000000 ); 
    SetTextAlign( hDC, TA_TOP ); 

    // Paint the alphabet onto the selected bitmap 
    hr = PaintAlphabet( hDC, false ); 
    if( FAILED(hr) ) 
        goto LCleanReturn; 

    // Lock the surface and write the alpha values for the set pixels 
    D3DLOCKED_RECT d3dlr; 
    m_pTexture->LockRect( 0, &d3dlr, 0, 0 ); 
    BYTE* pDstRow; 
    pDstRow = (BYTE*)d3dlr.pBits; 
    WORD* pDst16; 
    BYTE bAlpha; // 4-bit measure of pixel intensity 
    DWORD x, y; 

    for( y=0; y < m_dwTexHeight; y++ ) 
    { 
        pDst16 = (WORD*)pDstRow; 
        for( x=0; x < m_dwTexWidth; x++ ) 
        { 
            bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4); 
            if (bAlpha > 0) 
            { 
                *pDst16++ = (WORD) ((bAlpha << 12) | 0x0fff); 
            } 
            else 
            { 
                *pDst16++ = 0x0000; 
            } 
        } 
        pDstRow += d3dlr.Pitch; 
    } 

    hr = S_OK; 

    // Done updating texture, so clean up used objects 
LCleanReturn: 
    if( m_pTexture ) 
        m_pTexture->UnlockRect(0); 

    SelectObject( hDC, hbmOld ); 
    SelectObject( hDC, hFontOld ); 
    DeleteObject( hbmBitmap ); 
    DeleteObject( hFont ); 
    DeleteDC( hDC ); 

    return hr; 
} 




//----------------------------------------------------------------------------- 
// Name: RestoreDeviceObjects() 
// Desc: 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::RestoreDeviceObjects() 
{ 
    HRESULT hr; 

    // Create vertex buffer for the letters 
    int vertexSize = max( sizeof(FONT2DVERTEX), sizeof(FONT3DVERTEX ) ); 
    if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( MAX_NUM_VERTICES * vertexSize, 
                                                       D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, 
                                                       D3DPOOL_DEFAULT, &m_pVB, NULL ) ) ) 
    { 
        return hr; 
    } 

    bool bSupportsAlphaBlend = true; 
    LPDIRECT3D9 pd3d9 = NULL; 
    if( SUCCEEDED( m_pd3dDevice->GetDirect3D( &pd3d9 ) ) ) 
    { 
        D3DCAPS9 Caps; 
        D3DDISPLAYMODE Mode; 
        LPDIRECT3DSURFACE9 pSurf = NULL; 
        D3DSURFACE_DESC Desc; 
        m_pd3dDevice->GetDeviceCaps( &Caps ); 
        m_pd3dDevice->GetDisplayMode( 0, &Mode ); 
        if( SUCCEEDED( m_pd3dDevice->GetRenderTarget( 0, &pSurf ) ) ) 
        { 
            pSurf->GetDesc( &Desc ); 
            if( FAILED( pd3d9->CheckDeviceFormat( Caps.AdapterOrdinal, Caps.DeviceType, Mode.Format, 
                D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_SURFACE,  
                Desc.Format ) ) ) 
            { 
                bSupportsAlphaBlend = false; 
            } 
            SAFE_RELEASE( pSurf ); 
        } 
        SAFE_RELEASE( pd3d9 ); 
    } 

    // Create the state blocks for rendering text 
    for( UINT which=0; which<2; which++ ) 
    { 
        m_pd3dDevice->BeginStateBlock(); 
        m_pd3dDevice->SetTexture( 0, m_pTexture ); 

        if ( D3DFONT_ZENABLE & m_dwFontFlags ) 
            m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); 
        else 
            m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); 

        if( bSupportsAlphaBlend ) 
        { 
            m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); 
            m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,   D3DBLEND_SRCALPHA ); 
            m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,  D3DBLEND_INVSRCALPHA ); 
        } 
        else 
        { 
            m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); 
        } 
        m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE ); 
        m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF,         0x08 ); 
        m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC,  D3DCMP_GREATEREQUAL ); 
        m_pd3dDevice->SetRenderState( D3DRS_FILLMODE,   D3DFILL_SOLID ); 
        m_pd3dDevice->SetRenderState( D3DRS_CULLMODE,   D3DCULL_CCW ); 
        m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,    FALSE ); 
        m_pd3dDevice->SetRenderState( D3DRS_CLIPPING,         TRUE ); 
        m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE,  FALSE ); 
        m_pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND,      D3DVBF_DISABLE ); 
        m_pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE ); 
        m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,        FALSE ); 
        m_pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE, 
            D3DCOLORWRITEENABLE_RED  | D3DCOLORWRITEENABLE_GREEN | 
            D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA ); 
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE ); 
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); 
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); 
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE ); 
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); 
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); 
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 ); 
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); 
        m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE ); 
        m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE ); 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE ); 

        if( which==0 ) 
            m_pd3dDevice->EndStateBlock( &m_pStateBlockSaved ); 
        else 
            m_pd3dDevice->EndStateBlock( &m_pStateBlockDrawText ); 
    } 

    return S_OK; 
} 




//----------------------------------------------------------------------------- 
// Name: InvalidateDeviceObjects() 
// Desc: Destroys all device-dependent objects 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::InvalidateDeviceObjects() 
{ 
    SAFE_RELEASE( m_pVB ); 
    SAFE_RELEASE( m_pStateBlockSaved ); 
    SAFE_RELEASE( m_pStateBlockDrawText ); 

    return S_OK; 
} 




//----------------------------------------------------------------------------- 
// Name: DeleteDeviceObjects() 
// Desc: Destroys all device-dependent objects 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::DeleteDeviceObjects() 
{ 
    SAFE_RELEASE( m_pTexture ); 
    m_pd3dDevice = NULL; 

    return S_OK; 
} 




//----------------------------------------------------------------------------- 
// Name: GetTextExtent() 
// Desc: Get the dimensions of a text string 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::GetTextExtent( TCHAR* strText, SIZE* pSize ) 
{ 
    if( NULL==strText || NULL==pSize ) 
        return E_FAIL; 

    FLOAT fRowWidth  = 0.0f; 
    FLOAT fRowHeight = (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight; 
    FLOAT fWidth     = 0.0f; 
    FLOAT fHeight    = fRowHeight; 

    while( *strText ) 
    { 
        TCHAR c = *strText++; 

        if( c == _T('\n') ) 
        { 
            fRowWidth = 0.0f; 
            fHeight  += fRowHeight; 
        } 

        if( (c-32) < 0 || (c-32) >= 128-32 ) 
            continue; 

        FLOAT tx1 = m_fTexCoords[c-32][0]; 
        FLOAT tx2 = m_fTexCoords[c-32][2]; 

        fRowWidth += (tx2-tx1)*m_dwTexWidth - 2*m_dwSpacing; 

        if( fRowWidth > fWidth ) 
            fWidth = fRowWidth; 
    } 

    pSize->cx = (int)fWidth; 
    pSize->cy = (int)fHeight; 

    return S_OK; 
} 




//----------------------------------------------------------------------------- 
// Name: DrawTextScaled() 
// Desc: Draws scaled 2D text.  Note that x and y are in viewport coordinates 
//       (ranging from -1 to +1).  fXScale and fYScale are the size fraction  
//       relative to the entire viewport.  For example, a fXScale of 0.25 is 
//       1/8th of the screen width.  This allows you to output text at a fixed 
//       fraction of the viewport, even if the screen or window size changes. 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z, 
                                  FLOAT fXScale, FLOAT fYScale, DWORD dwColor, 
                                   TCHAR* strText, DWORD dwFlags ) 
{ 
    if( m_pd3dDevice == NULL ) 
        return E_FAIL; 

    // Set up renderstate 
    m_pStateBlockSaved->Capture(); 
    m_pStateBlockDrawText->Apply(); 
    m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX ); 
    m_pd3dDevice->SetPixelShader( NULL ); 
    m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) ); 

    // Set filter states 
    if( dwFlags & D3DFONT_FILTERED ) 
    { 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); 
    } 

    D3DVIEWPORT9 vp; 
    m_pd3dDevice->GetViewport( &vp ); 
    FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight; 

    // Center the text block in the viewport 
    if( dwFlags & D3DFONT_CENTERED_X ) 
    { 
        const TCHAR* strTextTmp = strText; 
        float xFinal = 0.0f; 

        while( *strTextTmp ) 
        { 
            TCHAR c = *strTextTmp++; 
     
            if( c == _T('\n') ) 
                break;  // Isn't supported.   
            if( (c-32) < 0 || (c-32) >= 128-32 ) 
                continue; 

            FLOAT tx1 = m_fTexCoords[c-32][0]; 
            FLOAT tx2 = m_fTexCoords[c-32][2]; 

            FLOAT w = (tx2-tx1)*m_dwTexWidth; 

            w *= (fXScale*vp.Height)/fLineHeight; 

            xFinal += w - (2 * m_dwSpacing) * (fXScale*vp.Height)/fLineHeight; 
        } 

        x = -xFinal/vp.Width; 
    } 
    if( dwFlags & D3DFONT_CENTERED_Y ) 
    { 
        y = -fLineHeight/vp.Height; 
    } 

    FLOAT sx  = (x+1.0f)*vp.Width/2; 
    FLOAT sy  = (y+1.0f)*vp.Height/2; 
    FLOAT sz  = z; 
    FLOAT rhw = 1.0f; 

    // Adjust for character spacing 
    sx -= m_dwSpacing * (fXScale*vp.Height)/fLineHeight; 
    FLOAT fStartX = sx; 

    // Fill vertex buffer 
    FONT2DVERTEX* pVertices; 
    DWORD         dwNumTriangles = 0L; 
    m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); 

    while( *strText ) 
    { 
        TCHAR c = *strText++; 

        if( c == _T('\n') ) 
        { 
            sx  = fStartX; 
            sy += fYScale*vp.Height; 
        } 

        if( (c-32) < 0 || (c-32) >= 128-32 ) 
            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; 
        FLOAT h = (ty2-ty1)*m_dwTexHeight; 

        w *= (fXScale*vp.Height)/fLineHeight; 
        h *= (fYScale*vp.Height)/fLineHeight; 

        if( c != _T(' ') ) 
        { 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx1, ty2 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx2, ty1 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 ); 
            dwNumTriangles += 2; 

            if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) 
            { 
                // Unlock, render, and relock the vertex buffer 
                m_pVB->Unlock(); 
                m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); 
                m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); 
                dwNumTriangles = 0L; 
            } 
        } 

        sx += w - (2 * m_dwSpacing) * (fXScale*vp.Height)/fLineHeight; 
    } 

    // Unlock and render the vertex buffer 
    m_pVB->Unlock(); 
    if( dwNumTriangles > 0 ) 
        m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); 

    // Restore the modified renderstates 
    m_pStateBlockSaved->Apply(); 

    return S_OK; 
} 




//----------------------------------------------------------------------------- 
// Name: DrawText() 
// Desc: Draws 2D text. Note that sx and sy are in pixels 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor, 
                            TCHAR* strText, DWORD dwFlags ) 
{ 
    if( m_pd3dDevice == NULL ) 
        return E_FAIL; 

    // Setup renderstate 
    m_pStateBlockSaved->Capture(); 
    m_pStateBlockDrawText->Apply(); 
    m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX ); 
    m_pd3dDevice->SetPixelShader( NULL ); 
    m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) ); 

    // Set filter states 
    if( dwFlags & D3DFONT_FILTERED ) 
    { 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); 
    } 

    // Center the text block in the viewport 
    if( dwFlags & D3DFONT_CENTERED_X ) 
    { 
        D3DVIEWPORT9 vp; 
        m_pd3dDevice->GetViewport( &vp ); 
        const TCHAR* strTextTmp = strText; 
        float xFinal = 0.0f; 

        while( *strTextTmp ) 
        { 
            TCHAR c = *strTextTmp++; 
     
            if( c == _T('\n') ) 
                break;  // Isn't supported.   
            if( (c-32) < 0 || (c-32) >= 128-32 ) 
                continue; 

            FLOAT tx1 = m_fTexCoords[c-32][0]; 
            FLOAT tx2 = m_fTexCoords[c-32][2]; 
     
            FLOAT w = (tx2-tx1) *  m_dwTexWidth / m_fTextScale; 
     
            xFinal += w - (2 * m_dwSpacing); 
        } 

        sx = (vp.Width-xFinal)/2.0f; 
    } 
    if( dwFlags & D3DFONT_CENTERED_Y ) 
    { 
        D3DVIEWPORT9 vp; 
        m_pd3dDevice->GetViewport( &vp ); 
        float fLineHeight = ((m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight); 
        sy = (vp.Height-fLineHeight)/2; 
    } 

    // Adjust for character spacing 
    sx -= m_dwSpacing; 
    FLOAT fStartX = sx; 

    // Fill vertex buffer 
    FONT2DVERTEX* pVertices = NULL; 
    DWORD         dwNumTriangles = 0; 
    m_pVB->Lock( 0, 0, (void**)&pVertices, 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-32) < 0 || (c-32) >= 128-32 ) 
            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(' ') ) 
        { 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); 
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); 
            dwNumTriangles += 2; 

            if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) 
            { 
                // Unlock, render, and relock the vertex buffer 
                m_pVB->Unlock(); 
                m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); 
                pVertices = NULL; 
                m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); 
                dwNumTriangles = 0L; 
            } 
        } 

        sx += w - (2 * m_dwSpacing); 
    } 

    // Unlock and render the vertex buffer 
    m_pVB->Unlock(); 
    if( dwNumTriangles > 0 ) 
        m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); 

    // Restore the modified renderstates 
    m_pStateBlockSaved->Apply(); 

    return S_OK; 
} 




//----------------------------------------------------------------------------- 
// Name: Render3DText() 
// Desc: Renders 3D text 
//----------------------------------------------------------------------------- 
HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags ) 
{ 
    if( m_pd3dDevice == NULL ) 
        return E_FAIL; 

    // Setup renderstate 
    m_pStateBlockSaved->Capture(); 
    m_pStateBlockDrawText->Apply(); 
    m_pd3dDevice->SetFVF( D3DFVF_FONT3DVERTEX ); 
    m_pd3dDevice->SetPixelShader( NULL ); 
    m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT3DVERTEX) ); 

    // Set filter states 
    if( dwFlags & D3DFONT_FILTERED ) 
    { 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); 
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); 
    } 

    // Position for each text element 
    FLOAT x = 0.0f; 
    FLOAT y = 0.0f; 

    // Center the text block at the origin (not the viewport) 
    if( dwFlags & D3DFONT_CENTERED_X ) 
    { 
        SIZE sz; 
        GetTextExtent( strText, &sz ); 
        x = -(((FLOAT)sz.cx)/10.0f)/2.0f; 
    } 
    if( dwFlags & D3DFONT_CENTERED_Y ) 
    { 
        SIZE sz; 
        GetTextExtent( strText, &sz ); 
        y = -(((FLOAT)sz.cy)/10.0f)/2.0f; 
    } 

    // Turn off culling for two-sided text 
    if( dwFlags & D3DFONT_TWOSIDED ) 
        m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); 

    // Adjust for character spacing 
    x -= m_dwSpacing / 10.0f; 
    FLOAT fStartX = x; 
    TCHAR c; 

    // Fill vertex buffer 
    FONT3DVERTEX* pVertices; 
    DWORD         dwNumTriangles = 0L; 
    m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); 

    while( (c = *strText++) != 0 ) 
    { 
        if( c == '\n' ) 
        { 
            x = fStartX; 
            y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f; 
        } 

        if( (c-32) < 0 || (c-32) >= 128-32 ) 
            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  / ( 10.0f * m_fTextScale ); 
        FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale ); 

        if( c != _T(' ') ) 
        { 
            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+0,0), D3DXVECTOR3(0,0,-1), tx1, ty2 ); 
            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 ); 
            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 ); 
            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+h,0), D3DXVECTOR3(0,0,-1), tx2, ty1 ); 
            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 ); 
            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 ); 
            dwNumTriangles += 2; 

            if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) 
            { 
                // Unlock, render, and relock the vertex buffer 
                m_pVB->Unlock(); 
                m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); 
                m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); 
                dwNumTriangles = 0L; 
            } 
        } 

        x += w - (2 * m_dwSpacing) / 10.0f; 
    } 

    // Unlock and render the vertex buffer 
    m_pVB->Unlock(); 
    if( dwNumTriangles > 0 ) 
        m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); 

    // Restore the modified renderstates 
    m_pStateBlockSaved->Apply(); 

    return S_OK; 
}
Is this 'd3dfont.h' or 'd3dfont.cpp'? Listed below are files I found from KODER codes.

d3dfont.h


//-----------------------------------------------------------------------------
// File: D3DFont.h
//
// Desc: Texture-based font class
//-----------------------------------------------------------------------------
#ifndef D3DFONT_H
#define D3DFONT_H
#include "bos.h"
#include <tchar.h>
#include <D3D9.h>


// Font creation flags
#define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002
#define D3DFONT_ZENABLE 0x0004

// Font rendering flags
#define D3DFONT_CENTERED_X 0x0001
#define D3DFONT_CENTERED_Y 0x0002
#define D3DFONT_TWOSIDED 0x0004
#define D3DFONT_FILTERED 0x0008
#define D3DFONT_TOP 0x0016
#define D3DFONT_BOTTOM 0x0032




//-----------------------------------------------------------------------------
// Name: class CD3DFont
// Desc: Texture-based font class for doing text in a 3D scene.
//-----------------------------------------------------------------------------
class CD3DFont
{
TCHAR m_strFontName[80]; // Font properties
DWORD m_dwFontHeight;
DWORD m_dwFontFlags;

LPDIRECT3DDEVICE9 m_pd3dDevice; // A D3DDevice used for rendering
LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
DWORD m_dwTexWidth; // Texture dimensions
DWORD m_dwTexHeight;
FLOAT m_fTextScale;
FLOAT m_fTexCoords[128-32][4];
DWORD m_dwSpacing; // Character pixel spacing per side

// Stateblocks for setting and restoring render states
LPDIRECT3DSTATEBLOCK9 m_pStateBlockSaved;
LPDIRECT3DSTATEBLOCK9 m_pStateBlockDrawText;

public:
// 2D and 3D text drawing functions
HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor,
const TCHAR* strText, DWORD dwFlags=0L );
HRESULT DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
const TCHAR* strText, DWORD dwFlags=0L );
HRESULT Render3DText( const TCHAR* strText, DWORD dwFlags=0L );

// Function to get extent of text
HRESULT GetTextExtent( const TCHAR* strText, SIZE* pSize );

// Initializing and destroying device-dependent objects
HRESULT InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice );
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();
HRESULT DeleteDeviceObjects();

// Constructor / destructor
CD3DFont( const TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags=0L );
~CD3DFont();
};




#endif


About

d3dfont.cpp
Attached below (file is too long) - Make sure you rename it (.cpp instead of .txt)
d3dfont.txtattachment deleted · 16 downloads before removal
Did you change the READWRITE value for the memory page, before you set the detour in the region? I think this comes back to your detour and not this guys font class or anything.
Quote Originally Posted by why06 View Post
Did you change the READWRITE value for the memory page, before you set the detour in the region? I think this comes back to your detour and not this guys font class or anything.
It was working just yesterday, and I have no recollection of any changes today.. and it's just massively failing now.

Also, I don't have a detour, it's just a simple hook on the DirectX render functions /:
Try

Code:
fontSegoe = new CD3DFont("Segoe UI", 10, NULL);
If I remember correctly, the string literal doesn't require a cast to be implemented.

2: Try it without the dynamic memory allocated 'fontSegoe', i.e:
fontSegoe = CD3DFont((TCHAR*)"Segoe UI", 10, NULL);
If it requires a global score, just declare it so. Again, I don't think you need to cast this.
Text file approved, not that I see the reason for uploading a text, C&P into Code box would have worked fine......
Thanks for your help everyone, but I just restored back to yesterday's backup and all problems went away.

I also compared the two, and there was no difference in the source files...

So.. wtf? O.o

EDIT : Nevermind.. error came up again after 5 minutes of run-time.

--"
Ur not checking to make sure the d3d module is loaded so every time you hook. Its a toss up as to weather its loaded or not. That's my best guess. Post the actual hook if u want a definite answer.
Quote Originally Posted by why06 View Post
Ur not checking to make sure the d3d module is loaded so every time you hook. Its a toss up as to weather its loaded or not. That's my best guess. Post the actual hook if u want a definite answer.
I think he is just modifing the D3D Starter Kit, so my guess would be that it requires the old dx08 or 09 files. Check DirectX site for the SDK.
I've never used the original CD3Dfont, however try the one modified by Hans211. I believe that he removed a lot of useless functions and fixed up a few things. I don't use it that often I prefer LPD3DXFONT, but whenever I used it I never had any trouble with it.
Uhm, at school now, so I don't have the code with me.. but here are all the errors I got (originally, in order).

Application verifier has triggered a breakpoint in DirectX9 Sample Environment.exe.

This is an error in DirectX9 Sample Environment.exe or any of the DLLs it has loaded.

Please see the output window for more diagnostic information


=======================================
VERIFIER STOP 0000060E: pid 0x1050: Unexpected exception raised in thread function.

C0000005 : Exception code.
0523F7C0 : Exception record. Use .exr to display it.
0523F7DC : Context record. Use .cxr to display it.
00000000 : Not used.


=======================================
This verifier stop is continuable.
After debugging it use `go' to continue.

=======================================

Application verifier has triggered a breakpoint in DirectX9 Sample Environment.exe.

This is an error in DirectX9 Sample Environment.exe or any of the DLLs it has loaded.

Please see the output window for more diagnostic information
Unhandled exception at 0x73373376 (testLibrary.dll) in DirectX9 Sample Environment.exe: 0xC0000005: Access violation writing location 0x04b0f000.
First-chance exception at 0x73373376 (testLibrary.dll) in DirectX9 Sample Environment.exe: 0xC0000005: Access violation writing location 0x04b0f000.
Quote Originally Posted by CodeDemon View Post
I've never used the original CD3Dfont, however try the one modified by Hans211. I believe that he removed a lot of useless functions and fixed up a few things. I don't use it that often I prefer LPD3DXFONT, but whenever I used it I never had any trouble with it.
Could you post that please?

Meh, plus, I think I found my problem --"

I was strcat-ing something on another thread and overflowing the buffer <.<

stupid stupid me. Thanks for your help everyone !

/facepalm me
Quote Originally Posted by freedompeace View Post
Uhm, at school now, so I don't have the code with me.. but here are all the errors I got (originally, in order).





Could you post that please?

Meh, plus, I think I found my problem --"

I was strcat-ing something on another thread and overflowing the buffer <.<

stupid stupid me. Thanks for your help everyone !

/facepalm me
Yep! Here ya go

HansD3DFont.rar MD5:d29244cd5add522ca22564df3014b6b2 - VirSCAN.org Scanners did not find malware!ⓘ

VirusTotal - Free Online Virus, Malware and URL Scannerⓘ


I uploaded the file incase I C+Ped it incorrectly or if you dont have time to make new files, but here is the source:

Credits to Hans211:

d3dfont9.h
Code:
//-----------------------------------------------------------------------------
// File: D3DFont.h
// Desc: Texture-based font class
// Copyright (c)  Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#ifndef D3DFONT_H
#define D3DFONT_H
#include <tchar.h>
#include <D3D9.h>


// Font creation flags
#define D3DFONT_BOLD        0x0001
#define D3DFONT_ITALIC      0x0002
#define D3DFONT_ZENABLE     0x0004

// Font rendering flags
#define D3DFONT_CENTERED    0x0001
#define D3DFONT_TWOSIDED    0x0002
#define D3DFONT_FILTERED    0x0004
#define D3DFONT_RIGHT       0x0008			// non standard feature
#define D3DFONT_SHADOW      0x0010			// non standard feature



//-----------------------------------------------------------------------------
// Name: class CD3DFont
// Desc: Texture-based font class for doing text in a 3D scene.
//-----------------------------------------------------------------------------
class CD3DFont
{
    TCHAR   m_strFontName[80];            // Font properties
    DWORD   m_dwFontHeight;
    DWORD   m_dwFontFlags;

    LPDIRECT3DDEVICE9       m_pd3dDevice; // A D3DDevice used for rendering
    LPDIRECT3DTEXTURE9      m_pTexture;   // The d3d texture for this font
    LPDIRECT3DVERTEXBUFFER9 m_pVB;        // VertexBuffer for rendering text
    DWORD   m_dwTexWidth;                 // Texture dimensions
    DWORD   m_dwTexHeight;
    FLOAT   m_fTextScale;
    FLOAT   m_fTexCoords[128-32][4];
    DWORD   m_dwSpacing;                  // Character pixel spacing per side

    // Stateblocks for setting and restoring render states
    LPDIRECT3DSTATEBLOCK9 m_pStateBlockSaved;
    LPDIRECT3DSTATEBLOCK9 m_pStateBlockDrawText;

public:
    // 2D and 3D text drawing functions
    HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor, 
                      const TCHAR* strText, DWORD dwFlags=0L );
    HRESULT DrawTextScaled( FLOAT x, FLOAT y, FLOAT z, 
                            FLOAT fXScale, FLOAT fYScale, DWORD dwColor, 
                            const TCHAR* strText, DWORD dwFlags=0L );
    HRESULT Render3DText( const TCHAR* strText, DWORD dwFlags=0L );
    
    // Function to get extent of text
    HRESULT GetTextExtent( const TCHAR* strText, SIZE* pSize );

    // Initializing and destroying device-dependent objects
    HRESULT InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice );
    HRESULT RestoreDeviceObjects();
    HRESULT InvalidateDeviceObjects();
    HRESULT DeleteDeviceObjects();

    // Constructor / destructor
    CD3DFont( const TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags=0L );
    ~CD3DFont();
};




#endif
d3dfont9.cpp

Code:
// -----------------------------------------------------------------------------
// File: D3DFont.cpp
// Desc: Texture-based font class
// Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
//
// Changes by Hans211
// - Added D3D_FONT_RIGHT
// - Stripped not needed functions
// -----------------------------------------------------------------------------
#include <stdio.h>
#include <tchar.h>
#include <D3DX9.h>
#include "D3DFont9.h"


//-----------------------------------------------------------------------------
// Custom vertex types for rendering text
//-----------------------------------------------------------------------------
#define MAX_NUM_VERTICES 50*6

struct FONT2DVERTEX { D3DXVECTOR4 p;   DWORD color;     FLOAT tu, tv; };
struct FONT3DVERTEX { D3DXVECTOR3 p;   D3DXVECTOR3 n;   FLOAT tu, tv; };

#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)

inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color,
                                      FLOAT tu, FLOAT tv )
{
    FONT2DVERTEX v;   v.p = p;   v.color = color;   v.tu = tu;   v.tv = tv;
    return v;
}

inline FONT3DVERTEX InitFont3DVertex( const D3DXVECTOR3& p, const D3DXVECTOR3& n,
                                      FLOAT tu, FLOAT tv )
{
    FONT3DVERTEX v;   v.p = p;   v.n = n;   v.tu = tu;   v.tv = tv;
    return v;
}




//-----------------------------------------------------------------------------
// Name: CD3DFont()
// Desc: Font class constructor
//-----------------------------------------------------------------------------
CD3DFont::CD3DFont( const TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags )
{
    _***ncpy( m_strFontName, strFontName, sizeof(m_strFontName) / sizeof(TCHAR) );
    m_strFontName[sizeof(m_strFontName) / sizeof(TCHAR) - 1] = _T('\0');
    m_dwFontHeight         = dwHeight;
    m_dwFontFlags          = dwFlags;
    m_dwSpacing            = 0;

    m_pd3dDevice           = NULL;
    m_pTexture             = NULL;
    m_pVB                  = NULL;

    m_pStateBlockSaved     = NULL;
    m_pStateBlockDrawText  = NULL;
}




//-----------------------------------------------------------------------------
// Name: ~CD3DFont()
// Desc: Font class destructor
//-----------------------------------------------------------------------------
CD3DFont::~CD3DFont()
{
    InvalidateDeviceObjects();
    DeleteDeviceObjects();
}




//-----------------------------------------------------------------------------
// Name: InitDeviceObjects()
// Desc: Initializes device-dependent objects, including the vertex buffer used
//       for rendering text and the texture map which stores the font image.
//-----------------------------------------------------------------------------
HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
{
    HRESULT hr;

    // Keep a local copy of the device
    m_pd3dDevice = pd3dDevice;

    // Establish the font and texture size
    m_fTextScale  = 1.0f; // Draw fonts into texture without scaling

    // Large fonts need larger textures
    if( m_dwFontHeight > 60 )
        m_dwTexWidth = m_dwTexHeight = 2048;
    else if( m_dwFontHeight > 30 )
        m_dwTexWidth = m_dwTexHeight = 1024;
    else if( m_dwFontHeight > 15 )
        m_dwTexWidth = m_dwTexHeight = 512;
    else
        m_dwTexWidth  = m_dwTexHeight = 256;

    // If requested texture is too big, use a smaller texture and smaller font,
    // and scale up when rendering.
    D3DCAPS9 d3dCaps;
    m_pd3dDevice->GetDeviceCaps( &d3dCaps );

    if( m_dwTexWidth > d3dCaps.MaxTextureWidth )
    {
        m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth;
        m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth;
    }

    // Create a new texture for the font
    hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1,
                                      0, D3DFMT_A4R4G4B4,
                                      D3DPOOL_MANAGED, &m_pTexture, NULL );
    if( FAILED(hr) )
        return hr;

    // Prepare to create a bitmap
    DWORD*      pBitmapBits;
    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;

    // Create a DC and a bitmap for the font
    HDC     hDC       = CreateCompatibleDC( NULL );
    HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
                                          (void**)&pBitmapBits, NULL, 0 );
    SetMapMode( hDC, MM_TEXT );

    // Create a font.  By specifying ANTIALIASED_QUALITY, we might get an
    // antialiased font, but this is not guaranteed.
    INT nHeight    = -MulDiv( m_dwFontHeight, 
        (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
    DWORD dwBold   = (m_dwFontFlags&D3DFONT_BOLD)   ? FW_BOLD : FW_NORMAL;
    DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE    : FALSE;
    HFONT hFont    = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic,
                          FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
                          CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
                          VARIABLE_PITCH, m_strFontName );
    if( NULL==hFont )
        return E_FAIL;

    SelectObject( hDC, hbmBitmap );
    SelectObject( hDC, hFont );

    // Set text properties
    SetTextColor( hDC, RGB(255,255,255) );
    SetBkColor(   hDC, 0x00000000 );
    SetTextAlign( hDC, TA_TOP );

    // Loop through all printable character and output them to the bitmap..
    // Meanwhile, keep track of the corresponding tex coords for each character.
    DWORD x = 0;
    DWORD y = 0;
    TCHAR str[2] = _T("x");
    SIZE size;

    // Calculate the spacing between characters based on line height
    GetTextExtentPoint32( hDC, TEXT(" "), 1, &size );
    x = m_dwSpacing = (DWORD) ceil(size.cy * 0.3f);

    for( TCHAR c=32; c<127; c++ )
    {
        str[0] = c;
        GetTextExtentPoint32( hDC, str, 1, &size );

        if( (DWORD)(x + size.cx + m_dwSpacing) > m_dwTexWidth )
        {
            x  = m_dwSpacing;
            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_dwSpacing))/m_dwTexWidth;
        m_fTexCoords[c-32][1] = ((FLOAT)(y + 0       + 0          ))/m_dwTexHeight;
        m_fTexCoords[c-32][2] = ((FLOAT)(x + size.cx + m_dwSpacing))/m_dwTexWidth;
        m_fTexCoords[c-32][3] = ((FLOAT)(y + size.cy + 0          ))/m_dwTexHeight;

        x += size.cx + (2 * m_dwSpacing);
    }

    // Lock the surface and write the alpha values for the set pixels
    D3DLOCKED_RECT d3dlr;
    m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
    BYTE* pDstRow = (BYTE*)d3dlr.pBits;
    WORD* pDst16;
    BYTE bAlpha; // 4-bit measure of pixel intensity

    for( y=0; y < m_dwTexHeight; y++ )
    {
        pDst16 = (WORD*)pDstRow;
        for( x=0; x < m_dwTexWidth; x++ )
        {
            bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
            if (bAlpha > 0)
            {
                *pDst16++ = (WORD) ((bAlpha << 12) | 0x0fff);
            }
            else
            {
                *pDst16++ = 0x0000;
            }
        }
        pDstRow += d3dlr.Pitch;
    }

    // Done updating texture, so clean up used objects
    m_pTexture->UnlockRect(0);
    DeleteObject( hbmBitmap );
    DeleteDC( hDC );
    DeleteObject( hFont );

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: RestoreDeviceObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DFont::RestoreDeviceObjects()
{
    HRESULT hr;

    // Create vertex buffer for the letters
    int vertexSize = max( sizeof(FONT2DVERTEX), sizeof(FONT3DVERTEX ) );
    if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( MAX_NUM_VERTICES * vertexSize,
                                                       D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
                                                       D3DPOOL_DEFAULT, &m_pVB, NULL ) ) )
    {
        return hr;
    }

    // Create the state blocks for rendering text
    for( UINT which=0; which<2; which++ )
    {
        m_pd3dDevice->BeginStateBlock();
        m_pd3dDevice->SetTexture( 0, m_pTexture );

        if ( D3DFONT_ZENABLE & m_dwFontFlags )
            m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
        else
            m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );

        m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
        m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,   D3DBLEND_SRCALPHA );
        m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,  D3DBLEND_INVSRCALPHA );
        m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE );
        m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF,         0x08 );
        m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC,  D3DCMP_GREATEREQUAL );
        m_pd3dDevice->SetRenderState( D3DRS_FILLMODE,   D3DFILL_SOLID );
        m_pd3dDevice->SetRenderState( D3DRS_CULLMODE,   D3DCULL_CCW );
        m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,    FALSE );
        m_pd3dDevice->SetRenderState( D3DRS_CLIPPING,         TRUE );
        m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE,  FALSE );
        m_pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND,      D3DVBF_DISABLE );
        m_pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
        m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,        FALSE );
        m_pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE,
            D3DCOLORWRITEENABLE_RED  | D3DCOLORWRITEENABLE_GREEN |
            D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA );
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
        m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE );
        m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE );

        if( which==0 )
            m_pd3dDevice->EndStateBlock( &m_pStateBlockSaved );
        else
            m_pd3dDevice->EndStateBlock( &m_pStateBlockDrawText );
    }

    return S_OK;
}


#define SAFE_RELEASE(p)	if (p)  { free(p); p=NULL; }

//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc: Destroys all device-dependent objects
//-----------------------------------------------------------------------------
HRESULT CD3DFont::InvalidateDeviceObjects()
{
    SAFE_RELEASE( m_pVB );
    SAFE_RELEASE( m_pStateBlockSaved );
    SAFE_RELEASE( m_pStateBlockDrawText );

    return S_OK;
}


//-----------------------------------------------------------------------------
// Name: DeleteDeviceObjects()
// Desc: Destroys all device-dependent objects
//-----------------------------------------------------------------------------
HRESULT CD3DFont::DeleteDeviceObjects()
{
    SAFE_RELEASE( m_pTexture );
    m_pd3dDevice = NULL;

    return S_OK;
}


//-----------------------------------------------------------------------------
// Name: GetTextExtent()
// Desc: Get the dimensions of a text string
//-----------------------------------------------------------------------------
HRESULT CD3DFont::GetTextExtent( const TCHAR* strText, SIZE* pSize )
{
    if( NULL==strText || NULL==pSize )
        return E_FAIL;

    FLOAT fRowWidth  = 0.0f;
    FLOAT fRowHeight = (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
    FLOAT fWidth     = 0.0f;
    FLOAT fHeight    = fRowHeight;

    while( *strText )
    {
        TCHAR c = *strText++;

        if( c == _T('\n') )
        {
            fRowWidth = 0.0f;
            fHeight  += fRowHeight;
        }

        if( (c-32) < 0 || (c-32) >= 128-32 )
            continue;

        FLOAT tx1 = m_fTexCoords[c-32][0];
        FLOAT tx2 = m_fTexCoords[c-32][2];

        fRowWidth += (tx2-tx1)*m_dwTexWidth - 2*m_dwSpacing;

        if( fRowWidth > fWidth )
            fWidth = fRowWidth;
    }

    pSize->cx = (int)fWidth;
    pSize->cy = (int)fHeight;

    return S_OK;
}


//-----------------------------------------------------------------------------
// Name: DrawText()
// Desc: Draws 2D text. Note that sx and sy are in pixels
//-----------------------------------------------------------------------------
HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
                            const TCHAR* strText, DWORD dwFlags )
{
    if( m_pd3dDevice == NULL )
        return E_FAIL;

    // Setup renderstate
    m_pStateBlockSaved->Capture();
    m_pStateBlockDrawText->Apply();
    m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX );
    m_pd3dDevice->SetPixelShader( NULL );
    m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );

    // Set filter states
    if( dwFlags & D3DFONT_FILTERED )
    {
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
        m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
    }

    if( dwFlags & D3DFONT_RIGHT ) {
        SIZE sz;
        GetTextExtent( strText, &sz );
        sx -= (FLOAT)sz.cx;
    } else if( dwFlags & D3DFONT_CENTERED ) {
        SIZE sz;
        GetTextExtent( strText, &sz );
        sx -= (FLOAT)sz.cx/2.0f;
    }

    // Adjust for character spacing
    sx -= m_dwSpacing;
    FLOAT fStartX = sx;

    // Fill vertex buffer
    FONT2DVERTEX* pVertices = NULL;
    DWORD         dwNumTriangles = 0;
    m_pVB->Lock( 0, 0, (void**)&pVertices, 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-32) < 0 || (c-32) >= 128-32 )
            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(' ') )
        {
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 );
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 );
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
            *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
            dwNumTriangles += 2;

            if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
            {
                // Unlock, render, and relock the vertex buffer
                m_pVB->Unlock();
                m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
                pVertices = NULL;
                m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
                dwNumTriangles = 0L;
            }
        }

        sx += w - (2 * m_dwSpacing);
    }

    // Unlock and render the vertex buffer
    m_pVB->Unlock();
    if( dwNumTriangles > 0 )
        m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );

    // Restore the modified renderstates
    m_pStateBlockSaved->Apply();

    return S_OK;
}
Edit: Just realized you solved the problem, maybe this will help somebody else /
HansD3DFont.rarattachment deleted · 20 downloads before removal
Well, considering the font class is from Microsoft, I doubt it's that o.o. Are you debugging the application? Check the stack around the error for anything gone wrong.
Quote Originally Posted by mmbob View Post
Well, considering the font class is from Microsoft, I doubt it's that o.o. Are you debugging the application? Check the stack around the error for anything gone wrong.
Noo, it was me and my fail programming abilities. <.<
Posts 1–15 of 16 · Page 1 of 2

Post a Reply

Similar Threads

Talk with us