Browse Source

use modified ver from french website, + my own mods

cxgeorge 24 years ago
parent
commit
1cbdcc2582
2 changed files with 538 additions and 222 deletions
  1. 487 213
      panda/src/dxgsg8/d3dfont8.cxx
  2. 51 9
      panda/src/dxgsg8/d3dfont8.h

+ 487 - 213
panda/src/dxgsg8/d3dfont8.cxx

@@ -2,9 +2,9 @@
 // File: D3DFont.cpp
 //
 // Desc: Texture-based font class
-//
+//       modified from a modified version of DXSDK CD3DFont from http://www.lafaqmfc.com/directx.htm
+//       Note that this is faster than ID3DXFont, which calls GDI in Draw()
 //-----------------------------------------------------------------------------
-
 #ifndef STRICT
 #define STRICT
 #endif
@@ -18,7 +18,6 @@
 //-----------------------------------------------------------------------------
 // Custom vertex types for rendering text
 //-----------------------------------------------------------------------------
-#define MAX_NUM_VERTICES 50*6
 
 struct FONT2DVERTEX {
     D3DXVECTOR4 p;   DWORD color;     FLOAT tu, tv;
@@ -27,9 +26,6 @@ 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;
@@ -55,8 +51,11 @@ CD3DFont::CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags ) {
     m_pTexture             = NULL;
     m_pVB                  = NULL;
 
-    m_dwSavedStateBlock    = 0L;
-    m_dwDrawTextStateBlock = 0L;
+    m_dwSavedStateBlock    = NULL;
+    m_dwDrawTextStateBlock = NULL;
+
+    ClearBeginEndData ( ) ; 
+    m_bBeginText = false ; 
 }
 
 //-----------------------------------------------------------------------------
@@ -82,32 +81,16 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
     // Establish the font and texture size
     m_fTextScale  = 1.0f; // Draw fonts into texture without scaling
 
-    // Large fonts need larger textures
+    // Large fonts need larger textures 
+    // We can be generous at this step, this is an estimate
     if(m_dwFontHeight > 40)
+        m_dwTexWidth = m_dwTexHeight = 2048;
+    else if(m_dwFontHeight > 32)
         m_dwTexWidth = m_dwTexHeight = 1024;
-    else if(m_dwFontHeight > 20)
+    else if(m_dwFontHeight > 16)
         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.
-    D3DCAPS8 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 );
-    if(FAILED(hr)) {
-        cout << "CD3DFONT CreateTexture failed!" << D3DERRORSTRING(hr);
-        return hr;
-    }
+        m_dwTexWidth = m_dwTexHeight = 256;
 
     // Prepare to create a bitmap
     DWORD*      pBitmapBits;
@@ -132,47 +115,183 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
                               (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,
+    HFONT hFont    = CreateFont( nHeight, 0, 0, 0, dwBold, 
+
+                                 FALSE ,   // dwItalic, // NO! We should not do that...
+                                    // See below comment about GetTextExtentPoint32
+
                                  FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
                                  CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
                                  VARIABLE_PITCH, m_strFontName );
     if(NULL==hFont) {
-        cout << "CD3DFONT CreateFont failed!\n";
+        cout << "CD3DFont InitDeviceObjects(): initial CreateFont failed!  GetLastError=" << GetLastError() << endl;
         return E_FAIL;
     }
 
-    SelectObject( hDC, hbmBitmap );
-    SelectObject( hDC, hFont );
+    HBITMAP hbmOld = ( HBITMAP ) SelectObject ( hDC, hbmBitmap );
+    HFONT   hfOld  = ( HFONT ) 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.
+    // First Loop through all printable characters 
+    // in order to determine the smallest necessary texture
     DWORD x = 0;
     DWORD y = 0;
     TCHAR str[2] = _T("x");
     SIZE size;
+    SIZE sizes [ 127 - 32 ] ;
 
     for(TCHAR c=32; c<127; c++) {
         str[0] = c;
-        GetTextExtentPoint32( hDC, str, 1, &size );
+        // GetTextExtentPoint32 does not care that the font is Italic or not, it will 
+        // return the same value. However, if we specify an Italic font, the output 
+        // on the bitmap will use more pixels. 
+        // If the font is Italic we have to output the standard character 
+        // and bend our vertices.
+        GetTextExtentPoint32 ( hDC, str, 1, & sizes [ c - 32 ] );
+    } ; 
+
+    static DWORD TexturesSizes [ 5 ] = { 128 , 256 , 512 , 1024 , 2048} ; 
+    DWORD dwTexSize = 0 ;  
+    for(DWORD iTex = 0 ; iTex < 5 ; ++ iTex) {
+        // fake the tex coord loop calculation 
+        x = 0 ; 
+        y = 0 ; 
+        for(TCHAR c=32; c<127; c++) {
+            if((DWORD)( x + sizes[ c - 32 ].cx+1) > TexturesSizes [ iTex ]) {
+                x  = 0;
+                y += sizes[ c - 32 ].cy+1;
+                // new y size 
+                if((DWORD) ( y + sizes[ 0 ].cy + 1 ) >= TexturesSizes [ iTex ]) {
+                    // does not fit, let's try a larger one 
+                    break ; 
+                }; 
+            }; 
+            x += sizes[ c - 32 ].cx + 2 ;
+        } ; 
+
+        if((DWORD) ( y + sizes[ 0 ].cy + 1 ) < TexturesSizes [ iTex ]) {
+            // Yahoo! it fits! 
+            dwTexSize = TexturesSizes [ iTex ] ; 
+            break ; 
+        }; 
+    } ; 
+
+    m_dwTexWidth = m_dwTexHeight = dwTexSize ;
+
+    // Select old objects ( added ) 
+    // Is this needed for compatible DCs? 
+    // The old handles are not not NULL, so it is done "by the book"
+    SelectObject ( hDC, hbmOld );
+    SelectObject ( hDC, hfOld );
+
+    // delete our gdi objects
+    DeleteObject( hbmBitmap );
+    DeleteObject( hFont );
+    DeleteDC( hDC );
+
+    // moved here to allow deletion of GDI objects 
+    if(dwTexSize == 0) {
+        cout << "CD3DFont InitDeviceObjects() error: Texture didnt fit, creation failed!\n";
+        return E_FAIL;
+    }
+
+    // Re-Create new GDI stuff with the optimal size 
+    // 
+    // Prepare to create a bitmap
+    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       = CreateCompatibleDC( NULL );
+    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.
+    nHeight  = -MulDiv( m_dwFontHeight, 
+                        (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
+    dwBold   = (m_dwFontFlags&D3DFONT_BOLD)   ? FW_BOLD : FW_NORMAL;
+    dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE    : FALSE;
+    hFont    = CreateFont( nHeight, 0, 0, 0, dwBold, 
+                           FALSE , // was dwItalic, // see above 
+                           FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
+                           CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
+                           VARIABLE_PITCH, m_strFontName );
+
+    if(NULL==hFont) {
+        cout << "CD3DFont InitDeviceObjects(): optimal CreateFont failed!  GetLastError=" << GetLastError() << endl;
+        return E_FAIL;
+    }
+
+    hbmOld = ( HBITMAP ) SelectObject ( hDC, hbmBitmap );
+    hfOld  = ( HFONT ) SelectObject ( hDC, hFont );
+
+    // Set text properties
+    SetTextColor( hDC, RGB(255,255,255) );
+    SetBkColor(   hDC, 0x00000000 );
+    SetTextAlign( hDC, TA_TOP );
+
+    // If requested texture is too big, use a smaller texture and smaller font,
+    // and scale up when rendering.
+    D3DCAPS8 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 );
+    if(FAILED(hr)) {
+        SelectObject ( hDC, hbmOld );
+        SelectObject ( hDC, hfOld );
+
+        DeleteObject( hbmBitmap );
+        DeleteObject( hFont );
+        DeleteDC( hDC );
+
+        cout << "CD3DFont InitDeviceObjs CreateTexture failed!" << D3DERRORSTRING(hr);
+        return hr;
+    }; 
+
+    // Loop through all printable character and output them to the bitmap..
+    // Meanwhile, keep track of the corresponding tex coords for each character.
+    x = 0 ; 
+    y = 0 ; 
+
+    for(TCHAR c=32; c<127; c++) {
+        str[0] = c;
+        GetTextExtentPoint32( hDC, str, 1, &size );
         if((DWORD)(x+size.cx+1) > m_dwTexWidth) {
             x  = 0;
             y += size.cy+1;
         }
 
-        ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL );
+        // We need one pixel on both sides 
 
-        m_fTexCoords[c-32][0] = ((FLOAT)(x+0))/m_dwTexWidth;
-        m_fTexCoords[c-32][1] = ((FLOAT)(y+0))/m_dwTexHeight;
-        m_fTexCoords[c-32][2] = ((FLOAT)(x+0+size.cx))/m_dwTexWidth;
-        m_fTexCoords[c-32][3] = ((FLOAT)(y+0+size.cy))/m_dwTexHeight;
+        // plus one here for one pixel on the left
+        ExtTextOut( hDC, x + 1, y, ETO_OPAQUE, NULL, str, 1, NULL );
 
-        x += size.cx+1;
+        m_fTexCoords[c-32][0] = ( (FLOAT) x + 0.5f ) / m_dwTexWidth ;
+        m_fTexCoords[c-32][1] = ( (FLOAT) y + 0.5f ) / m_dwTexHeight ;
+        m_fTexCoords[c-32][2] = ( (FLOAT) x + 0.5f + size.cx ) / m_dwTexWidth;
+        m_fTexCoords[c-32][3] = ( (FLOAT) y + 0.5f + size.cy ) / m_dwTexHeight;
+
+        // plus two here because we also need one more pixel on the right side
+        x += size.cx + 2 ;
     }
 
     // Lock the surface and write the alpha values for the set pixels
@@ -197,9 +316,13 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
 
     // Done updating texture, so clean up used objects
     m_pTexture->UnlockRect(0);
+
+    SelectObject ( hDC, hbmOld );
+    SelectObject ( hDC, hfOld );
+
     DeleteObject( hbmBitmap );
-    DeleteDC( hDC );
     DeleteObject( hFont );
+    DeleteDC( hDC );
 
     return RestoreDeviceObjects();
 }
@@ -208,14 +331,17 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
 // Name: RestoreDeviceObjects()
 // Desc:
 //-----------------------------------------------------------------------------
-HRESULT CD3DFont::RestoreDeviceObjects(void) {
+HRESULT CD3DFont::RestoreDeviceObjects() {
     HRESULT hr;
 
     // Create vertex buffer for the letters
-    if(FAILED( hr = m_pd3dDevice->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
-                                                      D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
-                                                      D3DPOOL_DEFAULT, &m_pVB ) )) {
-        cout << "CD3DFONT::RestoreDevObjs() CreateVB failed!" << D3DERRORSTRING(hr);
+    if(FAILED( hr = m_pd3dDevice->CreateVertexBuffer(
+            // can be rendered 3d 
+                                                    MAX_NUM_VERTICES*sizeof(FONT3DVERTEX /*FONT2DVERTEX */ ),
+                                                    D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
+                                                    D3DPOOL_DEFAULT,  // D3DUSAGE_DYNAMIC makes D3DPOOL_MANAGED impossible
+                                                    &m_pVB ) )) {
+        cout << "CD3DFont CreateVB failed!" << D3DERRORSTRING(hr);
         return hr;
     }
 
@@ -268,17 +394,22 @@ HRESULT CD3DFont::RestoreDeviceObjects(void) {
 }
 
 
-
-
 //-----------------------------------------------------------------------------
 // Name: InvalidateDeviceObjects()
 // Desc: Destroys all device-dependent objects
 //-----------------------------------------------------------------------------
 HRESULT CD3DFont::InvalidateDeviceObjects() {
+    #ifdef _DEBUG
+    if(m_pVB) {
+        cout << "XXXX Releasing Font VertexBuffer\n";
+    }
+    #endif
+
     SAFE_RELEASE( m_pVB );
 
     // Delete the state blocks
-    if(IS_VALID_PTR(m_pd3dDevice)) {
+    if(m_pd3dDevice) {
+        assert(IS_VALID_PTR(m_pd3dDevice));
         if(m_dwSavedStateBlock)
             m_pd3dDevice->DeleteStateBlock( m_dwSavedStateBlock );
         if(m_dwDrawTextStateBlock)
@@ -292,13 +423,12 @@ HRESULT CD3DFont::InvalidateDeviceObjects() {
 }
 
 
-
-
 //-----------------------------------------------------------------------------
 // Name: DeleteDeviceObjects()
 // Desc: Destroys all device-dependent objects
 //-----------------------------------------------------------------------------
 HRESULT CD3DFont::DeleteDeviceObjects() {
+    InvalidateDeviceObjects();
     SAFE_RELEASE( m_pTexture );
     m_pd3dDevice = NULL;
 
@@ -306,8 +436,6 @@ HRESULT CD3DFont::DeleteDeviceObjects() {
 }
 
 
-
-
 //-----------------------------------------------------------------------------
 // Name: GetTextExtent()
 // Desc: Get the dimensions of a text string
@@ -346,9 +474,6 @@ HRESULT CD3DFont::GetTextExtent( TCHAR* strText, SIZE* pSize ) {
     return S_OK;
 }
 
-
-
-
 //-----------------------------------------------------------------------------
 // Name: DrawTextScaled()
 // Desc: Draws scaled 2D text.  Note that x and y are in viewport coordinates
@@ -363,158 +488,297 @@ HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
     if(m_pd3dDevice == NULL)
         return E_FAIL;
 
-    // Set up renderstate
-    m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock );
-    m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
-    m_pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX );
-    m_pd3dDevice->SetPixelShader( NULL );
-    m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT2DVERTEX) );
-
-    // Set filter states
-    if(dwFlags & D3DFONT_FILTERED) {
-        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
-        m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
-    }
-
-    D3DVIEWPORT8 vp;
-    m_pd3dDevice->GetViewport( &vp );
-    FLOAT sx  = (x+1.0f)*vp.Width/2;
-    FLOAT sy  = (y+1.0f)*vp.Height/2;
-    FLOAT sz  = z;
-    FLOAT rhw = 1.0f;
-    FLOAT fStartX = sx;
-
-    FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight;
-
-    // Fill vertex buffer
-    FONT2DVERTEX* pVertices;
-    DWORD         dwNumTriangles = 0L;
-    m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
-
-    while(*strText) {
-        TCHAR c = *strText++;
+    HRESULT hr ; 
+    if(m_bBeginText) {
+        hr = DeferedDrawTextScaled ( x, y, z, fXScale, fYScale, dwColor, strText, dwFlags ) ; 
+    } else {
+        BeginText ( ) ; 
+        hr = DeferedDrawTextScaled ( x, y, z, fXScale, fYScale, dwColor, strText, dwFlags ) ; 
+        if(! FAILED ( hr ))
+            EndText ( ) ;
+    } ; 
+
+    return hr ;
+}
 
-        if(c == _T('\n')) {
-            sx  = fStartX;
-            sy += fYScale*vp.Height;
-        }
-        if(c < _T(' '))
-            continue;
+//-----------------------------------------------------------------------------
+// Name: DrawText()
+// Desc: Draws 2D text
+//-----------------------------------------------------------------------------
+HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
+                            TCHAR* strText, DWORD dwFlags ) {
+    if(m_pd3dDevice == NULL)
+        return E_FAIL;
 
-        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];
+    HRESULT hr ; 
+    if(m_bBeginText) {
+        hr = DeferedDrawText ( sx, sy, dwColor, strText, dwFlags ) ; 
+    } else {
+        BeginText(); 
+        hr = DeferedDrawText ( sx, sy, dwColor, strText, dwFlags ) ; 
+        if(! FAILED ( hr ))
+            EndText ( ) ;
+    } ; 
+
+    return hr ;
+}
 
-        FLOAT w = (tx2-tx1)*m_dwTexWidth;
-        FLOAT h = (ty2-ty1)*m_dwTexHeight;
 
-        w *= (fXScale*vp.Width)/fLineHeight;
-        h *= (fYScale*vp.Height)/fLineHeight;
+void CD3DFont::ClearBeginEndData ( void ) {
+    m_nDeferedCalls = 0 ; 
+    m_TextBuffer [ 0 ] = 0 ; 
+    m_pTextBuffer = & m_TextBuffer [ 0 ] ; 
+} 
+
+HRESULT CD3DFont::BeginText ( void ) {
+    m_bBeginText = true ; 
+    ClearBeginEndData() ; 
+
+    return S_OK ; 
+} 
+
+HRESULT CD3DFont::DeferedDrawTextScaled
+( FLOAT x, FLOAT y, FLOAT z, 
+  FLOAT fXScale, FLOAT fYScale, DWORD dwColor, 
+  TCHAR* strText, DWORD dwFlags ) {
+    return 
+    DeferedDraw ( true , x, y, z, fXScale, fYScale, dwColor, strText, dwFlags ) ; 
+} 
+
+HRESULT CD3DFont::DeferedDrawText
+( FLOAT x, FLOAT y, DWORD dwColor, 
+  TCHAR* strText, DWORD dwFlags ) {
+    return 
+    DeferedDraw ( false , x, y, 0.0f , 0.0f , 0.0f , dwColor, strText, dwFlags ) ; 
+} 
+
+HRESULT CD3DFont::DeferedDraw
+( bool bScaled , 
+  FLOAT x, FLOAT y, FLOAT z, 
+  FLOAT fXScale, FLOAT fYScale, DWORD dwColor, 
+  TCHAR* strText, DWORD dwFlags ) {
+    if(m_nDeferedCalls >= MaxCalls) {
+        cout << "CD3DFont DeferedDraw() error, MaxCalls exceeded!\n";
+        return E_FAIL ;
+    }
 
-        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;
+    // we need to make a deep copy of the string 
+    // the user object might have fallen out of scope
+    // when it will be time to render 
+    int nStrLen = strlen ( strText ) + 1 ; 
+    int nUsed = m_pTextBuffer - & m_pTextBuffer [ 0 ] ; 
+    if(nUsed + nStrLen > TextBufferLength) {
+        cout << "CD3DFont DeferedDraw() error, TextBufferLength exceeded!\n";
+        return E_FAIL ;
+    }
 
-            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, (BYTE**)&pVertices, D3DLOCK_DISCARD );
-                dwNumTriangles = 0L;
-            }
-        }
+    strcpy ( m_pTextBuffer , strText ) ; 
+    m_DTArgs [ m_nDeferedCalls ].m_strText = m_pTextBuffer ; 
+    m_pTextBuffer += nStrLen ; 
 
-        sx += w;
-    }
+    m_DTArgs [ m_nDeferedCalls ].m_bScaled = bScaled ; 
+    m_DTArgs [ m_nDeferedCalls ].m_x = x ; 
+    m_DTArgs [ m_nDeferedCalls ].m_y = y ; 
+    m_DTArgs [ m_nDeferedCalls ].m_z = z ; 
+    m_DTArgs [ m_nDeferedCalls ].m_fXScale = fXScale ; 
+    m_DTArgs [ m_nDeferedCalls ].m_fYScale = fYScale ; 
+    m_DTArgs [ m_nDeferedCalls ].m_dwColor = dwColor ; 
+    m_DTArgs [ m_nDeferedCalls ].m_dwFlags = dwFlags ; 
 
-    // Unlock and render the vertex buffer
-    m_pVB->Unlock();
-    if(dwNumTriangles > 0)
-        m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
+    m_nDeferedCalls ++ ; 
 
-    // Restore the modified renderstates
-    m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock );
+    return S_OK ; 
+} 
 
-    return S_OK;
-}
+HRESULT CD3DFont::EndText ( void ) {
+    if(m_pd3dDevice == NULL)
+        return E_FAIL;
+    HRESULT hr;
 
+    assert(IS_VALID_PTR(m_pVB));
 
+    DWORD hSavedVertexShader,hSavedPixelShader;
+    UINT SavedStreamStride;
+    IDirect3DVertexBuffer8 *pSavedStreamData=NULL;
 
+    hr = m_pd3dDevice->GetVertexShader(&hSavedVertexShader);
+    hr = m_pd3dDevice->GetPixelShader(&hSavedPixelShader);
 
-//-----------------------------------------------------------------------------
-// Name: DrawText()
-// Desc: Draws 2D text
-//-----------------------------------------------------------------------------
-HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
-                            TCHAR* strText, DWORD dwFlags ) {
-    if(m_pd3dDevice == NULL)
+    // Set up renderstate
+    hr = m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock );
+    hr = m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
+    if(hSavedVertexShader!=D3DFVF_FONT2DVERTEX)
+        hr = m_pd3dDevice->SetVertexShader(D3DFVF_FONT2DVERTEX);
+    if(hSavedPixelShader!=NULL)
+        hr = m_pd3dDevice->SetPixelShader(NULL);
+
+    hr = m_pd3dDevice->GetStreamSource(0,&pSavedStreamData,&SavedStreamStride);
+    if(FAILED(hr)) {
+        cout << "CD3DFont EndText GetStreamSource() failed!" << D3DERRORSTRING(hr);
         return E_FAIL;
+    }
 
-    // Setup renderstate
-    m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock );
-    m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
-    m_pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX );
-    m_pd3dDevice->SetPixelShader( NULL );
-    m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT2DVERTEX) );
+    if((pSavedStreamData!=m_pVB)||(SavedStreamStride!=sizeof(FONT2DVERTEX))) {
+        hr = m_pd3dDevice->SetStreamSource(0,m_pVB,sizeof(FONT2DVERTEX));
+        if(FAILED(hr)) {
+            cout << "CD3DFont EndText initial SetStreamSource() failed!" << D3DERRORSTRING(hr);
+            return E_FAIL;
+        }
+    }
 
     // Set filter states
-    if(dwFlags & D3DFONT_FILTERED) {
+    //
+    // filter if any in our list is specified filtered 
+    //
+    // This functionality is different from the original D3DFont 
+    // but is a significant speed increase
+    //
+    // User will make another batch if necessary
+    //  
+    bool bFiltered = false ; 
+    for(UINT i = 0 ; i < m_nDeferedCalls ; ++ i) {
+        DWORD   dwFlags = m_DTArgs [ i ].m_dwFlags ; 
+        if(dwFlags & D3DFONT_FILTERED) {
+            bFiltered = true ; 
+            break ; 
+        }
+    } ; 
+    if(bFiltered) {
         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
-    }
+    }; 
 
-    FLOAT fStartX = sx;
+    // useless if nothing is scaled but should be fast enough 
+    D3DVIEWPORT8 vp;
+    m_pd3dDevice->GetViewport( &vp );
+    FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight;
 
     // Fill vertex buffer
-    FONT2DVERTEX* pVertices = NULL;
-    DWORD         dwNumTriangles = 0;
+    FONT2DVERTEX* pVertices;
+    DWORD         dwNumTriangles = 0L;
     m_pVB->Lock( 0, 0, (BYTE**)&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 < _T(' '))
-            continue;
-
-        FLOAT tx1 = m_fTexCoords[c-32][0];
-        FLOAT ty1 = m_fTexCoords[c-32][1];
-        FLOAT tx2 = m_fTexCoords[c-32][2];
-        FLOAT ty2 = m_fTexCoords[c-32][3];
-
-        FLOAT w = (tx2-tx1) *  m_dwTexWidth / m_fTextScale;
-        FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale;
-
-        if(c != _T(' ')) {
-            *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, (BYTE**)&pVertices, D3DLOCK_DISCARD );
-                dwNumTriangles = 0L;
-            }
-        }
-
-        sx += w;
-    }
+    bool bItalic = 0 != ( m_dwFontFlags & D3DFONT_ITALIC ) ; 
+    // loop on our batched sets of arguments 
+    for(UINT i = 0 ; i < m_nDeferedCalls ; ++ i) {
+        bool    bScaled = m_DTArgs [ i ].m_bScaled ; 
+        FLOAT   x       = m_DTArgs [ i ].m_x       ; 
+        FLOAT   y       = m_DTArgs [ i ].m_y       ; 
+        FLOAT   z       = m_DTArgs [ i ].m_z       ; 
+        FLOAT   fXScale = m_DTArgs [ i ].m_fXScale ; 
+        FLOAT   fYScale = m_DTArgs [ i ].m_fYScale ; 
+        DWORD   dwColor = m_DTArgs [ i ].m_dwColor ; 
+        TCHAR * strText = m_DTArgs [ i ].m_strText ; 
+
+        if(bScaled) {
+
+            FLOAT sx  = (x+1.0f)*vp.Width/2;
+            FLOAT sy  = (y-1.0f)*vp.Height/2;
+            FLOAT sz  = z;
+            FLOAT rhw = 1.0f;
+            FLOAT fStartX = sx;
+
+            FLOAT fBend = 0.0f ; 
+            if(bItalic)
+                fBend = fYScale*vp.Height / 4.0f ;
+
+            while(*strText) {
+                TCHAR c = *strText++;
+
+                if(c == _T('\n')) {
+                    sx  = fStartX;
+                    sy += fYScale*vp.Height;
+                }
+                if(c < _T(' '))
+                    continue;
+
+                FLOAT tx1 = m_fTexCoords[c-32][0];
+                FLOAT ty1 = m_fTexCoords[c-32][1];
+                FLOAT tx2 = m_fTexCoords[c-32][2];
+                FLOAT ty2 = m_fTexCoords[c-32][3];
+
+                FLOAT w = (tx2-tx1)*m_dwTexWidth;
+                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 + fBend,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 + fBend,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 + fBend,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, (BYTE**)&pVertices, D3DLOCK_DISCARD );
+                        dwNumTriangles = 0L;
+                    }
+                }
+
+                sx += w;
+            } ; 
+        } else {  // not scaled 
+            FLOAT fBend = 0.0f ; 
+            if(bItalic)
+                fBend = fLineHeight / 4.0f ;
+
+            // Lazy guy...
+            FLOAT sx = x ; 
+            FLOAT sy = y ; 
+
+            FLOAT fStartX = sx;
+            while(*strText) {
+                TCHAR c = *strText++;
+
+                if(c == _T('\n')) {
+                    sx = fStartX ;
+                    sy += fLineHeight ;
+                }
+                if(c < _T(' '))
+                    continue;
+
+                FLOAT tx1 = m_fTexCoords[c-32][0];
+                FLOAT ty1 = m_fTexCoords[c-32][1];
+                FLOAT tx2 = m_fTexCoords[c-32][2];
+                FLOAT ty2 = m_fTexCoords[c-32][3];
+
+                FLOAT w = (tx2-tx1) *  m_dwTexWidth / m_fTextScale;
+                FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale;
+
+                if(c != _T(' ')) {
+                    *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 + fBend,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 + fBend,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 + fBend,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, (BYTE**)&pVertices, D3DLOCK_DISCARD );
+                        dwNumTriangles = 0L;
+                    }
+                };  // endif not blank 
+
+                sx += w;
+            } ; // end while 
+
+        } ; // end if else scaled 
+
+    } ; // end for 
+
+    m_bBeginText = false ; 
+    ClearBeginEndData ( ) ; 
 
     // Unlock and render the vertex buffer
     m_pVB->Unlock();
@@ -523,20 +787,31 @@ HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
 
     // Restore the modified renderstates
     m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock );
+    if((hSavedVertexShader!=NULL) && (hSavedVertexShader!=D3DFVF_FONT2DVERTEX))
+        m_pd3dDevice->SetVertexShader(hSavedVertexShader);
+    if(hSavedPixelShader!=NULL)
+        m_pd3dDevice->SetPixelShader(hSavedPixelShader);
+
+    if(IS_VALID_PTR(pSavedStreamData) && ((pSavedStreamData!=m_pVB)||(SavedStreamStride!=sizeof(FONT2DVERTEX)))) {
+        hr = m_pd3dDevice->SetStreamSource(0,pSavedStreamData,SavedStreamStride);
+        if(FAILED(hr)) {
+            cout << "CD3DFont EndText restore SetStreamSource() failed!" << D3DERRORSTRING(hr);
+            return E_FAIL;
+        }
+        pSavedStreamData->Release();
+    }
 
     return S_OK;
-}
-
-
-/*
+} 
 
+#if 0
+// dont need this now
 //-----------------------------------------------------------------------------
 // Name: Render3DText()
 // Desc: Renders 3D text
 //-----------------------------------------------------------------------------
-HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
-{
-    if( m_pd3dDevice == NULL )
+HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags ) {
+    if(m_pd3dDevice == NULL)
         return E_FAIL;
 
     // Setup renderstate
@@ -547,8 +822,7 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
     m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT3DVERTEX) );
 
     // Set filter states
-    if( dwFlags & D3DFONT_FILTERED )
-    {
+    if(dwFlags & D3DFONT_FILTERED) {
         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
     }
@@ -558,8 +832,7 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
     FLOAT y = 0.0f;
 
     // Center the text block at the origin
-    if( dwFlags & D3DFONT_CENTERED )
-    {
+    if(dwFlags & D3DFONT_CENTERED) {
         SIZE sz;
         GetTextExtent( strText, &sz );
         x = -(((FLOAT)sz.cx)/10.0f)/2.0f;
@@ -567,7 +840,7 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
     }
 
     // Turn off culling for two-sided text
-    if( dwFlags & D3DFONT_TWOSIDED )
+    if(dwFlags & D3DFONT_TWOSIDED)
         m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
 
     FLOAT fStartX = x;
@@ -575,18 +848,21 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
 
     // Fill vertex buffer
     FONT3DVERTEX* pVertices;
-    DWORD         dwVertex       = 0L;
+    // DWORD         dwVertex       = 0L; // not ref'ed
     DWORD         dwNumTriangles = 0L;
     m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
 
-    while( c = *strText++ )
-    {
-        if( c == '\n' )
-        {
+    bool bItalic = 0 != ( m_dwFontFlags & D3DFONT_ITALIC ) ; 
+    FLOAT fBend = 0.0f ; 
+    if(bItalic)
+        fBend = ( ( m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f ) / 4.0f ;
+
+    while(c = *strText++) {
+        if(c == '\n') {
             x = fStartX;
             y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f;
         }
-        if( c < 32 )
+        if(c < 32)
             continue;
 
         FLOAT tx1 = m_fTexCoords[c-32][0];
@@ -597,18 +873,16 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
         FLOAT w = (tx2-tx1) * m_dwTexWidth  / ( 10.0f * m_fTextScale );
         FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale );
 
-        if( c != _T(' ') )
-        {
+        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+0 + fBend ,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 + fBend ,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 );
+            *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0 + fBend ,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
             dwNumTriangles += 2;
 
-            if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
-            {
+            if(dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) {
                 // Unlock, render, and relock the vertex buffer
                 m_pVB->Unlock();
                 m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
@@ -622,7 +896,7 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
 
     // Unlock and render the vertex buffer
     m_pVB->Unlock();
-    if( dwNumTriangles > 0 )
+    if(dwNumTriangles > 0)
         m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
 
     // Restore the modified renderstates
@@ -630,4 +904,4 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
 
     return S_OK;
 }
-*/
+#endif

+ 51 - 9
panda/src/dxgsg8/d3dfont8.h

@@ -1,13 +1,14 @@
-//-----------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------
 // File: D3DFont.h
 //
 // Desc: Texture-based font class
-//-----------------------------------------------------------------------------
+//       based on a modified version of DXSDK CD3DFont from http://www.lafaqmfc.com/directx.htm
+//       Note that this is faster than ID3DXFont, which calls GDI in Draw()
+//---------------------------------------------------------------------------------------------
 #ifndef D3DFONT_H
 #define D3DFONT_H
 #include <tchar.h>
-#include <D3D8.h>
-
+#include <d3d8.h>
 
 // Font creation flags
 #define D3DFONT_BOLD        0x0001
@@ -19,13 +20,21 @@
 #define D3DFONT_TWOSIDED    0x0002
 #define D3DFONT_FILTERED    0x0004
 
-
 //-----------------------------------------------------------------------------
 // Name: class CD3DFont
 // Desc: Texture-based font class for doing text in a 3D scene.
 //-----------------------------------------------------------------------------
 class CD3DFont
 {
+    enum 
+    { 
+        D3DFVF_FONT2DVERTEX = (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) , 
+        D3DFVF_FONT3DVERTEX = (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1) , 
+        TextBufferLength = 1024 , 
+        MAX_NUM_VERTICES = TextBufferLength * 6 , 
+        MaxCalls = 30 
+    } ; 
+
     TCHAR   m_strFontName[80];            // Font properties
     DWORD   m_dwFontHeight;
     DWORD   m_dwFontFlags;
@@ -42,20 +51,53 @@ class CD3DFont
     DWORD   m_dwSavedStateBlock;
     DWORD   m_dwDrawTextStateBlock;
 
+    struct DrawTextArgs 
+    {
+        bool  m_bScaled ; 
+        FLOAT m_x ;  FLOAT m_y ;  FLOAT m_z ; 
+        FLOAT m_fXScale ; FLOAT m_fYScale ; 
+        DWORD m_dwColor ;  
+        TCHAR *m_strText ; 
+        DWORD m_dwFlags ; 
+    } ; 
+
+    DrawTextArgs m_DTArgs [ MaxCalls ] ; 
+    char    m_TextBuffer  [ TextBufferLength ] ; 
+    char   *m_pTextBuffer ; 
+    UINT    m_nDeferedCalls ;
+    bool    m_bBeginText ; 
+    inline  HRESULT DeferedDrawText( FLOAT x, FLOAT y, DWORD dwColor, 
+                      TCHAR* strText, DWORD dwFlags=0L );
+    inline  HRESULT DeferedDrawTextScaled ( FLOAT x, FLOAT y, FLOAT z, 
+                            FLOAT fXScale, FLOAT fYScale, DWORD dwColor, 
+                            TCHAR* strText, DWORD dwFlags=0L ) ; 
+    inline  HRESULT DeferedDraw
+            ( bool bScaled , 
+              FLOAT x, FLOAT y, FLOAT z, 
+              FLOAT fXScale, FLOAT fYScale, DWORD dwColor, 
+              TCHAR* strText, DWORD dwFlags ) ; 
+
+    inline  void ClearBeginEndData (void ) ; 
+
+
 public:
     // 2D and 3D text drawing functions
+    HRESULT BeginText ( void ) ;
+    HRESULT EndText ( void ) ;
+
     HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor, 
                       TCHAR* strText, DWORD dwFlags=0L );
-    HRESULT DrawTextScaled( FLOAT x, FLOAT y, FLOAT z, 
+    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 );
+                            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( LPDIRECT3DDEVICE8 pd3dDevice );
+    HRESULT InitDeviceObjects(LPDIRECT3DDEVICE8 pd3dDevice);
     HRESULT RestoreDeviceObjects(void);
     HRESULT InvalidateDeviceObjects(void);
     HRESULT DeleteDeviceObjects(void);