Port font to use new texture format

This commit is contained in:
Benau 2017-01-06 18:20:19 +08:00
parent 4bcf03e296
commit 2af126357d
5 changed files with 41 additions and 112 deletions

View File

@ -104,6 +104,8 @@ public:
{
}
virtual ~ITexture() {}
//! Lock function.
/** Locks the Texture and returns a pointer to access the
pixels. After lock() has been called and all operations on the pixels

View File

@ -23,6 +23,8 @@
#include "font/font_settings.hpp"
#include "graphics/2dutils.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/stk_texture.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/skin.hpp"
#include "utils/string_utils.hpp"
@ -50,8 +52,6 @@ FontWithFace::FontWithFace(const std::string& name, FaceTTF* ttf)
*/
FontWithFace::~FontWithFace()
{
m_page->drop();
m_page = NULL;
m_spritebank->drop();
m_spritebank = NULL;
@ -66,9 +66,6 @@ FontWithFace::~FontWithFace()
void FontWithFace::init()
{
setDPI();
m_page = irr_driver->getVideoDriver()->createImage(video::ECF_A8R8G8B8,
core::dimension2du(getGlyphPageSize(), getGlyphPageSize()));
// Get the max height for this face
assert(m_face_ttf->getTotalFaces() > 0);
FT_Face cur_face = m_face_ttf->getFace(0);
@ -129,32 +126,17 @@ void FontWithFace::loadGlyphInfo(wchar_t c)
*/
void FontWithFace::createNewGlyphPage()
{
m_page->fill(video::SColor(0, 255, 255, 255));
video::IImage* glyph = irr_driver->getVideoDriver()
->createImage(video::ECF_A8R8G8B8,
core::dimension2du(getGlyphPageSize(), getGlyphPageSize()));
glyph->fill(video::SColor(0, 255, 255, 255));
m_current_height = 0;
m_used_width = 0;
m_used_height = 0;
// Font textures can not be resized (besides the impact on quality in
// this case, the rectangles in spritebank would become wrong).
core::dimension2du old_max_size = irr_driver->getVideoDriver()
->getDriverAttributes().getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
irr_driver->getVideoDriver()->getNonConstDriverAttributes()
.setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(0, 0));
video::ITexture* page_texture = irr_driver->getVideoDriver()
->addTexture("Glyph_page", m_page);
m_spritebank->addTexture(NULL);
m_spritebank->setTexture(m_spritebank->getTextureCount() - 1,
page_texture);
// Doing so to make sure the texture inside the sprite bank has only 1
// reference, so they can be removed or updated on-the-fly
irr_driver->getVideoDriver()->removeTexture(page_texture);
assert(page_texture->getReferenceCount() == 1);
irr_driver->getVideoDriver()->getNonConstDriverAttributes()
.setAttribute("MAX_TEXTURE_SIZE", old_max_size);
STKTexture* stkt = new STKTexture(glyph, typeid(*this).name() +
StringUtils::toString(m_spritebank->getTextureCount()));
m_spritebank->addTexture(stkt);
STKTexManager::getInstance()->addTexture(stkt);
} // createNewGlyphPage
// ----------------------------------------------------------------------------
@ -164,6 +146,7 @@ void FontWithFace::createNewGlyphPage()
*/
void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
{
#ifndef SERVER_ONLY
assert(gi.glyph_index > 0);
assert(gi.font_number < m_face_ttf->getTotalFaces());
FT_Face cur_face = m_face_ttf->getFace(gi.font_number);
@ -198,29 +181,12 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
getGlyphPageSize()) ||
m_used_height + texture_size.Height > getGlyphPageSize())
{
// Current glyph page is full:
// Save the old glyph page
core::dimension2du old_max_size = irr_driver->getVideoDriver()
->getDriverAttributes().getAttributeAsDimension2d
("MAX_TEXTURE_SIZE");
irr_driver->getVideoDriver()->getNonConstDriverAttributes()
.setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(0, 0));
video::ITexture* page_texture = irr_driver->getVideoDriver()
->addTexture("Glyph_page", m_page);
m_spritebank->setTexture(m_spritebank->getTextureCount() - 1,
page_texture);
irr_driver->getVideoDriver()->removeTexture(page_texture);
assert(page_texture->getReferenceCount() == 1);
irr_driver->getVideoDriver()->getNonConstDriverAttributes()
.setAttribute("MAX_TEXTURE_SIZE", old_max_size);
// Clear and add a new one
// Add a new glyph page if current one is full
createNewGlyphPage();
}
video::IImage* glyph = NULL;
unsigned int* image_data = NULL;
switch (bits.pixel_mode)
{
case FT_PIXEL_MODE_GRAY:
@ -234,7 +200,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
const float gray_count = static_cast<float>(bits.num_grays);
const unsigned int image_pitch =
glyph->getPitch() / sizeof(unsigned int);
unsigned int* image_data = (unsigned int*)glyph->lock();
image_data = (unsigned int*)glyph->lock();
unsigned char* glyph_data = bits.buffer;
for (unsigned int y = 0; y < (unsigned int)bits.rows; y++)
@ -254,8 +220,11 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
default:
assert(false);
}
if (!glyph)
Log::fatal("FontWithFace", "Failed to load a glyph");
if (glyph == NULL)
{
Log::warn("FontWithFace", "Failed to load a glyph");
return;
}
// Done creating a single glyph, now copy to the glyph page...
// Determine the linebreak location
@ -266,8 +235,20 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
m_current_height = 0;
}
// Copy to the full glyph page
glyph->copyTo(m_page, core::position2di(m_used_width, m_used_height));
const unsigned int cur_tex = m_spritebank->getTextureCount() -1;
video::ITexture* tex = m_spritebank->getTexture(cur_tex);
glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
unsigned int format = GL_BGRA;
#if defined(USE_GLES2)
if (!CVS->isEXTTextureFormatBGRA8888Usable())
format = GL_RGBA;
#endif
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
texture_size.Width, texture_size.Height, format, GL_UNSIGNED_BYTE,
image_data);
if (tex->hasMipMaps())
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// Store the rectangle of current glyph
gui::SGUISpriteFrame f;
@ -275,7 +256,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
core::rect<s32> rectangle(m_used_width, m_used_height,
m_used_width + bits.width, m_used_height + bits.rows);
f.rectNumber = m_spritebank->getPositions().size();
f.textureNumber = m_spritebank->getTextureCount() - 1;
f.textureNumber = cur_tex;
// Add frame to sprite
s.Frames.push_back(f);
@ -303,6 +284,7 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
m_used_width += texture_size.Width;
if (m_current_height < texture_size.Height)
m_current_height = texture_size.Height;
#endif
} // insertGlyph
// ----------------------------------------------------------------------------
@ -321,23 +303,6 @@ void FontWithFace::updateCharactersList()
}
m_new_char_holder.clear();
// Update last glyph page
core::dimension2du old_max_size = irr_driver->getVideoDriver()
->getDriverAttributes().getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
irr_driver->getVideoDriver()->getNonConstDriverAttributes()
.setAttribute("MAX_TEXTURE_SIZE", core::dimension2du(0, 0));
video::ITexture* page_texture = irr_driver->getVideoDriver()
->addTexture("Glyph_page", m_page);
m_spritebank->setTexture(m_spritebank->getTextureCount() - 1,
page_texture);
irr_driver->getVideoDriver()->removeTexture(page_texture);
assert(page_texture->getReferenceCount() == 1);
irr_driver->getVideoDriver()->getNonConstDriverAttributes()
.setAttribute("MAX_TEXTURE_SIZE", old_max_size);
} // updateCharactersList
// ----------------------------------------------------------------------------
@ -347,21 +312,7 @@ void FontWithFace::updateCharactersList()
*/
void FontWithFace::dumpGlyphPage(const std::string& name)
{
for (unsigned int i = 0; i < m_spritebank->getTextureCount(); i++)
{
video::ITexture* tex = m_spritebank->getTexture(i);
core::dimension2d<u32> size = tex->getSize();
video::ECOLOR_FORMAT col_format = tex->getColorFormat();
void* data = tex->lock();
video::IImage* image = irr_driver->getVideoDriver()
->createImageFromData(col_format, size, data, false/*copy mem*/);
tex->unlock();
irr_driver->getVideoDriver()->writeImageToFile(image, std::string
(name + "_" + StringUtils::toString(i) + ".png").c_str());
image->drop();
}
// Todo for new texture format
} // dumpGlyphPage
// ----------------------------------------------------------------------------
@ -618,28 +569,6 @@ void FontWithFace::render(const core::stringw& text,
}
else
{
// Prevent overwriting texture used by billboard text when
// using lazy loading characters
if (supportLazyLoadChar() && fallback[i])
{
const int cur_texno = m_fallback_font->getSpriteBank()
->getSprites()[area.spriteno].Frames[0].textureNumber;
if (cur_texno == int(m_fallback_font->getSpriteBank()
->getTextureCount() - 1))
{
m_fallback_font->createNewGlyphPage();
}
}
else if (supportLazyLoadChar())
{
const int cur_texno = m_spritebank
->getSprites()[area.spriteno].Frames[0].textureNumber;
if (cur_texno == int(m_spritebank->getTextureCount() - 1))
{
createNewGlyphPage();
}
}
// Billboard text specific, use offset_y_bt instead
float glyph_offset_x = area.bearing_x *
(fallback[i] ? m_fallback_font_scale : scale);

View File

@ -129,9 +129,6 @@ private:
/** Sprite bank to store each glyph. */
gui::IGUISpriteBank* m_spritebank;
/** A full glyph page for this font. */
video::IImage* m_page;
/** The current max height at current drawing line in glyph page. */
unsigned int m_current_height;

View File

@ -137,6 +137,7 @@ video::ITexture* STKTexManager::getUnicolorTexture(const irr::video::SColor &c)
// ----------------------------------------------------------------------------
core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
{
#ifndef SERVER_ONLY
if (CVS->isTextureCompressionEnabled())
return L"Please disable texture compression for reloading textures.";
@ -179,5 +180,5 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
if (result.empty())
return L"Texture(s) not found!";
return result + "reloaded.";
#endif // !SERVER_ONLY
} // reloadTexture

View File

@ -66,7 +66,7 @@ public:
// ------------------------------------------------------------------------
STKTexture(video::IImage* image, const std::string& name);
// ------------------------------------------------------------------------
~STKTexture();
virtual ~STKTexture();
// ------------------------------------------------------------------------
virtual void* lock(video::E_TEXTURE_LOCK_MODE mode =
video::ETLM_READ_WRITE, u32 mipmap_level = 0)