让irrlicht-1.4beta支持中文
2009-10-09 11:53
375 查看
近来在研究irrlicht 下了个1.4的发现不支持中文输入输出,在网上找了些发现都是以前版本的发法,用的是FreeType,试了试,发现跟irrlicht 1.4 不是很好接,最后没办法看了一下代码。发现1.4其实是支持中文的,只不过要改一些东西。
irrlicht的字体用的是BMP的,所以首先我想到的就是他的字体导出工具,打开一看有两个,一个老的,一个是新的。用新的试了半天才发现,他的字体图片上都打有点。。而新的工具不能打点。 没办法。。用老的吧。结果老的又不支持中文改吧。
第一步。在StdAfx.h的#include <windows.h>前加入
#define _WIN32_WINNT 0x0500
第二步,将工程属性改为 UNICODE 的
第三。改IrrFontTool.cpp的代码。因为改的挺多,就直接贴上吧。以下是代码
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h
// This is the Font tool for the Irrlicht Engine. It only runs and compiles
// with windows.
// I hacked this program within a few minutes, so the code is currently not
// documentated and very C.
#include "stdafx.h"
#include <tchar.h>
#include "resource.h"
#include "stdio.h"
#include "stdlib.h"
struct SCharData
{
wchar_t character;
int width;
int height;
int posX;
int posY;
};
int CALLBACK EnumFamCallBack(CONST LOGFONT *lplf, CONST TEXTMETRIC *lptm, DWORD FontType, LPARAM lpData)
{
SendDlgItemMessage ((HWND)lpData, IDC_LIST1, LB_ADDSTRING, 0, (LONG)lplf->lfFaceName);
return 1;
}
void updateFontPreview(HWND hWnd)
{
int sizeSel = SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETCURSEL, 0, 0);
int sel = SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETCURSEL, 0, 0);
int bold = SendDlgItemMessage(hWnd, IDC_CHECK1, BM_GETCHECK, 0, 0);
int italic = SendDlgItemMessage(hWnd, IDC_CHECK2, BM_GETCHECK, 0, 0);
if (sel != LB_ERR && sizeSel != LB_ERR)
{
TCHAR str[1024];
SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETTEXT, sizeSel, (LPARAM) str);
int fontSize = _wtoi(str);
SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETTEXT, sel, (LPARAM) str);
HDC dc = GetDC(hWnd);
HFONT font = CreateFontW(
-MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72),
0,0,0,
bold ? FW_BOLD : 0,
italic,
0,0,0,0,0,0,0,
str);
ReleaseDC(hWnd, dc);
RECT r;
HWND preview = GetDlgItem(hWnd, IDC_PREVIEW);
GetClientRect(preview, &r);
LOGBRUSH lbrush;
lbrush.lbColor = GetSysColor(COLOR_3DFACE);
lbrush.lbHatch = 0;
lbrush.lbStyle = BS_SOLID;
HBRUSH brush = CreateBrushIndirect(&lbrush);
HPEN pen = CreatePen(PS_NULL, 0, 0);
dc = GetDC(preview);
HGDIOBJ oldfont = SelectObject(dc, font);
HGDIOBJ oldpen = SelectObject(dc, pen);
HGDIOBJ oldbrush = SelectObject(dc, brush);
const TCHAR *text = L"ABCDEF abcdef 12345";
SetBkMode(dc, OPAQUE);
SetBkColor(dc, GetSysColor(COLOR_3DFACE));
Rectangle(dc, 0,0, r.right, r.bottom);
DrawText(dc, text, wcslen(text), &r, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
SelectObject(dc, oldfont);
SelectObject(dc, oldpen);
SelectObject(dc, oldbrush);
ReleaseDC(preview, dc);
DeleteObject(font);
DeleteObject(brush);
DeleteObject(pen);
}
}
void FillFontList(HWND hWnd)
{
// Fill list with font names
SendDlgItemMessage(hWnd, IDC_LIST1, LB_RESETCONTENT, 0, 0);
HDC dc = GetDC(hWnd);
EnumFonts(dc, 0, &EnumFamCallBack, (LPARAM)hWnd);
ReleaseDC(hWnd, dc);
SendDlgItemMessage (hWnd, IDC_LIST1, LB_SETCURSEL, 0, 0);
// Fill list with font sizes
TCHAR buf[128];
int sc[] = {4,6,8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,56,68,72,0};
for (int i=0; sc[i] != 0; ++i)
SendDlgItemMessage (hWnd, IDC_LIST2, LB_ADDSTRING, 0, (LONG)_itow(sc[i], buf, 10));
SendDlgItemMessage (hWnd, IDC_LIST2, LB_SETCURSEL, 4, 0);
// Fill texture size list
int tc[] = {64,128,256,512,1024,2048,0};
for (int t=0; tc[t] != 0; ++t)
{
_stprintf(buf, L"%d pixels width", tc[t]);
SendDlgItemMessage (hWnd, IDC_COMBO1, CB_ADDSTRING, 0, (LONG)buf);
}
SendDlgItemMessage (hWnd, IDC_COMBO1, CB_SETCURSEL, 2, 0);
}
inline int getTextureSizeFromSurfaceSize(int size)
{
int ts = 0x01;
while(ts < size)
ts <<= 1;
return ts;
}
void copyFontToClipBoard(HWND hWnd, int lastChar)
{
int surfaceSel = SendDlgItemMessage(hWnd, IDC_COMBO1, CB_GETCURSEL, 0, 0);
int sizeSel = SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETCURSEL, 0, 0);
int sel = SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETCURSEL, 0, 0);
int bold = SendDlgItemMessage(hWnd, IDC_CHECK1, BM_GETCHECK, 0, 0);
int italic = SendDlgItemMessage(hWnd, IDC_CHECK2, BM_GETCHECK, 0, 0);
if (sel == LB_ERR || sizeSel == LB_ERR || surfaceSel == CB_ERR)
return;
int i;
// We use the font render preview area as dc
HWND preview = GetDlgItem(hWnd, IDC_PREVIEW);
HDC dc = GetDC(NULL);
TCHAR str[1024];
SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETTEXT, sizeSel, (LPARAM) (LPCTSTR)str);
int fontSize = _wtoi(str);
SendDlgItemMessage(hWnd, IDC_COMBO1, CB_GETLBTEXT, surfaceSel, (LPARAM) (LPCTSTR)str);
int surfaceWidth = _wtoi(str);
SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETTEXT, sel, (LPARAM) (LPCTSTR)str);
HFONT font = CreateFontW(
-MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72),
0,0,0,
bold ? FW_BOLD : 0,
italic,
0,0,0,0,0,0,0,
str);
HGDIOBJ oldfont = SelectObject(dc, font);
// calculate text extents.
DWORD dwSize = GetFontUnicodeRanges( dc, 0);
char *buf = new char[dwSize];
LPGLYPHSET glyphs = (LPGLYPHSET)buf;
GetFontUnicodeRanges( dc, glyphs);
SIZE size;
size.cx = 0;
size.cy = 0;
int posx = 0;
int posy = 0;
int k= 0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
k++;
}
}
SCharData *asciiTable = new SCharData[k];
i=0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
wchar_t currentchar = ch;
GetTextExtentPoint32W(dc, ¤tchar, 1, &size);
++size.cx;
if (posx + size.cx > surfaceWidth)
{
posx = 0;
posy += size.cy+1;
}
asciiTable[i].posX = posx;
asciiTable[i].posY = posy;
asciiTable[i].width = size.cx;
asciiTable[i].height = size.cy;
posx += size.cx;
i++;
}
}
int surfaceHeight = asciiTable[k-1].posY + asciiTable[k-1].height + 1;
surfaceHeight = getTextureSizeFromSurfaceSize(surfaceHeight);
// draw characters
HBITMAP bmp = CreateCompatibleBitmap(dc, surfaceWidth, surfaceHeight);
HDC bmpdc = CreateCompatibleDC(dc);
LOGBRUSH lbrush;
lbrush.lbColor = RGB(0,0,0);
lbrush.lbHatch = 0;
lbrush.lbStyle = BS_SOLID;
HBRUSH brush = CreateBrushIndirect(&lbrush);
HPEN pen = CreatePen(PS_NULL, 0, 0);
HGDIOBJ oldbmp = SelectObject(bmpdc, bmp);
HGDIOBJ oldbmppen = SelectObject(bmpdc, pen);
HGDIOBJ oldbmpbrush = SelectObject(bmpdc, brush);
HGDIOBJ oldbmpfont = SelectObject(bmpdc, font);
SetTextColor(bmpdc, RGB(255,255,255));
Rectangle(bmpdc, 0,0,surfaceWidth,surfaceHeight);
SetBkMode(bmpdc, TRANSPARENT);
SCharData* d;
i = 0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
wchar_t currentchar = ch;
d = &asciiTable[i];
TextOutW(bmpdc, d->posX, d->posY, ¤tchar, 1);
SetPixel(bmpdc, d->posX, d->posY, RGB(255,255,0));// left upper corner mark
SetPixel(bmpdc, d->posX+ d->width -1, d->posY + d->height, RGB(255,0,0));// right lower corner mark
i++;
}
}
// draw index pixels
SetPixel(bmpdc, 0,0, RGB(255,255,0)); // left upper corner mark
SetPixel(bmpdc, 1,0, RGB(255,0,0)); // right lower corner mark
SetPixel(bmpdc, 2,0, RGB(0,0,0)); // background color mark
// copy to clipboard
OpenClipboard(hWnd);
EmptyClipboard();
SetClipboardData(CF_BITMAP, bmp);
CloseClipboard();
SelectObject(bmpdc, oldbmp);
SelectObject(bmpdc, oldbmppen);
SelectObject(bmpdc, oldbmpbrush);
SelectObject(bmpdc, oldbmpfont);
SelectObject(dc, oldfont);
ReleaseDC(preview, dc);
DeleteDC(bmpdc);
DeleteObject(font);
DeleteObject(brush);
DeleteObject(pen);
DeleteObject(bmp);
}
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
{
int wNotifyCode = HIWORD(wParam);
int wID = LOWORD(wParam);
HWND hwndCtl = (HWND)lParam;
switch(wID)
{
case IDOK:
case IDCANCEL:
EndDialog(hwndDlg, wNotifyCode);
PostQuitMessage(0);
return TRUE;
case IDC_CHECK1:
case IDC_CHECK2:
case IDC_LIST1:
case IDC_LIST2:
updateFontPreview(hwndDlg);
return TRUE;
case IDC_BUTTON2:
return TRUE;
case IDC_BUTTON1:
copyFontToClipBoard(hwndDlg, 381);
return TRUE;
}
}
break;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
HWND hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProc);
ShowWindow(hWnd , SW_SHOW);
FillFontList(hWnd);
MSG msg;
do
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
while (msg.message != WM_QUIT);
return 0;
}
编译运行之后就可以导出了,不过图片的宽度要选的大一些。否则可能会有问题。
下面进行引擎的改造。
CGUIFont.h
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_GUI_FONT_H_INCLUDED__
#define __C_GUI_FONT_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include "IGUIFontBitmap.h"
#include "irrString.h"
#include "irrMap.h"
#include "IXMLReader.h"
#include "IReadFile.h"
#include "irrArray.h"
namespace irr
{
namespace video
{
class IVideoDriver;
class IImage;
}
namespace gui
{
class IGUIEnvironment;
class CGUIFont : public IGUIFontBitmap
{
public:
//! constructor
CGUIFont(IGUIEnvironment* env, const c8* filename);
//! destructor
virtual ~CGUIFont();
//! loads a font from a texture file
bool load(const c8* filename,wchar_t *sFontName = NULL);
//! loads a font from a texture file
bool load(io::IReadFile* file,wchar_t *sFontName = NULL);
//! loads a font from an XML file
bool load(io::IXMLReader* xml,wchar_t *sFontName = NULL);
//! draws an text and clips it to the specified rectangle if wanted
virtual void draw(const wchar_t* text, const core::rect<s32>& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect<s32>* clip=0);
//! returns the dimension of a text
virtual core::dimension2d<s32> getDimension(const wchar_t* text) const;
//! Calculates the index of the character in the text which is on a specific position.
virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const;
//! Returns the type of this font
virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; }
//! set an Pixel Offset on Drawing ( scale position on width )
virtual void setKerningWidth (s32 kerning);
virtual void setKerningHeight (s32 kerning);
//! set an Pixel Offset on Drawing ( scale position on width )
virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const;
virtual s32 getKerningHeight() const;
//! gets the sprite bank
virtual IGUISpriteBank* getSpriteBank() const;
//! returns the sprite number from a given character
virtual u32 getSpriteNoFromChar(const wchar_t *c) const;
private:
struct SFontArea
{
SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
s32 underhang;
s32 overhang;
s32 width;
u32 spriteno;
};
//! load & prepare font from ITexture
bool loadTexture(video::IImage * image, const c8* name);
void readPositions16bit(video::IImage* texture, s32& lowerRightPositions);
void readPositions32bit(video::IImage* texture, s32& lowerRightPositions);
bool loadFont(wchar_t *sFontName);
wchar_t GetChar(int n);
s32 getAreaFromCharacter (const wchar_t c) const;
void setMaxHeight();
core::array<SFontArea> Areas;
core::map<wchar_t, s32> CharacterMap;
video::IVideoDriver* Driver;
IGUISpriteBank* SpriteBank;
IGUIEnvironment* Environment;
u32 WrongCharacter;
s32 MaxHeight;
s32 GlobalKerningWidth, GlobalKerningHeight;
wchar_t *m_pFontTemp;
};
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_
#endif // __C_GUI_FONT_H_INCLUDED__
CGUIFont.cpp
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CGUIFont.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#define UNICODE
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <tchar.h>
#include "os.h"
#include "IGUIEnvironment.h"
#include "IXMLReader.h"
#include "IReadFile.h"
#include "IVideoDriver.h"
#include "IGUISpriteBank.h"
#include "CImage.h"
namespace irr
{
namespace gui
{
//! constructor
CGUIFont::CGUIFont(IGUIEnvironment *env, const c8* filename)
: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
{
#ifdef _DEBUG
setDebugName("CGUIFont");
#endif
if (Environment)
{
// don't grab environment, to avoid circular references
Driver = Environment->getVideoDriver();
SpriteBank = Environment->addEmptySpriteBank(filename);
}
m_pFontTemp = NULL;
if (Driver)
Driver->grab();
}
//! destructor
CGUIFont::~CGUIFont()
{
if (Driver)
Driver->drop();
if (SpriteBank)
SpriteBank->drop();
if(m_pFontTemp != NULL)
{
delete []m_pFontTemp;
m_pFontTemp = NULL;
}
}
bool CGUIFont::loadFont(wchar_t *sFontName)
{
HDC dc = GetDC(NULL);
HFONT font = CreateFontW(
-MulDiv(10, GetDeviceCaps(dc, LOGPIXELSY), 72),
0,0,0,
0,
false,
0,0,0,0,0,0,0,
sFontName);
HGDIOBJ oldFont = SelectObject(dc, font);
s32 size = GetFontUnicodeRanges( dc, 0);
c8 *buf = new c8[size];
LPGLYPHSET glyphs = (LPGLYPHSET)buf;
GetFontUnicodeRanges( dc, glyphs);
int num = 0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
num ++;
}
}
if(m_pFontTemp!=NULL)
{
delete []m_pFontTemp;
m_pFontTemp = NULL;
}
m_pFontTemp = new wchar_t[num];
num = 0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
m_pFontTemp[num] = ch;
num ++;
}
}
DeleteObject(oldFont);
DeleteDC(dc);
delete []buf;
return true;
}
//! loads a font file from xml
bool CGUIFont::load(io::IXMLReader* xml,wchar_t *sFontName)
{
if (!SpriteBank)
return false;
if(sFontName!=NULL)
{
loadFont(sFontName);
}
while (xml->read())
{
if (io::EXN_ELEMENT == xml->getNodeType())
{
if (core::stringw(L"Texture") == xml->getNodeName())
{
// add a texture
core::stringc fn = xml->getAttributeValue(L"filename");
u32 i = (u32)xml->getAttributeValueAsInt(L"index");
core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
while (i+1 > SpriteBank->getTextureCount())
SpriteBank->addTexture(0);
// disable mipmaps+filtering
bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
// load texture
SpriteBank->setTexture(i, Driver->getTexture(fn.c_str()));
// set previous mip-map+filter state
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
// couldn't load texture, abort.
if (!SpriteBank->getTexture(i))
{
os::Printer::log("Unable to load all textures in the font, aborting", ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
else
{
// colorkey texture rather than alpha channel?
if (alpha == core::stringw("false"))
Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0));
}
}
else if (core::stringw(L"c") == xml->getNodeName())
{
// adding a character to this font
SFontArea a;
SGUISpriteFrame f;
SGUISprite s;
core::rect<s32> rectangle;
a.underhang = xml->getAttributeValueAsInt(L"u");
a.overhang = xml->getAttributeValueAsInt(L"o");
a.spriteno = SpriteBank->getSprites().size();
s32 texno = xml->getAttributeValueAsInt(L"i");
// parse rectangle
core::stringc rectstr = xml->getAttributeValue(L"r");
wchar_t ch = xml->getAttributeValue(L"c")[0];
const c8 *c = rectstr.c_str();
s32 val;
val = 0;
while (*c >= '0' && *c <= '9')
{
val *= 10;
val += *c - '0';
c++;
}
rectangle.UpperLeftCorner.X = val;
while (*c == L' ' || *c == L',') c++;
val = 0;
while (*c >= '0' && *c <= '9')
{
val *= 10;
val += *c - '0';
c++;
}
rectangle.UpperLeftCorner.Y = val;
while (*c == L' ' || *c == L',') c++;
val = 0;
while (*c >= '0' && *c <= '9')
{
val *= 10;
val += *c - '0';
c++;
}
rectangle.LowerRightCorner.X = val;
while (*c == L' ' || *c == L',') c++;
val = 0;
while (*c >= '0' && *c <= '9')
{
val *= 10;
val += *c - '0';
c++;
}
rectangle.LowerRightCorner.Y = val;
CharacterMap.insert(ch,Areas.size());
// make frame
f.rectNumber = SpriteBank->getPositions().size();
f.textureNumber = texno;
// add frame to sprite
s.Frames.push_back(f);
s.frameTime = 0;
// add rectangle to sprite bank
SpriteBank->getPositions().push_back(rectangle);
a.width = rectangle.getWidth();
// add sprite to sprite bank
SpriteBank->getSprites().push_back(s);
// add character to font
Areas.push_back(a);
}
}
}
// set bad character
WrongCharacter = getAreaFromCharacter(L' ');
setMaxHeight();
return true;
}
void CGUIFont::setMaxHeight()
{
MaxHeight = 0;
s32 t;
core::array< core::rect<s32> >& p = SpriteBank->getPositions();
for (u32 i=0; i<p.size(); ++i)
{
t = p[i].getHeight();
if (t>MaxHeight)
MaxHeight = t;
}
}
//! loads a font file, native file needed, for texture parsing
bool CGUIFont::load(io::IReadFile* file,wchar_t *sFontName)
{
if (!Driver)
return false;
if(sFontName!=NULL)
{
loadFont(sFontName);
}
return loadTexture(Driver->createImageFromFile(file),
file->getFileName());
}
//! loads a font file, native file needed, for texture parsing
bool CGUIFont::load(const c8* filename,wchar_t *sFontName)
{
if (!Driver)
return false;
if(sFontName!=NULL)
{
loadFont(sFontName);
}
return loadTexture(Driver->createImageFromFile( filename ),
filename);
}
//! load & prepare font from ITexture
bool CGUIFont::loadTexture(video::IImage* image, const c8* name)
{
if (!image)
return false;
s32 lowerRightPositions = 0;
video::IImage* tmpImage=image;
bool deleteTmpImage=false;
switch(image->getColorFormat())
{
case video::ECF_R5G6B5:
tmpImage = new video::CImage(video::ECF_A1R5G5B5,image);
deleteTmpImage=true;
case video::ECF_A1R5G5B5:
readPositions16bit(tmpImage, lowerRightPositions);
break;
case video::ECF_R8G8B8:
tmpImage = new video::CImage(video::ECF_A8R8G8B8,image);
deleteTmpImage=true;
case video::ECF_A8R8G8B8:
readPositions32bit (tmpImage, lowerRightPositions);
break;
}
WrongCharacter = getAreaFromCharacter(L' ');
// output warnings
if (!lowerRightPositions || !SpriteBank->getSprites().size())
os::Printer::log("The amount of upper corner pixels or lower corner pixels is == 0, font file may be corrupted.", ELL_ERROR);
else
if (lowerRightPositions != (s32)SpriteBank->getPositions().size())
os::Printer::log("The amount of upper corner pixels and the lower corner pixels is not equal, font file may be corrupted.", ELL_ERROR);
bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions );
if ( ret )
{
SpriteBank->addTexture(Driver->addTexture(name, tmpImage));
}
if (deleteTmpImage)
tmpImage->drop();
image->drop();
setMaxHeight();
return ret;
}
wchar_t CGUIFont::GetChar(int n)
{
if(m_pFontTemp!= NULL)
{
return m_pFontTemp
;
}
return 0;
}
void CGUIFont::readPositions32bit(video::IImage* image, s32& lowerRightPositions)
{
const core::dimension2d<s32>& size = image->getDimension();
s32* p = (s32*)image->lock();
if (!p)
{
os::Printer::log("Could not lock texture while preparing texture for a font.", ELL_ERROR);
return;
}
// fix half alpha of top left pixel in some font textures
p[0] |= 0xFF000000;
s32 colorTopLeft = p[0];
s32 colorLowerRight = *(p+1);
s32 colorBackGround = *(p+2);
s32 colorBackGroundTransparent = 0; // 0x00FFFFFF & colorBackGround;
*(p+1) = colorBackGround;
// start parsing
core::position2d<s32> pos(0,0);
for (pos.Y=0; pos.Y<size.Height; ++pos.Y)
{
for (pos.X=0; pos.X<size.Width; ++pos.X)
{
if ( *p == colorTopLeft)
{
*p = colorBackGroundTransparent;
SpriteBank->getPositions().push_back(core::rect<s32>(pos, pos));
}
else
if (*p == colorLowerRight)
{
if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions)
{
image->unlock();
lowerRightPositions = 0;
return;
}
*p = colorBackGroundTransparent;
SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos;
// add frame to sprite bank
SGUISpriteFrame f;
f.rectNumber = lowerRightPositions;
f.textureNumber = 0;
SGUISprite s;
s.Frames.push_back(f);
s.frameTime = 0;
SpriteBank->getSprites().push_back(s);
// add character to font
SFontArea a;
a.overhang = 0;
a.underhang = 0;
a.spriteno = lowerRightPositions;
a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth();
Areas.push_back(a);
// map letter to character
wchar_t ch ;
if(m_pFontTemp != NULL)
ch = GetChar(lowerRightPositions);
else
ch = (wchar_t)(lowerRightPositions + 32);
CharacterMap.set(ch, lowerRightPositions);
++lowerRightPositions;
}
else
if (*p == colorBackGround)
{
*p = colorBackGroundTransparent;
}
++p;
}
}
// Positions parsed.
image->unlock();
}
void CGUIFont::readPositions16bit(video::IImage* image, s32& lowerRightPositions)
{
core::dimension2d<s32> size = image->getDimension();
s16* p = (s16*)image->lock();
if (!p)
{
os::Printer::log("Could not lock texture while preparing texture for a font.", ELL_ERROR);
return;
}
// fix half alpha of top left pixel in some font textures
p[0] |= 0x8000;
s16 colorTopLeft = p[0];
s16 colorLowerRight = *(p+1);
s16 colorBackGround = *(p+2);
s16 colorBackGroundTransparent = 0; // 0x7FFF & colorBackGround;
*(p+1) = colorBackGround;
// start parsing
core::position2d<s32> pos(0,0);
for (pos.Y=0; pos.Y<size.Height; ++pos.Y)
{
for (pos.X=0; pos.X<size.Width; ++pos.X)
{
if (*p == colorTopLeft)
{
*p = colorBackGroundTransparent;
SpriteBank->getPositions().push_back(core::rect<s32>(pos, pos));
}
else
if (*p == colorLowerRight)
{
// too many lower right points
if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions)
{
image->unlock();
lowerRightPositions = 0;
return;
}
*p = colorBackGroundTransparent;
SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos;
// add frame to sprite bank
SGUISpriteFrame f;
f.rectNumber = lowerRightPositions;
f.textureNumber = 0;
SGUISprite s;
s.Frames.push_back(f);
s.frameTime = 0;
SpriteBank->getSprites().push_back(s);
// add character to font
SFontArea a;
a.overhang = 0;
a.underhang = 0;
a.spriteno = lowerRightPositions;
a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth();
Areas.push_back(a);
// map letter to character
//wchar_t ch = (wchar_t)(lowerRightPositions + 32);
wchar_t ch ;
if(m_pFontTemp != NULL)
ch = GetChar(lowerRightPositions);
else
ch = (wchar_t)(lowerRightPositions + 32);
CharacterMap.set(ch, lowerRightPositions);
++lowerRightPositions;
}
else
if (*p == colorBackGround)
*p = colorBackGroundTransparent;
++p;
}
}
// Positions parsed.
image->unlock();
}
//! returns the dimension of text
core::dimension2d<s32> CGUIFont::getDimension(const wchar_t* text) const
{
core::dimension2d<s32> dim(0, 0);
core::dimension2d<s32> thisLine(0, MaxHeight);
for (const wchar_t* p = text; *p; ++p)
{
bool lineBreak=false;
if (*p == L'\r') // Mac or Windows breaks
{
lineBreak = true;
if (p[1] == L'\n') // Windows breaks
++p;
}
else if (*p == L'\n') // Unix breaks
{
lineBreak = true;
}
if (lineBreak)
{
dim.Height += thisLine.Height;
if (dim.Width < thisLine.Width)
dim.Width = thisLine.Width;
thisLine.Width = 0;
continue;
}
const SFontArea &area = Areas[getAreaFromCharacter(*p)];
thisLine.Width += area.underhang;
thisLine.Width += area.width + area.overhang + GlobalKerningWidth;
}
dim.Height += thisLine.Height;
if (dim.Width < thisLine.Width)
dim.Width = thisLine.Width;
return dim;
}
//! set an Pixel Offset on Drawing ( scale position on width )
void CGUIFont::setKerningWidth ( s32 kerning )
{
GlobalKerningWidth = kerning;
}
//! set an Pixel Offset on Drawing ( scale position on width )
s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const
{
s32 ret = GlobalKerningWidth;
if (thisLetter)
{
ret += Areas[getAreaFromCharacter(*thisLetter)].overhang;
if (previousLetter)
{
ret += Areas[getAreaFromCharacter(*previousLetter)].underhang;
}
}
return ret;
}
//! set an Pixel Offset on Drawing ( scale position on height )
void CGUIFont::setKerningHeight ( s32 kerning )
{
GlobalKerningHeight = kerning;
}
//! set an Pixel Offset on Drawing ( scale position on height )
s32 CGUIFont::getKerningHeight () const
{
return GlobalKerningHeight;
}
//! returns the sprite number from a given character
u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const
{
return Areas[getAreaFromCharacter(*c)].spriteno;
}
s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const
{
core::map<wchar_t, s32>::Node* n = CharacterMap.find(c);
if (n)
return n->getValue();
else
return WrongCharacter;
}
/*
//! draws an text and clips it to the specified rectangle if wanted
void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
{
if (!Driver)
return;
core::dimension2d<s32> textDimension;
core::position2d<s32> offset = position.UpperLeftCorner;
if (hcenter || vcenter)
{
textDimension = getDimension(text);
if (hcenter)
offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X;
if (vcenter)
offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y;
}
core::array<s32> indices;
indices.reallocate(core::stringw(text).size());
u32 n;
while(*text)
{
n = (*text) - 32;
if ( n > Positions.size())
n = WrongCharacter;
indices.push_back(n);
++text;
}
Driver->draw2DImage(Texture, offset, Positions, indices, GlobalKerningWidth, clip, color, true);
}
*/
//! draws some text and clips it to the specified rectangle if wanted
void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
{
if (!Driver)
return;
core::dimension2d<s32> textDimension;
core::position2d<s32> offset = position.UpperLeftCorner;
core::rect<s32> pos;
if (hcenter || vcenter || clip)
textDimension = getDimension(text);
if (hcenter)
offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X;
if (vcenter)
offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y;
if (clip)
{
core::rect<s32> clippedRect(offset, textDimension);
clippedRect.clipAgainst(*clip);
if (!clippedRect.isValid())
return;
}
while(*text)
{
SFontArea& area = Areas[getAreaFromCharacter(*text)];
offset.X += area.underhang;
SpriteBank->draw2DSprite(area.spriteno, offset, clip, color);
offset.X += area.width + area.overhang + GlobalKerningWidth;
++text;
}
}
//! Calculates the index of the character in the text which is on a specific position.
s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
{
s32 x = 0;
s32 idx = 0;
while (text[idx])
{
const SFontArea& a = Areas[getAreaFromCharacter(text[idx])];
x += a.width + a.overhang + a.underhang;
if (x >= pixel_x)
return idx;
++idx;
}
return -1;
}
IGUISpriteBank* CGUIFont::getSpriteBank() const
{
return SpriteBank;
}
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_
将 IGUIEnvironment.h
virtual IGUIFont* getFont(const c8* filename) = 0;
改为 virtual IGUIFont* getFont(const c8* filename,wchar_t *sFontName=NULL) = 0;
同样将 CGUIEnvironment.h
virtual IGUIFont* getFont(const c8* filename) = 0;
改为 virtual IGUIFont* getFont(const c8* filename,wchar_t *sFontName=NULL) = 0;
将CGUIEnvironment.cpp的getFont改为如下
//! returns the font
IGUIFont* CGUIEnvironment::getFont(const c8* filename,wchar_t *sFontName)
{
// search existing font
SFont f;
IGUIFont* ifont=0;
if (!filename)
f.Filename = "";
else
f.Filename = filename;
f.Filename.make_lower();
s32 index = Fonts.binary_search(f);
if (index != -1)
return Fonts[index].Font;
// font doesn't exist, attempt to load it
// does the file exist?
if (!FileSystem->existFile(filename))
{
os::Printer::log("Could not load font because the file does not exist", f.Filename.c_str(), ELL_ERROR);
return 0;
}
io::IXMLReader *xml = FileSystem->createXMLReader(filename);
if (xml)
{
// this is an XML font, but we need to know what type
EGUI_FONT_TYPE t = EGFT_CUSTOM;
bool found=false;
while(xml->read() && !found)
{
if (xml->getNodeType() == io::EXN_ELEMENT)
{
if (core::stringw(L"font") == xml->getNodeName())
{
if (core::stringw(L"vector") == xml->getAttributeValue(L"type"))
{
t = EGFT_VECTOR;
found=true;
}
else if (core::stringw(L"bitmap") == xml->getAttributeValue(L"type"))
{
t = EGFT_BITMAP;
found=true;
}
else found=true;
}
}
}
if (t==EGFT_BITMAP)
{
CGUIFont* font = new CGUIFont(this, filename);
ifont = (IGUIFont*)font;
// change working directory, for loading textures
core::stringc workingDir = FileSystem->getWorkingDirectory();
FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.Filename).c_str());
// load the font
if (!font->load(xml,sFontName))
{
font->drop();
font = 0;
ifont = 0;
}
// change working dir back again
FileSystem->changeWorkingDirectoryTo( workingDir.c_str());
}
else if (t==EGFT_VECTOR)
{
// todo: vector fonts
os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.Filename.c_str(), ELL_ERROR);
//CGUIFontVector* font = new CGUIFontVector(Driver);
//ifont = (IGUIFont*)font;
//if (!font->load(xml))
}
xml->drop();
}
if (!ifont)
{
CGUIFont* font = new CGUIFont(this, f.Filename.c_str());
ifont = (IGUIFont*)font;
if (!font->load(f.Filename.c_str(),sFontName))
{
font->drop();
return 0;
}
}
// add to fonts.
f.Font = ifont;
Fonts.push_back(f);
return ifont;
}
好了,我们可以使用了 ,在主函数里加入
IGUISkin* skin = env->getSkin();
IGUIFont* font = env->getFont("http://www.cnblogs.com/media/myfont0.bmp",L"宋体");//图片是刚才生成的图片,字体也是刚才字体工具上选中的字体
if (font)
skin->setFont(font);
skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);
最后CIrrDeviceWin32.cpp 里的WndProc里加入
case WM_IME_CHAR:
{
event.EventType = irr::EET_KEY_INPUT_EVENT;
event.KeyInput.PressedDown = true;
event.KeyInput.Key = irr::KEY_OEM_CLEAR ;
event.KeyInput.Shift = 0;
event.KeyInput.Control = 0;
char p1[2];
p1[0]=(char)((wParam&0xff00)>>8);
p1[1]=(char)(wParam&0xff);
if(p1[0]==0)
{
event.KeyInput.Char=(wchar_t)wParam;
}
else
//多字节代码转unicode
MultiByteToWideChar(CP_OEMCP,MB_PRECOMPOSED,p1,2,&(event.KeyInput.Char),1);
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
break;
}
用来支持中文输入
irrlicht的字体用的是BMP的,所以首先我想到的就是他的字体导出工具,打开一看有两个,一个老的,一个是新的。用新的试了半天才发现,他的字体图片上都打有点。。而新的工具不能打点。 没办法。。用老的吧。结果老的又不支持中文改吧。
第一步。在StdAfx.h的#include <windows.h>前加入
#define _WIN32_WINNT 0x0500
第二步,将工程属性改为 UNICODE 的
第三。改IrrFontTool.cpp的代码。因为改的挺多,就直接贴上吧。以下是代码
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h
// This is the Font tool for the Irrlicht Engine. It only runs and compiles
// with windows.
// I hacked this program within a few minutes, so the code is currently not
// documentated and very C.
#include "stdafx.h"
#include <tchar.h>
#include "resource.h"
#include "stdio.h"
#include "stdlib.h"
struct SCharData
{
wchar_t character;
int width;
int height;
int posX;
int posY;
};
int CALLBACK EnumFamCallBack(CONST LOGFONT *lplf, CONST TEXTMETRIC *lptm, DWORD FontType, LPARAM lpData)
{
SendDlgItemMessage ((HWND)lpData, IDC_LIST1, LB_ADDSTRING, 0, (LONG)lplf->lfFaceName);
return 1;
}
void updateFontPreview(HWND hWnd)
{
int sizeSel = SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETCURSEL, 0, 0);
int sel = SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETCURSEL, 0, 0);
int bold = SendDlgItemMessage(hWnd, IDC_CHECK1, BM_GETCHECK, 0, 0);
int italic = SendDlgItemMessage(hWnd, IDC_CHECK2, BM_GETCHECK, 0, 0);
if (sel != LB_ERR && sizeSel != LB_ERR)
{
TCHAR str[1024];
SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETTEXT, sizeSel, (LPARAM) str);
int fontSize = _wtoi(str);
SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETTEXT, sel, (LPARAM) str);
HDC dc = GetDC(hWnd);
HFONT font = CreateFontW(
-MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72),
0,0,0,
bold ? FW_BOLD : 0,
italic,
0,0,0,0,0,0,0,
str);
ReleaseDC(hWnd, dc);
RECT r;
HWND preview = GetDlgItem(hWnd, IDC_PREVIEW);
GetClientRect(preview, &r);
LOGBRUSH lbrush;
lbrush.lbColor = GetSysColor(COLOR_3DFACE);
lbrush.lbHatch = 0;
lbrush.lbStyle = BS_SOLID;
HBRUSH brush = CreateBrushIndirect(&lbrush);
HPEN pen = CreatePen(PS_NULL, 0, 0);
dc = GetDC(preview);
HGDIOBJ oldfont = SelectObject(dc, font);
HGDIOBJ oldpen = SelectObject(dc, pen);
HGDIOBJ oldbrush = SelectObject(dc, brush);
const TCHAR *text = L"ABCDEF abcdef 12345";
SetBkMode(dc, OPAQUE);
SetBkColor(dc, GetSysColor(COLOR_3DFACE));
Rectangle(dc, 0,0, r.right, r.bottom);
DrawText(dc, text, wcslen(text), &r, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
SelectObject(dc, oldfont);
SelectObject(dc, oldpen);
SelectObject(dc, oldbrush);
ReleaseDC(preview, dc);
DeleteObject(font);
DeleteObject(brush);
DeleteObject(pen);
}
}
void FillFontList(HWND hWnd)
{
// Fill list with font names
SendDlgItemMessage(hWnd, IDC_LIST1, LB_RESETCONTENT, 0, 0);
HDC dc = GetDC(hWnd);
EnumFonts(dc, 0, &EnumFamCallBack, (LPARAM)hWnd);
ReleaseDC(hWnd, dc);
SendDlgItemMessage (hWnd, IDC_LIST1, LB_SETCURSEL, 0, 0);
// Fill list with font sizes
TCHAR buf[128];
int sc[] = {4,6,8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,56,68,72,0};
for (int i=0; sc[i] != 0; ++i)
SendDlgItemMessage (hWnd, IDC_LIST2, LB_ADDSTRING, 0, (LONG)_itow(sc[i], buf, 10));
SendDlgItemMessage (hWnd, IDC_LIST2, LB_SETCURSEL, 4, 0);
// Fill texture size list
int tc[] = {64,128,256,512,1024,2048,0};
for (int t=0; tc[t] != 0; ++t)
{
_stprintf(buf, L"%d pixels width", tc[t]);
SendDlgItemMessage (hWnd, IDC_COMBO1, CB_ADDSTRING, 0, (LONG)buf);
}
SendDlgItemMessage (hWnd, IDC_COMBO1, CB_SETCURSEL, 2, 0);
}
inline int getTextureSizeFromSurfaceSize(int size)
{
int ts = 0x01;
while(ts < size)
ts <<= 1;
return ts;
}
void copyFontToClipBoard(HWND hWnd, int lastChar)
{
int surfaceSel = SendDlgItemMessage(hWnd, IDC_COMBO1, CB_GETCURSEL, 0, 0);
int sizeSel = SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETCURSEL, 0, 0);
int sel = SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETCURSEL, 0, 0);
int bold = SendDlgItemMessage(hWnd, IDC_CHECK1, BM_GETCHECK, 0, 0);
int italic = SendDlgItemMessage(hWnd, IDC_CHECK2, BM_GETCHECK, 0, 0);
if (sel == LB_ERR || sizeSel == LB_ERR || surfaceSel == CB_ERR)
return;
int i;
// We use the font render preview area as dc
HWND preview = GetDlgItem(hWnd, IDC_PREVIEW);
HDC dc = GetDC(NULL);
TCHAR str[1024];
SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETTEXT, sizeSel, (LPARAM) (LPCTSTR)str);
int fontSize = _wtoi(str);
SendDlgItemMessage(hWnd, IDC_COMBO1, CB_GETLBTEXT, surfaceSel, (LPARAM) (LPCTSTR)str);
int surfaceWidth = _wtoi(str);
SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETTEXT, sel, (LPARAM) (LPCTSTR)str);
HFONT font = CreateFontW(
-MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72),
0,0,0,
bold ? FW_BOLD : 0,
italic,
0,0,0,0,0,0,0,
str);
HGDIOBJ oldfont = SelectObject(dc, font);
// calculate text extents.
DWORD dwSize = GetFontUnicodeRanges( dc, 0);
char *buf = new char[dwSize];
LPGLYPHSET glyphs = (LPGLYPHSET)buf;
GetFontUnicodeRanges( dc, glyphs);
SIZE size;
size.cx = 0;
size.cy = 0;
int posx = 0;
int posy = 0;
int k= 0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
k++;
}
}
SCharData *asciiTable = new SCharData[k];
i=0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
wchar_t currentchar = ch;
GetTextExtentPoint32W(dc, ¤tchar, 1, &size);
++size.cx;
if (posx + size.cx > surfaceWidth)
{
posx = 0;
posy += size.cy+1;
}
asciiTable[i].posX = posx;
asciiTable[i].posY = posy;
asciiTable[i].width = size.cx;
asciiTable[i].height = size.cy;
posx += size.cx;
i++;
}
}
int surfaceHeight = asciiTable[k-1].posY + asciiTable[k-1].height + 1;
surfaceHeight = getTextureSizeFromSurfaceSize(surfaceHeight);
// draw characters
HBITMAP bmp = CreateCompatibleBitmap(dc, surfaceWidth, surfaceHeight);
HDC bmpdc = CreateCompatibleDC(dc);
LOGBRUSH lbrush;
lbrush.lbColor = RGB(0,0,0);
lbrush.lbHatch = 0;
lbrush.lbStyle = BS_SOLID;
HBRUSH brush = CreateBrushIndirect(&lbrush);
HPEN pen = CreatePen(PS_NULL, 0, 0);
HGDIOBJ oldbmp = SelectObject(bmpdc, bmp);
HGDIOBJ oldbmppen = SelectObject(bmpdc, pen);
HGDIOBJ oldbmpbrush = SelectObject(bmpdc, brush);
HGDIOBJ oldbmpfont = SelectObject(bmpdc, font);
SetTextColor(bmpdc, RGB(255,255,255));
Rectangle(bmpdc, 0,0,surfaceWidth,surfaceHeight);
SetBkMode(bmpdc, TRANSPARENT);
SCharData* d;
i = 0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
wchar_t currentchar = ch;
d = &asciiTable[i];
TextOutW(bmpdc, d->posX, d->posY, ¤tchar, 1);
SetPixel(bmpdc, d->posX, d->posY, RGB(255,255,0));// left upper corner mark
SetPixel(bmpdc, d->posX+ d->width -1, d->posY + d->height, RGB(255,0,0));// right lower corner mark
i++;
}
}
// draw index pixels
SetPixel(bmpdc, 0,0, RGB(255,255,0)); // left upper corner mark
SetPixel(bmpdc, 1,0, RGB(255,0,0)); // right lower corner mark
SetPixel(bmpdc, 2,0, RGB(0,0,0)); // background color mark
// copy to clipboard
OpenClipboard(hWnd);
EmptyClipboard();
SetClipboardData(CF_BITMAP, bmp);
CloseClipboard();
SelectObject(bmpdc, oldbmp);
SelectObject(bmpdc, oldbmppen);
SelectObject(bmpdc, oldbmpbrush);
SelectObject(bmpdc, oldbmpfont);
SelectObject(dc, oldfont);
ReleaseDC(preview, dc);
DeleteDC(bmpdc);
DeleteObject(font);
DeleteObject(brush);
DeleteObject(pen);
DeleteObject(bmp);
}
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
{
int wNotifyCode = HIWORD(wParam);
int wID = LOWORD(wParam);
HWND hwndCtl = (HWND)lParam;
switch(wID)
{
case IDOK:
case IDCANCEL:
EndDialog(hwndDlg, wNotifyCode);
PostQuitMessage(0);
return TRUE;
case IDC_CHECK1:
case IDC_CHECK2:
case IDC_LIST1:
case IDC_LIST2:
updateFontPreview(hwndDlg);
return TRUE;
case IDC_BUTTON2:
return TRUE;
case IDC_BUTTON1:
copyFontToClipBoard(hwndDlg, 381);
return TRUE;
}
}
break;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
HWND hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProc);
ShowWindow(hWnd , SW_SHOW);
FillFontList(hWnd);
MSG msg;
do
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
while (msg.message != WM_QUIT);
return 0;
}
编译运行之后就可以导出了,不过图片的宽度要选的大一些。否则可能会有问题。
下面进行引擎的改造。
CGUIFont.h
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_GUI_FONT_H_INCLUDED__
#define __C_GUI_FONT_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#include "IGUIFontBitmap.h"
#include "irrString.h"
#include "irrMap.h"
#include "IXMLReader.h"
#include "IReadFile.h"
#include "irrArray.h"
namespace irr
{
namespace video
{
class IVideoDriver;
class IImage;
}
namespace gui
{
class IGUIEnvironment;
class CGUIFont : public IGUIFontBitmap
{
public:
//! constructor
CGUIFont(IGUIEnvironment* env, const c8* filename);
//! destructor
virtual ~CGUIFont();
//! loads a font from a texture file
bool load(const c8* filename,wchar_t *sFontName = NULL);
//! loads a font from a texture file
bool load(io::IReadFile* file,wchar_t *sFontName = NULL);
//! loads a font from an XML file
bool load(io::IXMLReader* xml,wchar_t *sFontName = NULL);
//! draws an text and clips it to the specified rectangle if wanted
virtual void draw(const wchar_t* text, const core::rect<s32>& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect<s32>* clip=0);
//! returns the dimension of a text
virtual core::dimension2d<s32> getDimension(const wchar_t* text) const;
//! Calculates the index of the character in the text which is on a specific position.
virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const;
//! Returns the type of this font
virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; }
//! set an Pixel Offset on Drawing ( scale position on width )
virtual void setKerningWidth (s32 kerning);
virtual void setKerningHeight (s32 kerning);
//! set an Pixel Offset on Drawing ( scale position on width )
virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const;
virtual s32 getKerningHeight() const;
//! gets the sprite bank
virtual IGUISpriteBank* getSpriteBank() const;
//! returns the sprite number from a given character
virtual u32 getSpriteNoFromChar(const wchar_t *c) const;
private:
struct SFontArea
{
SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
s32 underhang;
s32 overhang;
s32 width;
u32 spriteno;
};
//! load & prepare font from ITexture
bool loadTexture(video::IImage * image, const c8* name);
void readPositions16bit(video::IImage* texture, s32& lowerRightPositions);
void readPositions32bit(video::IImage* texture, s32& lowerRightPositions);
bool loadFont(wchar_t *sFontName);
wchar_t GetChar(int n);
s32 getAreaFromCharacter (const wchar_t c) const;
void setMaxHeight();
core::array<SFontArea> Areas;
core::map<wchar_t, s32> CharacterMap;
video::IVideoDriver* Driver;
IGUISpriteBank* SpriteBank;
IGUIEnvironment* Environment;
u32 WrongCharacter;
s32 MaxHeight;
s32 GlobalKerningWidth, GlobalKerningHeight;
wchar_t *m_pFontTemp;
};
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_
#endif // __C_GUI_FONT_H_INCLUDED__
CGUIFont.cpp
// Copyright (C) 2002-2007 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CGUIFont.h"
#ifdef _IRR_COMPILE_WITH_GUI_
#define UNICODE
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <tchar.h>
#include "os.h"
#include "IGUIEnvironment.h"
#include "IXMLReader.h"
#include "IReadFile.h"
#include "IVideoDriver.h"
#include "IGUISpriteBank.h"
#include "CImage.h"
namespace irr
{
namespace gui
{
//! constructor
CGUIFont::CGUIFont(IGUIEnvironment *env, const c8* filename)
: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
{
#ifdef _DEBUG
setDebugName("CGUIFont");
#endif
if (Environment)
{
// don't grab environment, to avoid circular references
Driver = Environment->getVideoDriver();
SpriteBank = Environment->addEmptySpriteBank(filename);
}
m_pFontTemp = NULL;
if (Driver)
Driver->grab();
}
//! destructor
CGUIFont::~CGUIFont()
{
if (Driver)
Driver->drop();
if (SpriteBank)
SpriteBank->drop();
if(m_pFontTemp != NULL)
{
delete []m_pFontTemp;
m_pFontTemp = NULL;
}
}
bool CGUIFont::loadFont(wchar_t *sFontName)
{
HDC dc = GetDC(NULL);
HFONT font = CreateFontW(
-MulDiv(10, GetDeviceCaps(dc, LOGPIXELSY), 72),
0,0,0,
0,
false,
0,0,0,0,0,0,0,
sFontName);
HGDIOBJ oldFont = SelectObject(dc, font);
s32 size = GetFontUnicodeRanges( dc, 0);
c8 *buf = new c8[size];
LPGLYPHSET glyphs = (LPGLYPHSET)buf;
GetFontUnicodeRanges( dc, glyphs);
int num = 0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
num ++;
}
}
if(m_pFontTemp!=NULL)
{
delete []m_pFontTemp;
m_pFontTemp = NULL;
}
m_pFontTemp = new wchar_t[num];
num = 0;
for (unsigned int range=0; range < glyphs->cRanges; range++)
{
WCRANGE* current = &glyphs->ranges[range];
//maxy=0;
// loop through each glyph and write its size and position
for (int ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
{
m_pFontTemp[num] = ch;
num ++;
}
}
DeleteObject(oldFont);
DeleteDC(dc);
delete []buf;
return true;
}
//! loads a font file from xml
bool CGUIFont::load(io::IXMLReader* xml,wchar_t *sFontName)
{
if (!SpriteBank)
return false;
if(sFontName!=NULL)
{
loadFont(sFontName);
}
while (xml->read())
{
if (io::EXN_ELEMENT == xml->getNodeType())
{
if (core::stringw(L"Texture") == xml->getNodeName())
{
// add a texture
core::stringc fn = xml->getAttributeValue(L"filename");
u32 i = (u32)xml->getAttributeValueAsInt(L"index");
core::stringw alpha = xml->getAttributeValue(L"hasAlpha");
while (i+1 > SpriteBank->getTextureCount())
SpriteBank->addTexture(0);
// disable mipmaps+filtering
bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
// load texture
SpriteBank->setTexture(i, Driver->getTexture(fn.c_str()));
// set previous mip-map+filter state
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap);
// couldn't load texture, abort.
if (!SpriteBank->getTexture(i))
{
os::Printer::log("Unable to load all textures in the font, aborting", ELL_ERROR);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
else
{
// colorkey texture rather than alpha channel?
if (alpha == core::stringw("false"))
Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0));
}
}
else if (core::stringw(L"c") == xml->getNodeName())
{
// adding a character to this font
SFontArea a;
SGUISpriteFrame f;
SGUISprite s;
core::rect<s32> rectangle;
a.underhang = xml->getAttributeValueAsInt(L"u");
a.overhang = xml->getAttributeValueAsInt(L"o");
a.spriteno = SpriteBank->getSprites().size();
s32 texno = xml->getAttributeValueAsInt(L"i");
// parse rectangle
core::stringc rectstr = xml->getAttributeValue(L"r");
wchar_t ch = xml->getAttributeValue(L"c")[0];
const c8 *c = rectstr.c_str();
s32 val;
val = 0;
while (*c >= '0' && *c <= '9')
{
val *= 10;
val += *c - '0';
c++;
}
rectangle.UpperLeftCorner.X = val;
while (*c == L' ' || *c == L',') c++;
val = 0;
while (*c >= '0' && *c <= '9')
{
val *= 10;
val += *c - '0';
c++;
}
rectangle.UpperLeftCorner.Y = val;
while (*c == L' ' || *c == L',') c++;
val = 0;
while (*c >= '0' && *c <= '9')
{
val *= 10;
val += *c - '0';
c++;
}
rectangle.LowerRightCorner.X = val;
while (*c == L' ' || *c == L',') c++;
val = 0;
while (*c >= '0' && *c <= '9')
{
val *= 10;
val += *c - '0';
c++;
}
rectangle.LowerRightCorner.Y = val;
CharacterMap.insert(ch,Areas.size());
// make frame
f.rectNumber = SpriteBank->getPositions().size();
f.textureNumber = texno;
// add frame to sprite
s.Frames.push_back(f);
s.frameTime = 0;
// add rectangle to sprite bank
SpriteBank->getPositions().push_back(rectangle);
a.width = rectangle.getWidth();
// add sprite to sprite bank
SpriteBank->getSprites().push_back(s);
// add character to font
Areas.push_back(a);
}
}
}
// set bad character
WrongCharacter = getAreaFromCharacter(L' ');
setMaxHeight();
return true;
}
void CGUIFont::setMaxHeight()
{
MaxHeight = 0;
s32 t;
core::array< core::rect<s32> >& p = SpriteBank->getPositions();
for (u32 i=0; i<p.size(); ++i)
{
t = p[i].getHeight();
if (t>MaxHeight)
MaxHeight = t;
}
}
//! loads a font file, native file needed, for texture parsing
bool CGUIFont::load(io::IReadFile* file,wchar_t *sFontName)
{
if (!Driver)
return false;
if(sFontName!=NULL)
{
loadFont(sFontName);
}
return loadTexture(Driver->createImageFromFile(file),
file->getFileName());
}
//! loads a font file, native file needed, for texture parsing
bool CGUIFont::load(const c8* filename,wchar_t *sFontName)
{
if (!Driver)
return false;
if(sFontName!=NULL)
{
loadFont(sFontName);
}
return loadTexture(Driver->createImageFromFile( filename ),
filename);
}
//! load & prepare font from ITexture
bool CGUIFont::loadTexture(video::IImage* image, const c8* name)
{
if (!image)
return false;
s32 lowerRightPositions = 0;
video::IImage* tmpImage=image;
bool deleteTmpImage=false;
switch(image->getColorFormat())
{
case video::ECF_R5G6B5:
tmpImage = new video::CImage(video::ECF_A1R5G5B5,image);
deleteTmpImage=true;
case video::ECF_A1R5G5B5:
readPositions16bit(tmpImage, lowerRightPositions);
break;
case video::ECF_R8G8B8:
tmpImage = new video::CImage(video::ECF_A8R8G8B8,image);
deleteTmpImage=true;
case video::ECF_A8R8G8B8:
readPositions32bit (tmpImage, lowerRightPositions);
break;
}
WrongCharacter = getAreaFromCharacter(L' ');
// output warnings
if (!lowerRightPositions || !SpriteBank->getSprites().size())
os::Printer::log("The amount of upper corner pixels or lower corner pixels is == 0, font file may be corrupted.", ELL_ERROR);
else
if (lowerRightPositions != (s32)SpriteBank->getPositions().size())
os::Printer::log("The amount of upper corner pixels and the lower corner pixels is not equal, font file may be corrupted.", ELL_ERROR);
bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions );
if ( ret )
{
SpriteBank->addTexture(Driver->addTexture(name, tmpImage));
}
if (deleteTmpImage)
tmpImage->drop();
image->drop();
setMaxHeight();
return ret;
}
wchar_t CGUIFont::GetChar(int n)
{
if(m_pFontTemp!= NULL)
{
return m_pFontTemp
;
}
return 0;
}
void CGUIFont::readPositions32bit(video::IImage* image, s32& lowerRightPositions)
{
const core::dimension2d<s32>& size = image->getDimension();
s32* p = (s32*)image->lock();
if (!p)
{
os::Printer::log("Could not lock texture while preparing texture for a font.", ELL_ERROR);
return;
}
// fix half alpha of top left pixel in some font textures
p[0] |= 0xFF000000;
s32 colorTopLeft = p[0];
s32 colorLowerRight = *(p+1);
s32 colorBackGround = *(p+2);
s32 colorBackGroundTransparent = 0; // 0x00FFFFFF & colorBackGround;
*(p+1) = colorBackGround;
// start parsing
core::position2d<s32> pos(0,0);
for (pos.Y=0; pos.Y<size.Height; ++pos.Y)
{
for (pos.X=0; pos.X<size.Width; ++pos.X)
{
if ( *p == colorTopLeft)
{
*p = colorBackGroundTransparent;
SpriteBank->getPositions().push_back(core::rect<s32>(pos, pos));
}
else
if (*p == colorLowerRight)
{
if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions)
{
image->unlock();
lowerRightPositions = 0;
return;
}
*p = colorBackGroundTransparent;
SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos;
// add frame to sprite bank
SGUISpriteFrame f;
f.rectNumber = lowerRightPositions;
f.textureNumber = 0;
SGUISprite s;
s.Frames.push_back(f);
s.frameTime = 0;
SpriteBank->getSprites().push_back(s);
// add character to font
SFontArea a;
a.overhang = 0;
a.underhang = 0;
a.spriteno = lowerRightPositions;
a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth();
Areas.push_back(a);
// map letter to character
wchar_t ch ;
if(m_pFontTemp != NULL)
ch = GetChar(lowerRightPositions);
else
ch = (wchar_t)(lowerRightPositions + 32);
CharacterMap.set(ch, lowerRightPositions);
++lowerRightPositions;
}
else
if (*p == colorBackGround)
{
*p = colorBackGroundTransparent;
}
++p;
}
}
// Positions parsed.
image->unlock();
}
void CGUIFont::readPositions16bit(video::IImage* image, s32& lowerRightPositions)
{
core::dimension2d<s32> size = image->getDimension();
s16* p = (s16*)image->lock();
if (!p)
{
os::Printer::log("Could not lock texture while preparing texture for a font.", ELL_ERROR);
return;
}
// fix half alpha of top left pixel in some font textures
p[0] |= 0x8000;
s16 colorTopLeft = p[0];
s16 colorLowerRight = *(p+1);
s16 colorBackGround = *(p+2);
s16 colorBackGroundTransparent = 0; // 0x7FFF & colorBackGround;
*(p+1) = colorBackGround;
// start parsing
core::position2d<s32> pos(0,0);
for (pos.Y=0; pos.Y<size.Height; ++pos.Y)
{
for (pos.X=0; pos.X<size.Width; ++pos.X)
{
if (*p == colorTopLeft)
{
*p = colorBackGroundTransparent;
SpriteBank->getPositions().push_back(core::rect<s32>(pos, pos));
}
else
if (*p == colorLowerRight)
{
// too many lower right points
if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions)
{
image->unlock();
lowerRightPositions = 0;
return;
}
*p = colorBackGroundTransparent;
SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos;
// add frame to sprite bank
SGUISpriteFrame f;
f.rectNumber = lowerRightPositions;
f.textureNumber = 0;
SGUISprite s;
s.Frames.push_back(f);
s.frameTime = 0;
SpriteBank->getSprites().push_back(s);
// add character to font
SFontArea a;
a.overhang = 0;
a.underhang = 0;
a.spriteno = lowerRightPositions;
a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth();
Areas.push_back(a);
// map letter to character
//wchar_t ch = (wchar_t)(lowerRightPositions + 32);
wchar_t ch ;
if(m_pFontTemp != NULL)
ch = GetChar(lowerRightPositions);
else
ch = (wchar_t)(lowerRightPositions + 32);
CharacterMap.set(ch, lowerRightPositions);
++lowerRightPositions;
}
else
if (*p == colorBackGround)
*p = colorBackGroundTransparent;
++p;
}
}
// Positions parsed.
image->unlock();
}
//! returns the dimension of text
core::dimension2d<s32> CGUIFont::getDimension(const wchar_t* text) const
{
core::dimension2d<s32> dim(0, 0);
core::dimension2d<s32> thisLine(0, MaxHeight);
for (const wchar_t* p = text; *p; ++p)
{
bool lineBreak=false;
if (*p == L'\r') // Mac or Windows breaks
{
lineBreak = true;
if (p[1] == L'\n') // Windows breaks
++p;
}
else if (*p == L'\n') // Unix breaks
{
lineBreak = true;
}
if (lineBreak)
{
dim.Height += thisLine.Height;
if (dim.Width < thisLine.Width)
dim.Width = thisLine.Width;
thisLine.Width = 0;
continue;
}
const SFontArea &area = Areas[getAreaFromCharacter(*p)];
thisLine.Width += area.underhang;
thisLine.Width += area.width + area.overhang + GlobalKerningWidth;
}
dim.Height += thisLine.Height;
if (dim.Width < thisLine.Width)
dim.Width = thisLine.Width;
return dim;
}
//! set an Pixel Offset on Drawing ( scale position on width )
void CGUIFont::setKerningWidth ( s32 kerning )
{
GlobalKerningWidth = kerning;
}
//! set an Pixel Offset on Drawing ( scale position on width )
s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const
{
s32 ret = GlobalKerningWidth;
if (thisLetter)
{
ret += Areas[getAreaFromCharacter(*thisLetter)].overhang;
if (previousLetter)
{
ret += Areas[getAreaFromCharacter(*previousLetter)].underhang;
}
}
return ret;
}
//! set an Pixel Offset on Drawing ( scale position on height )
void CGUIFont::setKerningHeight ( s32 kerning )
{
GlobalKerningHeight = kerning;
}
//! set an Pixel Offset on Drawing ( scale position on height )
s32 CGUIFont::getKerningHeight () const
{
return GlobalKerningHeight;
}
//! returns the sprite number from a given character
u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const
{
return Areas[getAreaFromCharacter(*c)].spriteno;
}
s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const
{
core::map<wchar_t, s32>::Node* n = CharacterMap.find(c);
if (n)
return n->getValue();
else
return WrongCharacter;
}
/*
//! draws an text and clips it to the specified rectangle if wanted
void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
{
if (!Driver)
return;
core::dimension2d<s32> textDimension;
core::position2d<s32> offset = position.UpperLeftCorner;
if (hcenter || vcenter)
{
textDimension = getDimension(text);
if (hcenter)
offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X;
if (vcenter)
offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y;
}
core::array<s32> indices;
indices.reallocate(core::stringw(text).size());
u32 n;
while(*text)
{
n = (*text) - 32;
if ( n > Positions.size())
n = WrongCharacter;
indices.push_back(n);
++text;
}
Driver->draw2DImage(Texture, offset, Positions, indices, GlobalKerningWidth, clip, color, true);
}
*/
//! draws some text and clips it to the specified rectangle if wanted
void CGUIFont::draw(const wchar_t* text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
{
if (!Driver)
return;
core::dimension2d<s32> textDimension;
core::position2d<s32> offset = position.UpperLeftCorner;
core::rect<s32> pos;
if (hcenter || vcenter || clip)
textDimension = getDimension(text);
if (hcenter)
offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X;
if (vcenter)
offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y;
if (clip)
{
core::rect<s32> clippedRect(offset, textDimension);
clippedRect.clipAgainst(*clip);
if (!clippedRect.isValid())
return;
}
while(*text)
{
SFontArea& area = Areas[getAreaFromCharacter(*text)];
offset.X += area.underhang;
SpriteBank->draw2DSprite(area.spriteno, offset, clip, color);
offset.X += area.width + area.overhang + GlobalKerningWidth;
++text;
}
}
//! Calculates the index of the character in the text which is on a specific position.
s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
{
s32 x = 0;
s32 idx = 0;
while (text[idx])
{
const SFontArea& a = Areas[getAreaFromCharacter(text[idx])];
x += a.width + a.overhang + a.underhang;
if (x >= pixel_x)
return idx;
++idx;
}
return -1;
}
IGUISpriteBank* CGUIFont::getSpriteBank() const
{
return SpriteBank;
}
} // end namespace gui
} // end namespace irr
#endif // _IRR_COMPILE_WITH_GUI_
将 IGUIEnvironment.h
virtual IGUIFont* getFont(const c8* filename) = 0;
改为 virtual IGUIFont* getFont(const c8* filename,wchar_t *sFontName=NULL) = 0;
同样将 CGUIEnvironment.h
virtual IGUIFont* getFont(const c8* filename) = 0;
改为 virtual IGUIFont* getFont(const c8* filename,wchar_t *sFontName=NULL) = 0;
将CGUIEnvironment.cpp的getFont改为如下
//! returns the font
IGUIFont* CGUIEnvironment::getFont(const c8* filename,wchar_t *sFontName)
{
// search existing font
SFont f;
IGUIFont* ifont=0;
if (!filename)
f.Filename = "";
else
f.Filename = filename;
f.Filename.make_lower();
s32 index = Fonts.binary_search(f);
if (index != -1)
return Fonts[index].Font;
// font doesn't exist, attempt to load it
// does the file exist?
if (!FileSystem->existFile(filename))
{
os::Printer::log("Could not load font because the file does not exist", f.Filename.c_str(), ELL_ERROR);
return 0;
}
io::IXMLReader *xml = FileSystem->createXMLReader(filename);
if (xml)
{
// this is an XML font, but we need to know what type
EGUI_FONT_TYPE t = EGFT_CUSTOM;
bool found=false;
while(xml->read() && !found)
{
if (xml->getNodeType() == io::EXN_ELEMENT)
{
if (core::stringw(L"font") == xml->getNodeName())
{
if (core::stringw(L"vector") == xml->getAttributeValue(L"type"))
{
t = EGFT_VECTOR;
found=true;
}
else if (core::stringw(L"bitmap") == xml->getAttributeValue(L"type"))
{
t = EGFT_BITMAP;
found=true;
}
else found=true;
}
}
}
if (t==EGFT_BITMAP)
{
CGUIFont* font = new CGUIFont(this, filename);
ifont = (IGUIFont*)font;
// change working directory, for loading textures
core::stringc workingDir = FileSystem->getWorkingDirectory();
FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.Filename).c_str());
// load the font
if (!font->load(xml,sFontName))
{
font->drop();
font = 0;
ifont = 0;
}
// change working dir back again
FileSystem->changeWorkingDirectoryTo( workingDir.c_str());
}
else if (t==EGFT_VECTOR)
{
// todo: vector fonts
os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.Filename.c_str(), ELL_ERROR);
//CGUIFontVector* font = new CGUIFontVector(Driver);
//ifont = (IGUIFont*)font;
//if (!font->load(xml))
}
xml->drop();
}
if (!ifont)
{
CGUIFont* font = new CGUIFont(this, f.Filename.c_str());
ifont = (IGUIFont*)font;
if (!font->load(f.Filename.c_str(),sFontName))
{
font->drop();
return 0;
}
}
// add to fonts.
f.Font = ifont;
Fonts.push_back(f);
return ifont;
}
好了,我们可以使用了 ,在主函数里加入
IGUISkin* skin = env->getSkin();
IGUIFont* font = env->getFont("http://www.cnblogs.com/media/myfont0.bmp",L"宋体");//图片是刚才生成的图片,字体也是刚才字体工具上选中的字体
if (font)
skin->setFont(font);
skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);
最后CIrrDeviceWin32.cpp 里的WndProc里加入
case WM_IME_CHAR:
{
event.EventType = irr::EET_KEY_INPUT_EVENT;
event.KeyInput.PressedDown = true;
event.KeyInput.Key = irr::KEY_OEM_CLEAR ;
event.KeyInput.Shift = 0;
event.KeyInput.Control = 0;
char p1[2];
p1[0]=(char)((wParam&0xff00)>>8);
p1[1]=(char)(wParam&0xff);
if(p1[0]==0)
{
event.KeyInput.Char=(wchar_t)wParam;
}
else
//多字节代码转unicode
MultiByteToWideChar(CP_OEMCP,MB_PRECOMPOSED,p1,2,&(event.KeyInput.Char),1);
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
break;
}
用来支持中文输入
相关文章推荐
- 让irrlicht-1.4beta支持中文
- irrlicht引擎:中文支持
- [原创]IrrLicht-1.0中文支持
- irrlicht引擎:中文支持
- 让irrlicht支持中文输入和输出
- Irrlicht学习之添加中文的支持
- irrlicht 1.72 - svn版本中文支持解决办法
- irrlicht1.3中文支持
- 使用IrrlichtML让Irrlicht支持中文
- 让irrlicht 支持中文
- 让irrlicht 支持中文
- Irrlicht支持中文
- mysql 的 latin1 支持中文
- ubuntu添加gb18030等中文编码的支持
- 【web开发】spring+hibernate4支持中文排序
- ubuntu 9.10 开启tty中文支持及分辨率修改
- jsoncpp安装及对中文支持很好
- centOS 支持中文
- destoon学习记录(一)--支持中文的字符串切割函数
- common-fileupload:支持中文、大文件上传的上传组件