Port font to use new texture format
This commit is contained in:
parent
4bcf03e296
commit
2af126357d
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user