Archived

This topic is now archived and is closed to further replies.

eagleboy

Font engine

Recommended Posts

Hi, I''m in the process of determining the best way of implementing a font engine (and subsequently a console). My main requirement is that it be fast. The fonts themselves will be implemented with a font map. I have considering rendering to a surface and then rendering the surface over the scene. I''m concerned that this is less than optimal in terms of speed. Another option I believe, is rendering the characters as quads with D3D. I have no idea how to do this. How is this done? Anyone suggest a better way? Or shed light on the best way to implement these methods? eb.

Share this post


Link to post
Share on other sites
D3DFont, and Laurent''s version of it (search for D3DFont).

Also, GetTextExtentPoint32 in D3DFont should be replaced with GetCharABCWidthsFloat, which handles italics and TrueType fonts correctly.

Share this post


Link to post
Share on other sites
G''day!

The full source for a font engine is here:
http://www.drunkenhyena.com/docs/dhFastFont.phtml

It uses pre-created bitmap fonts, and it''s pretty fast. Free to use and abuse too.

Stay Casual,

Ken
Drunken Hyena

Share this post


Link to post
Share on other sites
My font class from my GUI code


  

// GUIFont.h: interface for the CGUIFont class.

//

//////////////////////////////////////////////////////////////////////


#if !defined(AFX_GUIFONT_H__97489361_14F4_11D6_8113_00A0CC7AF849__INCLUDED_)
#define AFX_GUIFONT_H__97489361_14F4_11D6_8113_00A0CC7AF849__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


#include "dxdraw.h"

class CGUIFont
{
public:
void ChangeTextColor(COLORREF new_color);
int GetTextWidth(char* text);

void DrawText(LPDIRECTDRAWSURFACE7 surf, char* text, int x, int y, bool p_bTransparent=true);

void CalcRectSurfDim(int RowHeight, int* p_pRows, SIZE* p_pSurfSize);
void Destroy();
CGUIFont(CDxDraw* pDxDraw, COLORREF color, char* psTypeFace, int iHeight);
virtual ~CGUIFont();
COLORREF GetTextColor() { return m_tTextColor; }
int GetTextHeight(char *text);

private:
bool Create(char* psTypeFace, int iHeight);
LPDIRECTDRAWSURFACE7 m_tDDSurf;
SIZE m_szSurfDim;
CDxDraw* m_ptDxDraw;
SIZE m_aCharSize[256];
POINT m_aCharPos[256];
int m_iNumRows;
COLORREF m_tTextColor;
};

#endif // !defined(AFX_GUIFONT_H__97489361_14F4_11D6_8113_00A0CC7AF849__INCLUDED_)



// GUIFont.cpp: implementation of the CGUIFont class.

//

//////////////////////////////////////////////////////////////////////


#include <windows.h>
#include "GUIFont.h"
#include "globaldef.h"

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////


CGUIFont::CGUIFont(CDxDraw* pDxDraw, COLORREF p_tTextColor, char* psTypeFace, int iHeight)
{
m_iNumRows = 0;
m_ptDxDraw = pDxDraw;
m_tTextColor = p_tTextColor;
memset(m_aCharSize, 0, 256);
Create(psTypeFace, iHeight);
}

CGUIFont::~CGUIFont()
{
Destroy();
}

void CGUIFont::Destroy()
{
if(m_tDDSurf)
{
m_tDDSurf->Release();
m_tDDSurf = NULL;
}

}

void CGUIFont::DrawText(LPDIRECTDRAWSURFACE7 surf, char *text, int x, int y, bool p_bTransparent)
{
int sx=0, sy=0, dx=0, dy=0, sprite_width=m_szSurfDim.cx, sprite_height=m_szSurfDim.cy;
int xinc=0, yinc=0;

for(int i=0; i<strlen(text); i++)
{
unsigned char character = (unsigned char) text[i];

sx = m_aCharPos[character].x;
sy = m_aCharPos[character].y;

dx = x+xinc;
dy = y+yinc;

sprite_width = m_aCharSize[character].cx;
sprite_height = m_aCharSize[character].cy;

m_ptDxDraw->Blit(m_tDDSurf, surf, dx, dy, sx, sy, sprite_width, sprite_height, p_bTransparent);

xinc += (sprite_width);
}
}

bool CGUIFont::Create(char* psTypeFace, int iHeight)
{
SIZE l_szBiggestChar = {0,0};

HDC l_thDCScreen = GetDC(NULL);

HFONT hFont = CreateFont(
-iHeight, //int nHeight, // logical height of font

0, //int nWidth, // logical average

0, //int nEscapement, // angle of escapement

0, //int nOrientation, // base-line orientation angle

FW_NORMAL, //int fnWeight, // font weight

0, //DWORD fdwItalic, // italic attribute flag

0, //DWORD fdwUnderline, // underline attribute flag

0, //DWORD fdwStrikeOut, // strikeout attribute flag

DEFAULT_CHARSET, //DWORD fdwCharSet, // character set identifier

0, //DWORD fdwOutputPrecision, // output precision

CLIP_DEFAULT_PRECIS, //DWORD fdwClipPrecision, // clipping precision

0, //DWORD fdwQuality, // output quality

0, //DWORD fdwPitchAndFamily, // pitch and family

psTypeFace// LPCTSTR lpszFace // pointer to typeface name string

);

SelectObject(l_thDCScreen, (HFONT) hFont);
SelectObject (l_thDCScreen, hFont) ;

RECT l_rcFormatDim = {0,0,1000,1000};

SetMapMode(l_thDCScreen, MM_TEXT);

// Registrera storleken på alla tecken samt det största tecknet.

char buffer[1];
for(int i=0; i<256; i++)
{
buffer[0] = (unsigned char) i;

if(!GetTextExtentPoint32(l_thDCScreen, buffer, 1, &m_aCharSize[i]))
show("failed to find font dimension");

if(m_aCharSize[i].cy > l_szBiggestChar.cy)
l_szBiggestChar.cy = m_aCharSize[i].cy;
if(m_aCharSize[i].cx > l_szBiggestChar.cx)
l_szBiggestChar.cx = m_aCharSize[i].cx;
}

ReleaseDC(NULL, l_thDCScreen);

// Calculate surface dimension

CalcRectSurfDim(l_szBiggestChar.cy, &m_iNumRows, &m_szSurfDim);

// Lägg på lite extra så alla bokstäver verkligen syns...

m_szSurfDim.cx+=30;
m_szSurfDim.cy+=30;

// Crate surface with transparent color (RGB(255,0,255))

if(m_ptDxDraw->CreateOffScreenSurf(&m_tDDSurf, m_szSurfDim.cx,
m_szSurfDim.cy, RGB(255,0,255)) == false)
return false;

m_ptDxDraw->SetTransparentColor(m_tDDSurf, RGB(255,0,255), RGB(255,0,255));

// Create a GDI surface from the surface and draw text on it.

HDC l_thDCFont;
if(m_tDDSurf->GetDC(&l_thDCFont) != DD_OK)
return false;

SetBkColor(l_thDCFont, RGB(255,0,255));
SetTextColor(l_thDCFont, m_tTextColor);
SelectObject(l_thDCFont, (HFONT) hFont);

int character=0;
int Width = 256;
int Height = l_szBiggestChar.cy*m_iNumRows;

for(int y=0; y<Height; y+=l_szBiggestChar.cy)
for(int x=0; x<Width; )
{
m_aCharPos[character].x = x;
m_aCharPos[character].y = y;

buffer[0] = (unsigned char) character;

TextOut (l_thDCFont, x, y, buffer, 1) ;

x += m_aCharSize[character].cx;

character++;
if(character > 255)
break;
}

m_tDDSurf->ReleaseDC(l_thDCFont);

//m_ptDxDraw->Blit(m_tDDSurf, 0,0,0,0, m_szSurfDim.cx, m_szSurfDim.cy, false);


return true;
}

void CGUIFont::CalcRectSurfDim(int RowHeight, int* p_pRows, SIZE* p_pSurfSize)
{
SIZE l_szDimSurface = { 256, 0 };

int rows=1, row_width=0;

for(int c=0; c<256; c++)
{
row_width += m_aCharSize[c].cx;
if(row_width >= l_szDimSurface.cx)
{
rows++;
row_width = 0;
l_szDimSurface.cy += RowHeight;
}
}

(*p_pSurfSize).cx = l_szDimSurface.cx;
(*p_pSurfSize).cy = l_szDimSurface.cy;
(*p_pRows) = rows;
}


int CGUIFont::GetTextWidth(char *text)
{
int Width = 0;
for(int i=0; i<strlen(text); i++)
Width += m_aCharSize[(unsigned char)text[i]].cx;

return Width;
}

int CGUIFont::GetTextHeight(char *text)
{
int Height = 0;
for(int i=0; i<strlen(text); i++)
if(Height < m_aCharSize[text[i]].cy)
Height = m_aCharSize[text[i]].cy;

return Height;
}

void CGUIFont::ChangeTextColor(COLORREF new_color)
{
m_ptDxDraw->ChangeColor(m_tDDSurf, new_color, m_tTextColor);
}



Zeblar Nagrim, Lord of Chaos

Share this post


Link to post
Share on other sites