aboutsummaryrefslogtreecommitdiffstats
path: root/src/text.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/text.cpp')
-rw-r--r--src/text.cpp114
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);
+ }
}