📄 font.cpp
字号:
//--------------------------------------------------
// Desc: Texture Font
// Author: artsylee/2006.11.03
//--------------------------------------------------
#include "../stdafx.h"
#include "Font.h"
#include "Log.h"
#include "Common.h"
#include "FontTexture.h"
#include "Interface.h"
#include "TextureManager.h"
//--------------------------------------------------
// 是否限定纹理尺寸为2的N次方
//--------------------------------------------------
#define _TEXTURE_POWER_2
GFont::GFont()
{
m_hFont = NULL;
m_UpdateTime = 0;
}
GFont::~GFont()
{
Release();
}
void GFont::Release()
{
m_UpdateTime = 0;
if(m_hFont)
{
DeleteObject(m_hFont);
}
FontTextureItor itor = m_FontTextureMap.begin();
while(itor!= m_FontTextureMap.end())
{
::DestroyTexture((*itor).first);
++itor;
}
m_FontTextureMap.clear();
}
//---------------------------------------------------
// 创建字体
//---------------------------------------------------
bool GFont::CreateFont(const char *szFontName, DWORD height, DWORD width, DWORD weight)
{
if(szFontName==NULL)
{
return false;
}
if(m_hFont!=NULL || m_FontTextureMap.size())
{
Release();
}
m_hFont = ::CreateFont(height,
width,
0,
0,
weight,
0,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_SWISS,
// FF_DONTCARE,
szFontName);
if(m_hFont==NULL)
{
WriteLog(INFO_ERROR, "Create font fail[%s]", szFontName);
return false;
}
strcpy(m_FontFamily, szFontName);
m_FontWidth = width;
m_FontHeight = height;
m_FontWeight = weight;
m_LineCount = 70;
m_LineHeight = 20;
/*
for(int i=0; i<MAX_FONT_TEXTURE; i++)
{
CFontTexture * pTexture = new CFontTexture;
pTexture->CreateFontTexture(FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT);
TextureHandle hTex = g_pTextureManager->InsertTexture(pTexture, MM_KEEPINMEMORY);
m_FontTextureMap.insert(FontTextureValue(hTex, pTexture));
}
*/
return true;
}
//---------------------------------------------------
// 格式化输出
//---------------------------------------------------
int GFont::DrawText(int x, int y, DWORD color, const char *pString, ...)
{
char *szText = new char[strlen(pString) + 256];
char *szBack = szText;
va_list va;
va_start(va, pString);
vsprintf(szText, pString, va);
va_end(va);
if(szText[0]==0)
{
delete [] szBack;
return 0;
}
int TotalLen, CurLen, LeaveLen;
int Ascii = 0, Chars = 0;
int XPos = x;
char Tmp[256];
int nLine = 0;
TotalLen = strlen(szText);
while(szText < szBack + TotalLen)
{
Ascii=0;
Chars=0;
XPos=x;
memset(Tmp, 0, 256);
LeaveLen = TotalLen - (int)(szText - szBack);
if(LeaveLen > (int)m_LineCount)
CurLen = (int)m_LineCount;
else
CurLen = LeaveLen;
while((Chars < CurLen) && *szText)
{
//控制字符串处理
Tmp[Chars] = *szText;
szText++;
Chars++;
if((unsigned char)Tmp[Chars-1]<128)
Ascii=1-Ascii;
}
// ASCII数量为单数
if(Ascii==1 && szText < szBack + TotalLen)
{
szText--;
Tmp[Chars-1]=0;
}
//_Show:
nLine++;
TextOut(XPos, y, color, Tmp);
y += m_LineHeight;
}
delete [] szBack;
return nLine;
}
//---------------------------------------------------
// 获取空闲纹理
//---------------------------------------------------
DWORD GFont::GetIdleTexture()
{
// 空的
FontTextureItor itor = m_FontTextureMap.begin();
while(itor != m_FontTextureMap.end())
{
if((*itor).second->IsEmpty())
{
return (*itor).first;
}
itor++;
}
// 最长时间不使用的
DWORD last = 0;
DWORD hTex;
itor = m_FontTextureMap.begin();
while(itor != m_FontTextureMap.end())
{
DWORD updatetm = (*itor).second->GetLastUseTime();
if(last == 0)
{
last = updatetm;
hTex = (*itor).first;
}
else
{
if(last > updatetm)
{
last = updatetm;
hTex = (*itor).first;
}
}
itor++;
}
return hTex;
}
//---------------------------------------------------
// 输出到纹理
//---------------------------------------------------
void GFont::TextOut(int x, int y, DWORD color, const char *pString)
{
if(pString[0]=='\0')
return;
DWORD dwNow = ::timeGetTime();
FontTextureItor itor = m_FontTextureMap.begin();
while(itor != m_FontTextureMap.end())
{
if((*itor).second->Compare(pString))
{
::Render((*itor).first, x, y, NULL, color);
(*itor).second->SetLastUseTime(dwNow);
return;
}
itor++;
}
DWORD hFind = INVALID_HANDLE;
CFontTexture * pTexture = NULL;
RECT rc = GetStringRect(pString);
if(m_FontTextureMap.size()>MAX_FONT_TEXTURE)
{
// 取空闲纹理
hFind = GetIdleTexture();
itor = m_FontTextureMap.find(hFind);
pTexture = (*itor).second;
pTexture->Release();
#ifdef _TEXTURE_POWER_2
int texWidth = FONT_TEXTURE_WIDTH;
int texHeight = FONT_TEXTURE_HEIGHT;
if(rc.right>FONT_TEXTURE_WIDTH)
texWidth = FONT_TEXTURE_WIDTH*2;
if(rc.bottom>FONT_TEXTURE_HEIGHT)
texHeight = FONT_TEXTURE_HEIGHT*2;
pTexture->CreateFontTexture(texWidth, texHeight);
#else
pTexture->CreateFontTexture(rc.right, rc.bottom);
#endif // _TEXTURE_POWER_2
}
else
{
// 创建新纹理
pTexture = new CFontTexture;
#ifdef _TEXTURE_POWER_2
int texWidth = FONT_TEXTURE_WIDTH;
int texHeight = FONT_TEXTURE_HEIGHT;
if(rc.right>FONT_TEXTURE_WIDTH)
texWidth = FONT_TEXTURE_WIDTH*2;
if(rc.bottom>FONT_TEXTURE_HEIGHT)
texHeight = FONT_TEXTURE_HEIGHT*2;
pTexture->CreateFontTexture(texWidth, texHeight);
#else
pTexture->CreateFontTexture(rc.right, rc.bottom);
#endif // _TEXTURE_POWER_2
hFind = g_pTextureManager->InsertTexture(pTexture, MM_KEEPINMEMORY);
m_FontTextureMap.insert(FontTextureValue(hFind, pTexture));
}
/*
Write Sting & Output
*/
pTexture->WriteString(pString, m_hFont);
::Render(hFind, x, y, NULL, color);
pTexture->SetLastUseTime(dwNow);
}
//---------------------------------------------------
// 单行输出
//---------------------------------------------------
void GFont::DrawSingleLine(int x, int y, DWORD color, bool bCenter, const char *pString, ...)
{
char szText[256];
va_list va;
va_start(va, pString);
vsprintf(szText, pString, va);
va_end(va);
if(bCenter)
{
RECT rc = GetStringRect(szText);
TextOut(x-rc.right/2, y-rc.bottom/2, color, szText);
}
else
{
TextOut(x, y, color, szText);
}
}
//---------------------------------------------------
// 此值最好有判断是否大于纹理的最大长度
// 注意此值必须为偶数
//---------------------------------------------------
void GFont::SetLineCount(DWORD dwCount)
{
/*
int MaxCount = (FONT_TEXTURE_WIDTH/m_FontHeight)*2;
if(dwCount>=MaxCount)
{
dwCount = MaxCount;
}
*/
if(dwCount%2 && dwCount>=1)
dwCount = dwCount-1;
m_LineCount = dwCount;
}
//---------------------------------------------------
// 获取字符串占用的RECT
//---------------------------------------------------
RECT GFont::GetStringRect(const char *pString)
{
HDC hDC = CreateCompatibleDC(NULL);
HFONT hOldFont = (HFONT)::SelectObject(hDC, m_hFont);
RECT rc = { 0, 0, 0, 0 };
SIZE sz;
::GetTextExtentPoint32(hDC, pString, strlen(pString), &sz);
::SelectObject(hDC, hOldFont);
::DeleteObject(hDC);
rc.right = sz.cx;
rc.bottom = sz.cy;
return rc;
}
RECT GFont::GetStringRectMultiLine(const char *pString)
{
RECT rc = { 0, 0, 0, 0 };
const char *szBack = pString;
if(pString==NULL || pString[0]==0)
{
return rc;
}
int TotalLen, CurLen, LeaveLen;
int Ascii = 0, Chars = 0;
char Tmp[256];
int nLine = 0;
TotalLen = strlen(pString);
while(pString < szBack + TotalLen)
{
Ascii=0;
Chars=0;
memset(Tmp, 0, 256);
LeaveLen = TotalLen - (int)(pString - szBack);
if(LeaveLen > (int)m_LineCount)
CurLen = (int)m_LineCount;
else
CurLen = LeaveLen;
while((Chars < CurLen) && *pString)
{
//控制字符串处理
Tmp[Chars] = *pString;
pString++;
Chars++;
if((unsigned char)Tmp[Chars-1]<128)
Ascii=1-Ascii;
}
// ASCII数量为单数
if(Ascii==1 && pString < szBack + TotalLen)
{
pString--;
Tmp[Chars-1]=0;
}
//_Show:
nLine++;
RECT temRc = GetStringRect(Tmp);
if(temRc.right>rc.right) rc.right = temRc.right;
if(temRc.bottom>rc.bottom) rc.bottom = temRc.bottom;
}
if(nLine>1)
{
rc.bottom = nLine*m_LineHeight-(m_LineHeight-rc.bottom);
}
return rc;
}
//---------------------------------------------------
// 更新
//---------------------------------------------------
void GFont::Update()
{
DWORD tm = ::timeGetTime();
if(tm - m_UpdateTime>FONTUPDATETIME)
{
FontTextureItor itor = m_FontTextureMap.begin();
while(itor != m_FontTextureMap.end())
{
if((tm-(*itor).second->GetLastUseTime())>FONTMAXEXIST)
{
if(g_pTextureManager)
{
g_pTextureManager->DestroyTexture((*itor).first);
}
itor = m_FontTextureMap.erase(itor);
continue;
}
itor++;
}
m_UpdateTime = tm;
}
}
//--------------------------------------------------
/*
Simple Font (2006_11_16)
*/
//--------------------------------------------------
CSimFont::CSimFont()
{
m_hFont = NULL;
}
CSimFont::~CSimFont()
{
if(m_hFont)
{
DeleteObject(m_hFont);
}
//不要自己删除,通过资源管理器删除
// m_pfTexture->Release();
if(!g_pTextureManager)
{
return;
}
g_pTextureManager->ReleaseTexture(m_texHandle);
}
bool CSimFont::CreateFont(int nHeight, int nWidth, int nEscapement, int nOrientation,
int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut,
DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality,
DWORD fdwPitchAndFamily, LPCTSTR lpszFace)
{
if(m_hFont!=NULL)
{
DeleteObject(m_hFont);
}
m_hFont = ::CreateFont(nHeight,
nWidth,
nEscapement,
nOrientation,
fnWeight,
fdwItalic,
fdwUnderline,
fdwStrikeOut,
DEFAULT_CHARSET,
fdwOutputPrecision,
fdwClipPrecision,
fdwQuality,
fdwPitchAndFamily,
lpszFace);
if(m_hFont==NULL)
{
WriteLog(INFO_ERROR, "Create font fail[%s]", lpszFace);
return false;
}
m_pfTexture = new CFontTexture;
m_texHandle = g_pTextureManager->InsertTexture(m_pfTexture, MM_KEEPINMEMORY);
return true;
}
bool CSimFont::CreateFont(char * szFontName, DWORD height, DWORD width, DWORD weight)
{
if(m_hFont!=NULL)
{
DeleteObject(m_hFont);
}
m_hFont = ::CreateFont(height,
width,
0,
0,
weight,
0,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_SWISS,
szFontName);
if(m_hFont==NULL)
{
WriteLog(INFO_ERROR, "Create font fail[%s]", szFontName);
return false;
}
m_pfTexture = new CFontTexture;
m_texHandle = g_pTextureManager->InsertTexture(m_pfTexture, MM_KEEPINMEMORY);
return true;
}
void CSimFont::DrawText(int x, int y, DWORD color, bool bCenter, char * pString, ...)
{
char szText[256];
va_list va;
va_start(va, pString);
vsprintf(szText, pString, va);
va_end(va);
if(bCenter)
{
RECT rc = GetStringRect(szText);
TextOut(x-rc.right/2, y-rc.bottom/2, color, szText);
}
else
{
TextOut(x, y, color, szText);
}
}
RECT CSimFont::GetStringRect(char * pString)
{
HDC hDC = CreateCompatibleDC(NULL);
HFONT hOldFont = (HFONT)::SelectObject(hDC, m_hFont);
RECT rc = { 0, 0, 0, 0 };
SIZE sz;
::GetTextExtentPoint32(hDC, pString, strlen(pString), &sz);
::SelectObject(hDC, hOldFont);
::DeleteObject(hDC);
rc.right = sz.cx;
rc.bottom = sz.cy;
return rc;
}
void CSimFont::TextOut(int x, int y, DWORD color, char * pString)
{
if(pString[0]=='\0')
return;
if(m_pfTexture->Compare(pString))
{
::Render(m_texHandle, x, y, NULL, color);
}
else
{
m_pfTexture->Release();
RECT rc = GetStringRect(pString);
#ifdef _TEXTURE_POWER_2
int texWidth = FONT_TEXTURE_WIDTH;
int texHeight = FONT_TEXTURE_HEIGHT;
if(rc.right>FONT_TEXTURE_WIDTH)
texWidth = FONT_TEXTURE_WIDTH*2;
if(rc.bottom>FONT_TEXTURE_HEIGHT)
texHeight = FONT_TEXTURE_HEIGHT*2;
m_pfTexture->CreateFontTexture(texWidth, texHeight);
#else
m_pfTexture->CreateFontTexture(rc.right, rc.bottom);
#endif // _TEXTURE_POWER_2
m_pfTexture->WriteString(pString, m_hFont);
::Render(m_texHandle, x, y, NULL, color);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -