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

你可能感兴趣的:(GUI)