- 注册时间
- 2004-11-1
- 最后登录
- 2018-4-24
版主
- 积分
- 548
|
用到的是日本人Zgock做的TrueType类库,CGUITTFont
原来支持的是dx8的,我机子上没有,所以改了一下,支持dx9,需要opengl也可以自己动手。
这是基于FreeType开发的,因此得去下FreeType的支持库。http://www.freetype.org/
我用的是自己编译的静态连接库,编译后的exe大约是多了250K左右。
个人觉得,这样至少比多带一个dll看起来舒服一点。
-----------------------main.cpp代码-------------------------------------------
#include <windows.h>
#include <irrlicht.h>
#include <CGUITTFont.h>
using namespace irr;
using namespace core;
using namespace video;
using namespace gui;
#pragma comment (lib, "Irrlicht.lib") //irrlicht的库文件
#pragma comment (lib, "freetype221.lib") //freetype的库文件
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
{
IrrlichtDevice *Device = createDevice(EDT_DIRECT3D9, dimension2d<s32>(400, 300),16, false, false, 0);//这里用的是dx9
Device->setWindowCaption(L"这是一个显示简体中文的简单例子");
IVideoDriver *Driver = Device->getVideoDriver();
CGUITTFace face;
face.load("C:\\windows\\fonts\\simsun.ttc"); //载入字体,这里用的是微软的宋体
CGUITTFont *Font = new CGUITTFont(Driver);
Font->attach(&face,26); //字体大小
Font->AntiAlias = true; //反锯齿,使得字体显示更好看
while(Device->run())
{
Driver->beginScene(true, true, SColor(0,100,100,100));
Font->draw(L"Hello World !",rect<s32>(50,50,0,0),SColor(255,255,0,0)); //SColor格式似乎是ARGB
Font->draw(L"你好 世界!",rect<s32>(50,100,0,0),SColor(255,0,255,0));
Driver->endScene();
}
Device->drop(); //释放资源
return 0;
}
----------------------------------------------------------------------
但是这样只是支持了中文的显示,对于中文输入还是不行。
估计那要去改irr::gui里面的东西了,不懂了,而且没找到现成的解决办法。 [s:6]
ps:没法上传附件,干脆用文本传了。
-----------CGUITTFont.h-----------------
#ifndef __C_GUI_TTFONT_H_INCLUDED__
#define __C_GUI_TTFONT_H_INCLUDED__
#include <ft2build.h>
#include <freetype/freetype.h>
#include <irrlicht.h>
namespace irr
{
namespace gui
{
class CGUITTFace : public IUnknown
{
public:
FT_Library library;
FT_Face face;
bool load(const c8* filename);
};
class CGUITTGlyph : public IUnknown
{
public:
bool cached;
video::IVideoDriver* Driver;
CGUITTGlyph();
virtual ~CGUITTGlyph();
void cache(u32 idx);
FT_Face *face;
u32 size;
u32 top;
u32 left;
u32 texw;
u32 texh;
u32 imgw;
u32 imgh;
video::ITexture *tex;
u32 top16;
u32 left16;
u32 texw16;
u32 texh16;
u32 imgw16;
u32 imgh16;
video::ITexture *tex16;
s32 offset;
u8 *image;
};
class CGUITTFont : public IGUIFont
{
public:
//! constructor
CGUITTFont(video::IVideoDriver* Driver);
//! destructor
virtual ~CGUITTFont();
//! loads a truetype font file
bool attach(CGUITTFace *Face,u32 size);
//! 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);
//! 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);
bool AntiAlias;
bool TransParency;
private:
s32 CGUITTFont::getWidthFromCharacter(wchar_t c);
u32 getGlyphByChar(wchar_t c);
video::IVideoDriver* Driver;
core::array< CGUITTGlyph > Glyphs;
CGUITTFace *tt_face;
};
} // end namespace gui
} // end namespace irr
#endif
-----------------CGUITTFont.h----------------------------------
-----------------CGUITTFont.cpp-------------------------------
#include "irrlicht.h"
#include "CGUITTFont.h"
namespace irr
{
namespace gui
{
CGUITTGlyph::CGUITTGlyph() : IUnknown()
{
tex = NULL;
image = NULL;
}
CGUITTGlyph::~CGUITTGlyph()
{
if (image) delete image;
// if (tex) Driver->removeTexture(tex);
}
void CGUITTGlyph::cache(u32 idx)
{
FT_Set_Pixel_Sizes(*face,0,size);
if (!FT_Load_Glyph(*face,idx,FT_LOAD_NO_HINTING|FT_LOAD_NO_BITMAP)){
FT_GlyphSlot glyph = (*face)->glyph;
FT_Bitmap bits;
if (glyph->format == ft_glyph_format_outline ){
if (!FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL)){
bits = glyph->bitmap;
u8 *pt = bits.buffer;
image = new u8[bits.width * bits.rows];
memcpy(image,pt,bits.width * bits.rows);
top = glyph->bitmap_top;
left = glyph->bitmap_left;
imgw = 1;
imgh = 1;
texw = bits.width;
texh = bits.rows;
for(;;){
if (imgw > texw){
break;
} else {
imgw <<= 1;
}
}
for(;;){
if (imgh > texh){
break;
} else {
imgh <<= 1;
}
}
if (imgw > imgh){
imgh = imgw;
} else {
imgw = imgh;
}
u32 *texd = new u32[imgw*imgh];
memset(texd,0,imgw*imgh*sizeof(u32));
u32 *texp = texd;
offset = size - bits.rows;
bool cflag = (Driver->getDriverType() == video::EDT_DIRECT3D9);
for (int i = 0;i < bits.rows;i++){
u32 *rowp = texp;
for (int j = 0;j < bits.width;j++){
if (*pt){
if (cflag){
*rowp = *pt;
*rowp *= 0x01010101;
} else {
*rowp = *pt << 24;
*rowp |= 0xffffff;
}
} else {
*rowp = 0;
}
pt++;
rowp++;
}
texp += imgw;
}
c8 name[128];
sprintf(name,"TTFontGlyph%d",idx);
video::IImage *img = Driver->createImageFromData(video::ECF_A8R8G8B8,core::dimension2d<s32>(imgw,imgh),texd);
bool flg16 = Driver->getTextureCreationFlag(video::ETCF_ALWAYS_16_BIT);
bool flg32 = Driver->getTextureCreationFlag(video::ETCF_ALWAYS_32_BIT);
Driver->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT,false);
Driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
tex = Driver->addTexture(name,img);
Driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,flg32);
Driver->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT,flg16);
delete texd;
cached = true;
}
}
}
if (!FT_Load_Glyph(*face,idx,FT_LOAD_NO_HINTING|FT_LOAD_RENDER|FT_LOAD_MONOCHROME)){
FT_GlyphSlot glyph = (*face)->glyph;
FT_Bitmap bits = glyph->bitmap;
u8 *pt = bits.buffer;
top16 = glyph->bitmap_top;
left16 = glyph->bitmap_left;
imgw16 = 1;
imgh16 = 1;
texw16 = bits.width;
texh16 = bits.rows;
for(;;){
if (imgw16 >= texw16){
break;
} else {
imgw16 <<= 1;
}
}
for(;;){
if (imgh16 >= texh16){
break;
} else {
imgh16 <<= 1;
}
}
if (imgw16 > imgh16){
imgh16 = imgw16;
} else {
imgw16 = imgh16;
}
u16 *texd16 = new u16[imgw16*imgh16];
memset(texd16,0,imgw16*imgh16*sizeof(u16));
u16 *texp16 = texd16;
offset = size - bits.rows;
for (int y = 0;y < bits.rows;y++){
u16 *rowp = texp16;
for (int x = 0;x < bits.width;x++){
if (pt[y * bits.pitch + (x / 8)] & (0x80 >> (x % 8))){
*rowp = 0xffff;
}
rowp++;
}
texp16 += imgw16;
}
c8 name[128];
sprintf(name,"TTFontGlyph%d_16",idx);
video::IImage *img = Driver->createImageFromData(video::ECF_A1R5G5B5,core::dimension2d<s32>(imgw16,imgh16),texd16);
tex16 = Driver->addTexture(name,img);
Driver->makeColorKeyTexture(tex16,video::SColor(0,0,0,0));
delete texd16;
}
}
//! constructor
CGUITTFont::CGUITTFont(video::IVideoDriver* driver)
: Driver(driver)
{
#ifdef _DEBUG
setDebugName("CGUITTFont");
#endif
if (Driver)
Driver->grab();
AntiAlias = false;
TransParency = false;
}
//! destructor
CGUITTFont::~CGUITTFont()
{
if (Driver)
Driver->drop();
}
//! loads a font file
bool CGUITTFace::load(const c8* filename)
{
if (FT_Init_FreeType( &library )){
return false;
}
if (FT_New_Face( library,filename,0,&face )){
return false;
}
return true;
}
bool CGUITTFont::attach(CGUITTFace *Face,u32 size)
{
if (!Driver)
return false;
tt_face = Face;
Glyphs.reallocate(tt_face->face->num_glyphs);
Glyphs.set_used(tt_face->face->num_glyphs);
for (int i = 0;i < tt_face->face->num_glyphs;i++){
Glyphs.Driver = Driver;
Glyphs.size = size;
Glyphs.face = &(tt_face->face);
Glyphs.cached = false;
// Glyphs.cache((wchar_t)i + 1);
}
return true;
}
u32 CGUITTFont::getGlyphByChar(wchar_t c){
u32 idx = FT_Get_Char_Index( tt_face->face, c );
if (idx && !Glyphs[idx - 1].cached) Glyphs[idx - 1].cache(idx);
return idx;
}
//! returns the dimension of a text
core::dimension2d<s32> CGUITTFont::getDimension(const wchar_t* text)
{
core::dimension2d<s32> dim(0, Glyphs[0].size);
for(const wchar_t* p = text; *p; ++p)
{
dim.Width += getWidthFromCharacter(*p);
}
return dim;
}
inline s32 CGUITTFont::getWidthFromCharacter(wchar_t c)
{
u32 n = getGlyphByChar(c);
if ( n > 0){
int w = Glyphs[n - 1].texw;
s32 left = Glyphs[n - 1].left;
if (w + left > 0) return w + left;
}
if (c >= 0x2000){
return Glyphs[0].size;
} else {
return Glyphs[0].size / 2;
}
}
//! draws an text and clips it to the specified rectangle if wanted
void CGUITTFont::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;
video::SColor colors[4];
for (int i = 0;i < 4;i++){
colors = color;
}
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;
}
u32 n;
while(*text)
{
n = getGlyphByChar(*text);
if ( n > 0){
if (AntiAlias){
s32 imgw = Glyphs[n-1].imgw;
s32 imgh = Glyphs[n-1].imgh;
s32 texw = Glyphs[n-1].texw;
s32 texh = Glyphs[n-1].texh;
s32 offx = Glyphs[n-1].left;
s32 offy = Glyphs[n-1].size - Glyphs[n-1].top;
if (Driver->getDriverType() != video::EDT_SOFTWARE){
if (!TransParency) color.color |= 0xff000000;
Driver->draw2DImage(Glyphs[n-1].tex,core::position2d<s32>(offset.X+offx,offset.Y+offy),core::rect<s32>(0,0,imgw-1,imgh-1),clip,color,true);
} else {
s32 a = color.getAlpha();
s32 r = color.getRed();
s32 g = color.getGreen();
s32 b = color.getBlue();
u8 *pt = Glyphs[n-1].image;
if (!TransParency) a = 255;
for (int y = 0;y < texh;y++){
for (int x = 0;x < texw;x++){
if (!clip || clip->isPointInside(core::position2d<s32>(offset.X+x+offx,offset.Y+y+offy))){
if (*pt){
Driver->draw2DRectangle(video::SColor((a * *pt)/255,r,g,b),core::rect<s32>(offset.X+x+offx,offset.Y+y+offy,offset.X+x+offx+1,offset.Y+y+offy+1));
}
pt++;
}
}
}
}
} else {
s32 imgw = Glyphs[n-1].imgw16;
s32 imgh = Glyphs[n-1].imgh16;
s32 texw = Glyphs[n-1].texw16;
s32 texh = Glyphs[n-1].texh16;
s32 offx = Glyphs[n-1].left16;
s32 offy = Glyphs[n-1].size - Glyphs[n-1].top16;
if (!TransParency){
color.color |= 0xff000000;
}
Driver->draw2DImage(Glyphs[n-1].tex16,core::position2d<s32>(offset.X+offx,offset.Y+offy),core::rect<s32>(0,0,imgw-1,imgh-1),clip,color,true);
}
offset.X += getWidthFromCharacter(*text);
} else {
offset.X += getWidthFromCharacter(*text);
}
++text;
}
}
//! Calculates the index of the character in the text which is on a specific position.
s32 CGUITTFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x)
{
s32 x = 0;
s32 idx = 0;
while (text[idx])
{
x += getWidthFromCharacter(text[idx]);
if (x >= pixel_x)
return idx;
++idx;
}
return -1;
}
#if 0
#endif
} // end namespace gui
} // end namespace irr
-----------------------CGUITTFont.cpp---------------------------- |
|