cegui中文显示问题

//----------------------------------------------------------------------------//
void FreeTypeFont::rasterise(utf32 start_codepoint, utf32 end_codepoint) const
{
CodepointMap::const_iterator s = d_cp_map.lower_bound(start_codepoint);
if (s == d_cp_map.end())
return;

CodepointMap::const_iterator orig_s = s;
CodepointMap::const_iterator e = d_cp_map.upper_bound(end_codepoint);
while (true)
{
// Create a new Imageset for glyphs
uint texsize = getTextureSize(s, e);
// If all glyphs were already rendered, do nothing
if (!texsize)
break;

Imageset& is = ImagesetManager::getSingleton().create(
d_name + "_auto_glyph_images_" + int (s->first),
System::getSingleton().getRenderer()->createTexture());
d_glyphImages.push_back(&is);

argb_t *mem_buffer = new argb_t [texsize * texsize];
memset(mem_buffer, 0, texsize * texsize * sizeof(argb_t));

uint x = INTER_GLYPH_PAD_SPACE, y = INTER_GLYPH_PAD_SPACE;
uint yb = INTER_GLYPH_PAD_SPACE;

bool finished = false;
bool forward = true;

while (s != d_cp_map.end())
{
// Check if we finished rendering all the required glyphs
finished ¦= (s == e);

// Check if glyph already rendered
if (!s->second.getImage())
{
// Render the glyph
if (FT_Load_Char(d_fontFace, s->first, FT_LOAD_RENDER ¦ FT_LOAD_FORCE_AUTOHINT ¦
(d_antiAliased ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO)))
{
std::stringstream err;
err << "Font::loadFreetypeGlyph - Failed to load glyph for codepoint: ";
err << static_cast<unsigned int>(s->first);
err << ". Will use an empty image for this glyph!";
Logger::getSingleton().logEvent(err.str(), Errors);

Rect area(0, 0, 0, 0);
Point offset(0, 0);
String name;
name += s->first;
is.defineImage(name, area, offset);
((FontGlyph &)s->second).setImage(&is.getImage(name));
float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);
((FontGlyph &)s->second).setAdvance(adv);
}
else
{
uint glyph_w = d_fontFace->glyph->bitmap.width + INTER_GLYPH_PAD_SPACE;
FT_Glyph_Metrics metrics = d_fontFace->glyph->metrics;
if (s->first == 32)
{
if(!FT_Load_Char (d_fontFace, 0x4e00, FT_LOAD_RENDER ¦ FT_LOAD_FORCE_AUTOHINT ¦ (d_antiAliased ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO)))
{
glyph_w = d_fontFace->glyph->bitmap.width + INTER_GLYPH_PAD_SPACE;
metrics = d_fontFace->glyph->metrics;
FT_Load_Char (d_fontFace, 32 , FT_LOAD_RENDER ¦ FT_LOAD_FORCE_AUTOHINT ¦ (d_antiAliased ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO));
}
}

uint glyph_h = d_fontFace->glyph->bitmap.rows + INTER_GLYPH_PAD_SPACE;
// Check if glyph right margin does not exceed texture size
uint x_next = x + glyph_w;
if (x_next > texsize)
{
x = INTER_GLYPH_PAD_SPACE;
x_next = x + glyph_w;
y = yb;
}

// Check if glyph bottom margine does not exceed texture size
uint y_bot = y + glyph_h;
if (y_bot > texsize)
break;

// Copy rendered glyph to memory buffer in RGBA format
drawGlyphToBuffer(mem_buffer + (y * texsize) + x, texsize);

// Create a new image in the imageset
Rect area(static_cast<float>(x),
static_cast<float>(y),
static_cast<float>(x + glyph_w - INTER_GLYPH_PAD_SPACE),
static_cast<float>(y + glyph_h - INTER_GLYPH_PAD_SPACE));

Point offset(metrics.horiBearingX * static_cast<float>(FT_POS_COEF),-d_fontFace->glyph->metrics.horiBearingY * static_cast<float>(FT_POS_COEF));

String name;
name += s->first;
is.defineImage(name, area, offset);
((FontGlyph &)s->second).setImage(&is.getImage(name));
float adv = metrics.horiAdvance * float(FT_POS_COEF);
((FontGlyph &)s->second).setAdvance(adv);

// Advance to next position
x = x_next;
if (y_bot > yb)
{
yb = y_bot;
}
}
}

// Go to next glyph, if we are going forward
if (forward)
if (++s == d_cp_map.end())
{
finished = true;
forward = false;
s = orig_s;
}
// Go to previous glyph, if we are going backward
if (!forward)
if ((s == d_cp_map.begin()) ¦¦ (--s == d_cp_map.begin()))
break;
}

is.getTexture()->loadFromMemory(mem_buffer, Size(texsize, texsize), Texture::PF_RGBA);
delete [] mem_buffer;

if (finished)
break;
}
}

// amount of bits in a uint
#define BITS_PER_UINT (sizeof (uint) * 8)
// must be a power of two
#define GLYPHS_PER_PAGE 256

//----------------------------------------------------------------------------//
const FontGlyph * FreeTypeFont::getGlyphData (utf32 codepoint)
{
/*if (codepoint > d_maxCodepoint)
return 0;

CodepointMap::const_iterator pos = d_hz_map.find(codepoint);
if (!d_hz_map[codepoint].getImage())
{
// Check if glyph page has been rasterised
uint page = codepoint / GLYPHS_PER_PAGE;
uint mask = 1 << (page & (BITS_PER_UINT - 1));
if (!(d_glyphPageLoaded[page / BITS_PER_UINT] & mask))
{
d_glyphPageLoaded[page / BITS_PER_UINT] ¦= mask;
rasteriseHZ(codepoint);
//}
}*/

if(codepoint < 256) //决定保留一张纹理放英文和字符

{

if (!m_Words)

{

/*uint page = codepoint / GLYPHS_PER_PAGE;

uint mask = 1 << (page & (BITS_PER_UINT - 1));

if (!(d_glyphPageLoaded [page / BITS_PER_UINT] & mask))

{}

d_glyphPageLoaded [page / BITS_PER_UINT] ¦= mask;*/

rasterise (codepoint & ~(GLYPHS_PER_PAGE - 1),

codepoint ¦ (GLYPHS_PER_PAGE - 1));

m_Words = true;

}

CodepointMap::const_iterator pos = d_cp_map.find (codepoint);

return (pos != d_cp_map.end()) ? &pos->second : 0;

}

else //显示汉字啦

{

CodepointMap::const_iterator pos;

pos = d_hz_map.find (codepoint);

if(pos != d_hz_map.end())

{

return (pos != d_hz_map.end()) ? &pos->second : 0;

}

else

{

rasteriseHZ(codepoint);

pos = d_hz_map.find (codepoint);

return (pos != d_hz_map.end()) ? &pos->second : 0;

}

}
}

//----------------------------------------------------------------------------//
void FreeTypeFont::rasteriseHZ(utf32 codepoint)
{
uint texsize = 512;

if(d_hz_map.size() == 0)
{
hzImageset = &(ImagesetManager::getSingleton ().create(d_name + "_auto_glyph_images_" + int (codepoint),System::getSingleton().getRenderer ()->createTexture ()));
hzmem_buffer = new argb_t[texsize * texsize];
memset(hzmem_buffer, 0, texsize * texsize * sizeof(argb_t));

m_nHZX = m_nHZY = m_nHZYB = INTER_GLYPH_PAD_SPACE;
}

/*//d_hz_map.clear();

//ImagesetManager::getSingleton ().destroy(hzImageset->getName());

hzImageset = &(ImagesetManager::getSingleton ().create(

d_name + "_auto_glyph_images_" ,

System::getSingleton ().getRenderer ()->createTexture ());)

//d_glyphImages.push_back (hzImageset);

float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);

d_hz_map[codepoint] = FontGlyph(adv);*/

d_hz_map[codepoint] = FontGlyph (0.0f);

CodepointMap::const_iterator hzInter = d_hz_map.find(codepoint);

if (!hzInter->second.getImage())

{
if (FT_Load_Char (d_fontFace, hzInter->first, FT_LOAD_RENDER ¦ FT_LOAD_FORCE_AUTOHINT ¦ (d_antiAliased ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO)))

{

std::stringstream err;

err << "Font::loadFreetypeGlyph - Failed to load glyph for codepoint: ";

err << static_cast<unsigned int> (hzInter->first);

err << ". Will use an empty image for this glyph!";

Logger::getSingleton ().logEvent (err.str (), Errors);

// Create a 'null' image for this glyph so we do not seg later

Rect area(0, 0, 0, 0);

Point offset(0, 0);

String name;

name += hzInter->first;

hzImageset->defineImage(name, area, offset);

((FontGlyph &)hzInter->second).setImage(&hzImageset->getImage(name));
float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);

d_hz_map[codepoint].setAdvance(adv);

}

else

{
uint glyph_w = d_fontFace->glyph->bitmap.width + INTER_GLYPH_PAD_SPACE;

uint glyph_h = d_fontFace->glyph->bitmap.rows + INTER_GLYPH_PAD_SPACE;

// Check if glyph right margin does not exceed texture size

uint x_next = m_nHZX + glyph_w;

if (x_next > texsize)

{

m_nHZX = INTER_GLYPH_PAD_SPACE;

x_next = m_nHZX + glyph_w;

m_nHZY = m_nHZYB;

}

// Check if glyph bottom margine does not exceed texture size

uint y_bot = m_nHZY + glyph_h;

if (y_bot > texsize)
{
hzImageset = &(ImagesetManager::getSingleton ().create(d_name + "_auto_glyph_images_" + int (codepoint),System::getSingleton().getRenderer ()->createTexture ()));
hzmem_buffer = new argb_t[texsize * texsize];
memset(hzmem_buffer, 0, texsize * texsize * sizeof(argb_t));

m_nHZX = m_nHZY = m_nHZYB = INTER_GLYPH_PAD_SPACE;
}

// Copy rendered glyph to memory buffer in RGBA format

drawGlyphToBuffer (hzmem_buffer + (m_nHZY * texsize) + m_nHZX, texsize);

// Create a new image in the imageset

Rect area(static_cast<float>(m_nHZX),

static_cast<float>(m_nHZY),

static_cast<float>(m_nHZX + glyph_w - INTER_GLYPH_PAD_SPACE),

static_cast<float>(m_nHZY + glyph_h - INTER_GLYPH_PAD_SPACE));

Point offset(d_fontFace->glyph->metrics.horiBearingX * static_cast<float>(FT_POS_COEF),

-d_fontFace->glyph->metrics.horiBearingY * static_cast<float>(FT_POS_COEF));

String name;

name += hzInter->first;

hzImageset->defineImage (name, area, offset);

((FontGlyph &)hzInter->second).setImage (&hzImageset->getImage (name));
float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);
((FontGlyph &)hzInter->second).setAdvance(adv);

// Advance to next position

m_nHZX = x_next;

if (y_bot > m_nHZYB)
{
m_nHZYB = y_bot;
}

}

}

// Copy our memory buffer into the texture and free it

hzImageset->getTexture ()->loadFromMemory (hzmem_buffer, CEGUI::Size(texsize,texsize), Texture::PF_RGBA);

}

//----------------------------------------------------------------------------//
void FreeTypeFont::drawGlyphToBuffer(argb_t *buffer, uint buf_width) const
{
FT_Bitmap *glyph_bitmap = &d_fontFace->glyph->bitmap;

for (int i = 0; i < glyph_bitmap->rows; ++i)
{
uchar *src = glyph_bitmap->buffer + (i * glyph_bitmap->pitch);
switch (glyph_bitmap->pixel_mode)
{
case FT_PIXEL_MODE_GRAY:
{
uchar *dst = reinterpret_cast<uchar*>(buffer);
for (int j = 0; j < glyph_bitmap->width; ++j)
{
// RGBA
*dst++ = mColour.r;
*dst++ = mColour.g;
*dst++ = mColour.b;
*dst++ = (*src++);
}
}
break;

case FT_PIXEL_MODE_MONO:
for (int j = 0; j < glyph_bitmap->width; ++j)
buffer [j] = (src [j / 8] & (0x80 >> (j & 7))) ? 0xFFFFFFFF : 0x00000000;
break;

default:
CEGUI_THROW(InvalidRequestException("Font::drawGlyphToBuffer: "
"The glyph could not be drawn because the pixel mode is "
"unsupported."));
break;
}

buffer += buf_width;
}
}

//----------------------------------------------------------------------------//
void FreeTypeFont::free()
{
if (!d_fontFace)
return;

d_cp_map.clear();

for (size_t i = 0; i < d_glyphImages.size(); i++)
ImagesetManager::getSingleton().destroy(d_glyphImages [i]->getName());
d_glyphImages.clear();

FT_Done_Face(d_fontFace);
d_fontFace = 0;
System::getSingleton().getResourceProvider()->unloadRawDataContainer(d_fontData);
}

//----------------------------------------------------------------------------//
void FreeTypeFont::updateFont()
{
//free();

System::getSingleton().getResourceProvider()->loadRawDataContainer(
d_filename, d_fontData, d_resourceGroup.empty() ?
getDefaultResourceGroup() : d_resourceGroup);

FT_Error error;

// create face using input font
if ((error = FT_New_Memory_Face(ft_lib, d_fontData.getDataPtr(),
static_cast<FT_Long>(d_fontData.getSize()), 0,
&d_fontFace)) != 0)
CEGUI_THROW(GenericException("FreeTypeFont::updateFont: Failed to "
"create face from font file '" + d_filename + "' error was: " +
((error < FT_Err_Max) ? ft_errors[error] : "unknown error")));

// check that default Unicode character map is available
if (!d_fontFace->charmap)
{
FT_Done_Face(d_fontFace);
d_fontFace = 0;
CEGUI_THROW(GenericException("FreeTypeFont::updateFont: "
"The font '" + d_name + "' does not have a Unicode charmap, and "
"cannot be used."));
}

uint horzdpi = System::getSingleton().getRenderer()->getDisplayDPI().d_x;
uint vertdpi = System::getSingleton().getRenderer()->getDisplayDPI().d_y;

float hps = d_ptSize * 64;
float vps = d_ptSize * 64;
if (d_autoScale)
{
hps *= d_horzScaling;
vps *= d_vertScaling;
}

if (FT_Set_Char_Size(d_fontFace, FT_F26Dot6(hps), FT_F26Dot6(vps), horzdpi, vertdpi))
{
// For bitmap fonts we can render only at specific point sizes.
// Try to find nearest point size and use it, if that is possible
float ptSize_72 = (d_ptSize * 72.0f) / vertdpi;
float best_delta = 99999;
float best_size = 0;
for (int i = 0; i < d_fontFace->num_fixed_sizes; i++)
{
float size = d_fontFace->available_sizes [i].size * float(FT_POS_COEF);
float delta = fabs(size - ptSize_72);
if (delta < best_delta)
{
best_delta = delta;
best_size = size;
}
}

if ((best_size <= 0) ¦¦
FT_Set_Char_Size(d_fontFace, 0, FT_F26Dot6(best_size * 64), 0, 0))
{
char size [20];
snprintf(size, sizeof(size), "%g", d_ptSize);
CEGUI_THROW(GenericException("FreeTypeFont::load - The font '" + d_name + "' cannot be rasterised at a size of " + size + " points, and cannot be used."));
}
}

if (d_fontFace->face_flags & FT_FACE_FLAG_SCALABLE)
{
//float x_scale = d_fontFace->size->metrics.x_scale * FT_POS_COEF * (1.0/65536.0);
float y_scale = d_fontFace->size->metrics.y_scale * float(FT_POS_COEF) * (1.0f / 65536.0f);
d_ascender = d_fontFace->ascender * y_scale;
d_descender = d_fontFace->descender * y_scale;
d_height = d_fontFace->height * y_scale;
}
else
{
d_ascender = d_fontFace->size->metrics.ascender * float(FT_POS_COEF);
d_descender = d_fontFace->size->metrics.descender * float(FT_POS_COEF);
d_height = d_fontFace->size->metrics.height * float(FT_POS_COEF);
}

if (d_specificLineSpacing > 0.0f)
{
d_height = d_specificLineSpacing;
}
if (!m_Words)
{
// Create an empty FontGlyph structure for every glyph of the font
FT_UInt gindex;
FT_ULong codepoint = FT_Get_First_Char(d_fontFace, &gindex);
FT_ULong max_codepoint = codepoint;

while (gindex)
{
if (max_codepoint < codepoint)
max_codepoint = codepoint;

// load-up required glyph metrics (don't render)
/* if (FT_Load_Char(d_fontFace, codepoint,
FT_LOAD_DEFAULT ¦ FT_LOAD_FORCE_AUTOHINT))
continue; // glyph error

float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);*/

// create a new empty FontGlyph with given character code
if(codepoint < 256)
d_cp_map[codepoint] = FontGlyph(0.0f);

// proceed to next glyph
codepoint = FT_Get_Next_Char(d_fontFace, codepoint, &gindex);
}

setMaxCodepoint(max_codepoint);
}
}


转载至:
http://lisuyong.com/2010/06/10/cegui
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值