diff options
Diffstat (limited to 'src/text.cpp')
-rw-r--r-- | src/text.cpp | 114 |
1 files changed, 83 insertions, 31 deletions
diff --git a/src/text.cpp b/src/text.cpp index 85c0ceb..8726b88 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -2,10 +2,6 @@ #include <iostream> -//FT_Library freetype; -//std::map<std::string, FT_Face> fonts; -//std::map<std::string, std::vector<FT_Info>> fontData; - void TextSystem::configure([[maybe_unused]] entityx::EntityManager& entities, [[maybe_unused]] entityx::EventManager& events) { @@ -28,6 +24,8 @@ void TextSystem::loadFont(const std::string& name, const std::string& file, int size) { + // Find or load font at given size + // if (fonts.find(file) == fonts.end()) { FT_Face face; @@ -39,34 +37,88 @@ void TextSystem::loadFont(const std::string& name, auto& face = fonts[file]; FT_Set_Pixel_Sizes(face, 0, size); - fontData.try_emplace(name, 95); - - char c = 32; - for (auto& d : fontData[name]) { - FT_Load_Char(face, c++, FT_LOAD_RENDER); - - glGenTextures(1, &d.tex); - glBindTexture(GL_TEXTURE_2D, d.tex); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - // convert red-on-black to RGBA - auto& g = face->glyph; - std::vector<uint32_t> buf (g->bitmap.width * g->bitmap.rows, 0xFFFFFF); - for (auto j = buf.size(); j--;) - buf[j] |= g->bitmap.buffer[j] << 24; - - d.wh = { g->bitmap.width, g->bitmap.rows }; - d.bl = { g->bitmap_left, g->bitmap_top }; - d.ad = { g->advance.x >> 6, g->advance.y >> 6 }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g->bitmap.width, g->bitmap.rows, - 0, GL_RGBA, GL_UNSIGNED_BYTE, buf.data()); + fontData.try_emplace(name); + + // Calculate dimensions of final texture + // + + float width = 0, height = 0; + for (int c = 32; c < 128; c++) { + FT_Load_Char(face, c, FT_LOAD_RENDER); + width += face->glyph->bitmap.width + 1; + height = std::max(height, static_cast<float>(face->glyph->bitmap.rows)); } - std::cout << "Loaded font: " << file << " (size: " << size << ')' - << std::endl; + // Generate texture to hold entire font + // + + auto& font = fontData[name]; + glGenTextures(1, &font.tex); + glGenBuffers(1, &font.vbo); + glBindTexture(GL_TEXTURE_2D, font.tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, + 0, GL_RED, GL_UNSIGNED_BYTE, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + // // convert red-on-black to RGBA + // auto& g = face->glyph; + // std::vector<uint32_t> buf (g->bitmap.width * g->bitmap.rows, 0xFFFFFF); + // for (auto j = buf.size(); j--;) + // buf[j] |= g->bitmap.buffer[j] << 24; + + // Load each character and add it to the texture + // + + float offsetX = 0, offsetY = 0; + for (int c = 32; c < 128; c++) { + FT_Load_Char(face, c, FT_LOAD_RENDER); + + auto* g = face->glyph; + glTexSubImage2D(GL_TEXTURE_2D, 0, offsetX, offsetY, + g->bitmap.width, g->bitmap.rows, + GL_RED, GL_UNSIGNED_BYTE, + g->bitmap.buffer); + + auto& d = font.data[c - 32]; + d.dim = { g->bitmap.width, g->bitmap.rows }; + d.bitmap = { g->bitmap_left, g->bitmap_top }; + d.advance = { g->advance.x >> 6, g->advance.y >> 6 }; + + d.offset = { offsetX / width, offsetY / height }; + offsetX += g->bitmap.width; + // Keep offsetY at zero? + } + + std::cout << "Loaded font: " << file << " (size: " << size << ", tex: " + << font.tex << ")" << std::endl; +} + +void TextSystem::updateVBOs(void) +{ + for (auto& data : fontData) { + auto& d = data.second; + d.buffer.clear(); + for (auto& text : d.text) { + for (char c : text.text) { + if (c < 32) + continue; + + d.buffer += { + text.x, text.y, text.z, + d.data[c].offset.first, d.data[c].offset.second, + 1.0f + }; + } + } + + glBindBuffer(GL_ARRAY_BUFFER, d.vbo); + glBufferData(GL_ARRAY_BUFFER, + d.text.size() * sizeof(TextMeshData), d.text.data(), + GL_STREAM_DRAW); + } } |