From 91e6988fce102f53c7eec0b4a5d54e1dad89d977 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 23 Jun 2014 14:23:34 -0400 Subject: [PATCH] add Font::Glyph class --- src/gui/Font.cc | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ src/gui/Font.h | 38 +++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/gui/Font.cc b/src/gui/Font.cc index 8ce4a1a..a95da8d 100644 --- a/src/gui/Font.cc +++ b/src/gui/Font.cc @@ -1,5 +1,8 @@ #include "Font.h" #include +#include + +#define round_up_26_6(val) (((val) + 63) >> 6u) namespace jes { @@ -26,6 +29,76 @@ namespace jes FT_Set_Pixel_Sizes(m_face, 0, size); + m_line_height = round_up_26_6(m_face->size->metrics.height); + + m_loaded = true; + return true; + } + + Font::GlyphRef Font::load_glyph(FT_ULong char_code) + { + GlyphRef glyph = new Glyph(); + if (glyph->load(m_face, char_code)) + return glyph; + return NULL; + } + + Font::Glyph::Glyph() + { + m_loaded = false; + } + + Font::Glyph::~Glyph() + { + if (m_loaded) + { + glDeleteTextures(1, &m_texture_id); + } + } + + bool Font::Glyph::load(FT_Face face, FT_ULong char_code) + { + if (FT_Load_Char(face, char_code, FT_LOAD_RENDER) != 0) + return false; + + int width = face->glyph->bitmap.width; + int height = face->glyph->bitmap.rows; + m_left = face->glyph->bitmap_left; + m_top = face->glyph->bitmap_top; + m_advance = round_up_26_6(face->glyph->advance.x); + uint8_t * texture = new uint8_t[width * height]; + for (int i = 0; i < height; i++) + { + memcpy(&texture[width * i], + &face->glyph->bitmap.buffer[width * (height - i - 1)], + width); + } + + glGenTextures(1, &m_texture_id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_texture_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texture); + delete[] texture; + + float w = width - 1; + float h = height - 1; + float s = 1.0 / (width * 2); + float t = 1.0 / (height * 2); + GLfloat box[4][4] = { + {0, 0, s, t}, + {w, 0, 1 - s, t}, + {0, h, s, 1 - t}, + {w, h, 1 - s, 1 - t}, + }; + glGenBuffers(1, &m_vbo_id); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id); + glBufferData(GL_ARRAY_BUFFER, sizeof(box), box, GL_STATIC_DRAW); + m_loaded = true; return true; } diff --git a/src/gui/Font.h b/src/gui/Font.h index ee7cae8..433bfa8 100644 --- a/src/gui/Font.h +++ b/src/gui/Font.h @@ -4,20 +4,54 @@ #include "jes/Ref.h" #include #include FT_FREETYPE_H +#include "gl3w.h" +#include namespace jes { class Font { public: + class Glyph + { + public: + Glyph(); + ~Glyph(); + bool load(FT_Face face, FT_ULong char_code); + int get_top() { return m_top; } + int get_left() { return m_left; } + int get_advance() { return m_advance; } + void draw() + { + glBindTexture(GL_TEXTURE_2D, m_texture_id); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + protected: + bool m_loaded; + int m_top; + int m_left; + int m_advance; + GLuint m_texture_id; + GLuint m_vbo_id; + }; + typedef Ref GlyphRef; + Font(); ~Font(); bool load(FT_Library ft, const char * fname, size_t size); - int get_line_height() { return round_up_26_6(m_face->size->metrics.height); } + int get_line_height() { return m_line_height; } + int get_advance() { return m_advance; } protected: - int round_up_26_6(int val) { return (val + 63) >> 6u; } + GlyphRef load_glyph(FT_ULong char_code); + FT_Face m_face; + int m_line_height; + int m_advance; bool m_loaded; + std::unordered_map m_glyphs; }; typedef Ref FontRef;