//----------------------------------------------------------------------------//
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) *
// 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
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) *
// 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
发表评论
-
跨浏览器插件框架FireBreath安装与使用之一——Windows下的插件
2013-12-23 16:58 1924跨浏览器插件框架FireBreath安装与使用之一——Win ... -
activex插件被拦截
2013-07-11 10:56 608win7,IE7、8、9都会有提示 “此网页需要运行以下加 ... -
游戏性能分析工具
2013-07-10 18:54 761PerfHUD dx 游戏性能分析工具 vtune ... -
重放攻击及防御方案
2013-07-01 18:24 2213什么是重放攻击 所谓重放攻击就是攻击者发送一个目的主 ... -
跨浏览器插件技术
2013-05-20 11:36 780firebreath -
如何制作网页安全登录控件
2013-05-08 15:17 1164什么是安全控件和安全控件如何安全这不是本文要讨论的范围 ... -
Ansi、Unicode、UTF8字符串之间的转换,wprintf
2013-05-08 10:03 1466Ansi字符串我们最熟悉,英文占一个字节,汉字2个字节,以 ... -
CEGUI与其他程序剪切复制粘帖的实现(支持中文)~~~
2013-05-07 14:33 767void xx() { using namespace CE ... -
npapi开发
2013-05-07 10:30 2391前面一段时间关注了用f ...
相关推荐
这个“CEGUI中文显示和输入Demo”是一个示例项目,旨在展示如何在使用CEGUI库时实现中文字符的正确显示和输入。在深入探讨这个Demo之前,我们先了解CEGUI的基础知识。 CEGUI是一个灵活且可扩展的图形用户界面系统,...
然而,直接在CEGUI的窗口中使用setText()函数传递UTF-8编码的中文字符串可能会遇到显示问题。以下是如何在CEGUI中正确显示汉字的详细步骤和相关知识点: 1. **字体资源**:首先,你需要一个包含中文字符的字体文件...
对于CEGUI的中文显示问题,有两种主要的处理方式。一种是在使用CELayoutEditor设计界面并导出为XML文件后,通过文本编辑器进行汉化,然后保存为UTF-8编码。另一种是在程序中动态显示中文,需要利用Windows API中的...
在进行CEGUI修改时,开发者可能会遇到的问题包括:性能优化(如减少内存消耗和提高渲染速度)、本地化支持(如添加中文处理)、兼容性问题(与不同的图形库或操作系统)、以及自定义组件的开发等。每个提供的压缩...
由于CEGUI支持中文显示,如果用Irrlicht做漂亮中文界面显示,CEGUI可能是目前最好的解决方法。CEGUI如何支持中文显示输入见网上相关文章。http://blog.csdn.net/sunxiaoju/article/details/51010080
在默认情况下,CEGUI依赖于特定的字体和字符集,这可能不包含中文字符,导致无法正确显示和输入中文。 要实现CEGUI的中文输入,我们需要解决以下几个关键问题: 1. **字体支持**:CEGUI允许用户自定义字体,我们...
以下是对CEGUI文档中文版的部分内容的详细解释: ### 渲染入门 在CEGUI中,渲染是通过`CEGUI::Renderer`对象完成的,它是CEGUI系统与底层图形API(如OpenGL或Direct3D)之间的桥梁。要开始使用CEGUI,首先你需要...
在`initialiseSample`方法中,你可能会看到创建和添加CEGUI窗口元素的代码,比如创建一个背景和一个静态文本,显示"Hello! CEGUI"。这些操作通常涉及到CEGUI的事件处理、布局管理以及渲染逻辑。 在主函数`main`中,...
1.由于整个 CEGUI-0.7.4 及 dependencies 太大。只上传与输入法相关的代码和资源。 2.找个新的 CEGUI-0.7.4 SDK 然后把附件的代码资源直接覆盖。然后编译跑起来既可以。...3.前提是你的CEGUI-0.7.4 能显示中文
首先,解决CEGUI中的中文显示问题。这通常涉及到创建和设置合适的字体。笔记中提到了两种方法: 1. 创建FreeType字体:通过`CEGUI::FontManager::getSingleton().createFreeTypeFont()`函数创建一个名为“Default...
4. "OGRE中文解决例子 支持中文":提供了解决OGRE显示中文问题的方法或示例代码。 5. "OGRE 3D 程序设计 lj少4篇":这可能是一系列介绍OGRE 3D编程的文章,作者为lj少。 6. "OGRE简单教程":包含基础的OGRE教程,...