1
0
Fork 0
spectre/source/Graphics/Font.cpp
Henrik Hautakoski c74dda1200 include/Spectre/Graphics/Font.h: move texture variable into it's own struct.
When implementing rendering of glyphs with different properties: size, stroke width, bold etc.
We will need to store them in different textures.
2016-04-23 18:36:39 +02:00

128 lines
2.5 KiB
C++

#include <Spectre/System/File.h>
#include <Spectre/System/Log.h>
#include <Spectre/Graphics/Font.h>
#include <Spectre/Graphics/Image.h>
#include <Spectre/Graphics/Texture.h>
#include <Spectre/Math/Math.h>
#include "Font/FreeTypeDriver.h"
Font::Font() :
m_size (22),
m_driver (new FreeTypeDriver())
{
}
Font::~Font()
{
delete m_driver;
}
bool Font::loadFromFile(const std::string& filename, unsigned int size)
{
if (!m_driver->loadFromFile(filename)) {
return false;
}
if (!m_driver->setCharacterSize(size)) {
return false;
}
m_size = size;
m_cacheTextureA.shelf = 0;
m_cacheTextureA.texpos = vec2u(0, 0);
createTexture();
return true;
}
bool Font::loadFromMemory(const void *data, unsigned int size)
{
return false;
}
Font::Glyph Font::getGlyph(unsigned int code) const
{
if (m_charset.find(code) == m_charset.end()) {
loadChar(code);
}
return m_charset[code];
}
void Font::loadChar(unsigned char code) const
{
Image img;
Font::Glyph glyph;
if (!m_driver) {
return;
}
glyph = m_driver->loadGlyph(code, img);
if (glyph.size > vec2b(0, 0)) {
Vector2u pos = findTextureRegion(img);
m_cacheTextureA.texture.enable();
m_cacheTextureA.texture.update(pos, img);
glyph.texture = &m_cacheTextureA.texture;
glyph.texture_origin = vec2u(pos.x, pos.y);
} else {
glyph.texture = NULL;
}
m_charset[code] = glyph;
}
void Font::createTexture()
{
m_cacheTextureA.texture.create(128, 32, PixelFormat::PF_Alpha);
m_cacheTextureA.texture.enable();
m_cacheTextureA.texture.setSmooth(true);
m_cacheTextureA.texture.disable();
}
void Font::resizeTexture() const
{
Texture& tex = m_cacheTextureA.texture;
unsigned int nextSize = math::nextPowerOfTwo(tex.getSize().y + 1);
Image tmpImg = tex.copyToImage();
// recreate texture.
tex.create(tex.getSize().x, nextSize, tmpImg.getFormat());
tex.update(vec2u(0, 0), tmpImg);
}
Vector2u Font::findTextureRegion(const Image& img) const
{
Vector2u pos;
if (m_cacheTextureA.texpos.x + img.getWidth() + 1 > m_cacheTextureA.texture.getSize().x) {
m_cacheTextureA.texpos.y += m_cacheTextureA.shelf;
m_cacheTextureA.texpos.x = 0;
m_cacheTextureA.shelf = 0;
}
if (img.getHeight() + 1 > m_cacheTextureA.shelf) {
m_cacheTextureA.shelf = img.getHeight() + 1;
if (m_cacheTextureA.texpos.y + m_cacheTextureA.shelf > m_cacheTextureA.texture.getSize().y) {
resizeTexture();
}
}
pos = m_cacheTextureA.texpos;
m_cacheTextureA.texpos.x += img.getWidth() + 1;
return pos;
}
const Texture* Font::getTexture() const
{
return &m_cacheTextureA.texture;
}