#include #include #include #include FT_FREETYPE_H #include #include #include #include "mesh.hpp" #include "arrays.hpp" #include "font.hpp" using namespace sim::graphics; struct character { unsigned long handle; float advance; glm::vec2 size; glm::vec2 bearing; }; static character chars[128]; void font::init() { FT_Library ft; FT_Face face; if(FT_Init_FreeType(&ft)) { std::cout << "Error: failed to init freetype\n"; return; } if(FT_New_Face(ft, "../assets/font/DroidSans.ttf", 0, &face)) { std::cout << "Error: failed to load freetype font\n"; return; } int size = 256; float m = 1.0f / size; FT_Set_Pixel_Sizes(face, 0, size); GLuint texids[128]; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for(int i = 0; i < 128; i++) { if(FT_Load_Char(face, (char)i, FT_LOAD_RENDER)) { std::cout << "Error: failed to load glyph " << i << "\n"; } int width = face->glyph->bitmap.width; int height = face->glyph->bitmap.rows; int offx = face->glyph->bitmap_left; int offy = face->glyph->bitmap_top; character& c = chars[i]; c.advance = face->glyph->advance.x * m / 64.0; c.size = {width * m, height * m}; c.bearing = {offx * m, offy * m}; if(c.size.x == 0 || c.size.y == 0) { c.handle = 0; continue; } glCreateTextures(GL_TEXTURE_2D, 1, &texids[i]); glTextureStorage2D(texids[i], 1, GL_R8, width, height); glTextureSubImage2D(texids[i], 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer); glTextureParameteri(texids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTextureParameteri(texids[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTextureParameteri(texids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTextureParameteri(texids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); c.handle = glGetTextureHandleARB(texids[i]); glMakeTextureHandleResidentARB(c.handle); chars[i] = c; } FT_Done_FreeType(ft); } void mesh::load_text(const char* text, double size) { std::vector vertices; std::vector indices; float x = 0, y = size; unsigned int at = 0; if(text[0] == '\0') { this->vertices.clear(); this->indices.clear(); return; } for(unsigned int i = 0; text[i] != '\0'; i++) { char c = text[i]; character ch = chars[c]; if(c == '\n') { x = 0; y += size; continue; } if(ch.handle == 0) { x += ch.advance * size; continue; } unsigned int index[6] = { at, at + 1, at + 3, at, at + 3, at + 2 }; float sx = x + ch.bearing.x * size; float sy = y - ch.bearing.y * size; float ex = sx + ch.size.x * size; float ey = sy + ch.size.y * size; vertices.push_back(arrays::vertex(ch.handle, {0, 0}, {sx, sy, 0, 1}, {0, 0, -1})); vertices.push_back(arrays::vertex(ch.handle, {0, 1}, {sx, ey, 0, 1}, {0, 0, -1})); vertices.push_back(arrays::vertex(ch.handle, {1, 0}, {ex, sy, 0, 1}, {0, 0, -1})); vertices.push_back(arrays::vertex(ch.handle, {1, 1}, {ex, ey, 0, 1}, {0, 0, -1})); indices.insert(indices.end(), &index[0], &index[6]); at += 4; x += ch.advance * size; } this->vertices = std::move(vertices); this->indices = std::move(indices); }