Diggler/Font.cpp
Dorian Wouters f2062d6fe7 Faster atlas creation
Block selection
Chunk de/compression now uses internal buffer directly (0-copy)
Optimized Chunk vertices list order (faster vert access from GPU cache)
F5 Debug info: added triangle count
Implemented ladder climb
Road + jump pad makes you jump farther
Fixed bad fog color blending (alpha-channel)
Changed LZFX and enet compilation to Release, -O3
2016-01-02 20:03:37 +01:00

173 lines
4.6 KiB
C++

#include "Font.hpp"
#include <fstream>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "Texture.hpp"
#include "Program.hpp"
#include "VBO.hpp"
#include "Game.hpp"
#include "GlUtils.hpp"
namespace Diggler {
Font::Renderer Font::R = {0};
static const struct { float r, g, b; } ColorTable[16] = {
{1.0f, 1.0f, 1.0f},
{0.66f, 0.66f, 0.66f},
{0.33f, 0.33f, 0.33f},
{0.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{1.0f, 0.5f, 0.0f},
{1.0f, 1.0f, 0.0f},
{0.5f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.5f},
{0.0f, 1.0f, 1.0f},
{0.0f, 0.5f, 1.0f},
{0.0f, 0.0f, 1.0f},
{0.5f, 0.0f, 1.0f},
{1.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.5f}
};
Font::Font(Game *G, const std::string& path) : G(G) {
if (!R.prog) {
R.prog = G->PM->getProgram(PM_2D | PM_TEXTURED | PM_COLORED);
R.att_coord = R.prog->att("coord");
R.att_texcoord = R.prog->att("texcoord");
R.att_color = R.prog->att("color");
R.uni_mvp = R.prog->uni("mvp");
}
m_texture = new Texture(path, Texture::PixelFormat::RGBA);
std::ifstream source(path + ".fdf", std::ios_base::binary);
if (source.good()) {
source.seekg(0, std::ios_base::end);
int size = (int)source.tellg() - 1; // Last byte is font's height
source.seekg(0, std::ios_base::beg);
//widths = new uint8[size];
texPos = new CharTexPos[95];
uint8 widths[95];
std::fill_n(widths, 95, 6);
source.read((char*)widths, size);
source.read((char*)&height, 1);
int left = 0;
for (uint8 i=0; i < 95; i++) {
texPos[i].width = widths[i];
texPos[i].left = (float)left / m_texture->getW();
left += widths[i];
texPos[i].right = (float)left / m_texture->getW();
}
}
}
struct Vertex { int x, y; float tx, ty; float r, g, b ,a; };
#define eraseCurChar() elements -= 6;
int Font::updateVBO(VBO &vbo, const std::string &text, GLenum usage) const {
int elements = text.size()*6;
Vertex *verts = new Vertex[elements];
uint8 c, w; int line = 0, cx = 0, v = 0; float l, r;
float cr = 1.0f, cg = 1.0f, cb = 1.0f, ca = 1.0f;
for (uint i=0; i < text.size(); i++) {
c = text[i];
if (c == '\n') {
eraseCurChar();
line -= height;
cx = 0;
continue;
}
if (c == '\f' && i < text.length()) {
/* \f can mean "format" */
eraseCurChar();
uint8 arg = text[++i];
eraseCurChar();
if (arg >= '0' && arg <= '9') {
uint8 index = arg - '0';
cr = ColorTable[index].r; cg = ColorTable[index].g; cb = ColorTable[index].b;
} else if (arg >= 'a' && arg <= 'f') {
uint8 index = (arg - 'a') + 10;
cr = ColorTable[index].r; cg = ColorTable[index].g; cb = ColorTable[index].b;
} else if (arg == 't') { // 't'ransparency
uint8 arg2 = text[++i];
eraseCurChar();
if (arg2 >= 'a' && arg2 <= 'z')
ca = (float)(arg2 - 'a')/('z'-'a');
}
continue;
}
if (c < ' ' || c > '~') {
eraseCurChar();
continue;
}
w = texPos[c - ' '].width;
l = texPos[c - ' '].left;
r = texPos[c - ' '].right;
verts[v+0] = { cx, line, l, 1.0, cr, cg, cb, ca };
verts[v+1] = { cx+w, line+height, r, 0.0, cr, cg, cb, ca };
verts[v+2] = { cx, line+height, l, 0.0, cr, cg, cb, ca };
verts[v+3] = { cx, line, l, 1.0, cr, cg, cb, ca };
verts[v+4] = { cx+w, line, r, 1.0, cr, cg, cb, ca };
verts[v+5] = { cx+w, line+height, r, 0.0, cr, cg, cb, ca };
v += 6;
cx += w;
}
vbo.setData(verts, elements, usage);
delete[] verts;
return elements;
}
void Font::draw(const VBO &vbo, int count, const glm::mat4& matrix) const {
glEnableVertexAttribArray(R.att_coord);
glEnableVertexAttribArray(R.att_texcoord);
glEnableVertexAttribArray(R.att_color);
R.prog->bind();
m_texture->bind();
vbo.bind();
glUniformMatrix4fv(R.uni_mvp, 1, GL_FALSE, glm::value_ptr(matrix));
glVertexAttribPointer(R.att_coord, 2, GL_INT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(R.att_texcoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, tx));
glVertexAttribPointer(R.att_color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, r));
glDrawArrays(GL_TRIANGLES, 0, count);
glDisableVertexAttribArray(R.att_color);
glDisableVertexAttribArray(R.att_texcoord);
glDisableVertexAttribArray(R.att_coord);
}
Font::Size Font::getSize(const std::string &text) const {
uint8 c; int x = 0, y = height, cx = 0;
for (uint i=0; i < text.size(); i++) {
c = text[i];
if (c == '\n') {
y += height;
if (cx > x)
x = cx;
cx = 0;
continue;
}
if (c == '\f' && i < text.length()) { /* 167 = '§' */
uint8 arg = text[++i];
if (arg == 't') {
i++;
}
continue;
}
x += texPos[c - ' '].width;
}
return Size { x, y };
}
int Font::getHeight() const {
return height;
}
Font::~Font() {
delete m_texture;
if (texPos)
delete[] texPos;
}
}