From b7ad236b7bea50e8e7ef1495396dcadf9920456a Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Fri, 25 Jul 2014 23:31:29 -0400 Subject: [PATCH] convert Font to Ruby class --- src/Font.cc | 98 +++++++++++++++++++++++++++++++++++++++++------------ src/Font.h | 60 +------------------------------- src/main.cc | 11 +++--- 3 files changed, 85 insertions(+), 84 deletions(-) diff --git a/src/Font.cc b/src/Font.cc index aaf0312..8ac47af 100644 --- a/src/Font.cc +++ b/src/Font.cc @@ -1,13 +1,44 @@ #include "Font.h" #include "ruby.h" +#include "GLTexture.h" #include #include #include #include FT_FREETYPE_H +#include #define round_up_26_6(val) (((val) + 63) >> 6u) +class Glyph +{ +public: + Glyph(); + bool load(FT_Face face, FT_ULong char_code); + int get_advance() { return m_advance; } + void render() + { + m_texture->bind(); + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } +protected: + bool m_loaded; + int m_advance; + GLTextureRef m_texture; + GLuint m_vbo_id; +}; +typedef Ref GlyphRef; + +typedef struct +{ + FT_Face face; + std::unordered_map glyphs; +} Font; + static FT_Library ft; +static VALUE ruby_class; static void Init_FreeType() { @@ -24,62 +55,87 @@ static void Init_FreeType() initialized = true; } -Font::Font() +void Font_free(void * ptr) { - m_loaded = false; + Font * font = (Font *)ptr; + + FT_Done_Face(font->face); + + delete font; } -Font::~Font() +static VALUE Font_new(VALUE klass, VALUE fname, VALUE size) { - if (m_loaded) - { - FT_Done_Face(m_face); - } -} + Init_FreeType(); -bool Font::load(FT_Library ft, const char * fname, size_t size) -{ - if (FT_New_Face(ft, fname, 0, &m_face) != 0) + Font * font = new Font(); + + fname = rb_funcall(fname, rb_intern("to_s"), 0); + const char * fname_cstr = StringValueCStr(fname); + + if (FT_New_Face(ft, fname_cstr, 0, &font->face) != 0) { - std::cerr << "Could not load font " << fname << std::endl; - return false; + delete font; + rb_raise(rb_eRuntimeError, + "Could not load font %s", + fname_cstr); } - FT_Set_Pixel_Sizes(m_face, 0, size); + FT_Set_Pixel_Sizes(font->face, 0, NUM2INT(size)); +#if 0 GlyphRef glyph = load_glyph('g'); if (glyph == NULL) { - std::cerr << "Could not load 'g' glyph from font" << fname << std::endl; return false; } m_glyphs['g'] = glyph; +#endif +#if 0 m_advance = glyph->get_advance(); m_line_height = round_up_26_6(m_face->size->metrics.height); +#endif #if 0 m_baseline_offset = round_up_26_6((m_face->size->metrics.height - (m_face->size->metrics.ascender - m_face->size->metrics.descender)) / 2 - m_face->size->metrics.descender); #endif +#if 0 m_baseline_offset = 1 - m_face->glyph->bitmap_top + m_face->glyph->bitmap.rows; +#endif - m_loaded = true; - return true; + return Data_Wrap_Struct(klass, NULL, Font_free, font); } -Font::GlyphRef Font::load_glyph(FT_ULong char_code) +void Font_Init() +{ + ruby_class = rb_define_class("Font", rb_cObject); + rb_define_singleton_method(ruby_class, "new", (VALUE(*)(...))Font_new, 2); +} + +static GlyphRef load_glyph(Font * font, FT_ULong char_code) { GlyphRef glyph = new Glyph(); - if (glyph->load(m_face, char_code)) + if (glyph->load(font->face, char_code)) return glyph; return NULL; } -Font::Glyph::Glyph() +static GlyphRef get_glyph(Font * font, FT_ULong char_code) +{ + auto it = font->glyphs.find(char_code); + if (it != font->glyphs.end()) + return it->second; + GlyphRef g = load_glyph(font, char_code); + font->glyphs[char_code] = g; + return g; +} + +Glyph::Glyph() { m_loaded = false; } -bool Font::Glyph::load(FT_Face face, FT_ULong char_code) +bool Glyph::load(FT_Face face, FT_ULong char_code) { if (FT_Load_Char(face, char_code, FT_LOAD_RENDER) != 0) return false; diff --git a/src/Font.h b/src/Font.h index 2f99d59..92aaaea 100644 --- a/src/Font.h +++ b/src/Font.h @@ -1,64 +1,6 @@ #ifndef JES_FONT_H #define JES_FONT_H -#include "Ref.h" -#include -#include FT_FREETYPE_H -#include "gl3w.h" -#include -#include "GLTexture.h" - -class Font -{ -public: - class Glyph - { - public: - Glyph(); - bool load(FT_Face face, FT_ULong char_code); - int get_advance() { return m_advance; } - void render() - { - m_texture->bind(); - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } - protected: - bool m_loaded; - int m_advance; - GLTextureRef m_texture; - 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 m_line_height; } - int get_advance() { return m_advance; } - int get_baseline_offset() { return m_baseline_offset; } - GlyphRef get_glyph(FT_ULong char_code) - { - auto it = m_glyphs.find(char_code); - if (it != m_glyphs.end()) - return it->second; - GlyphRef g = load_glyph(char_code); - m_glyphs[char_code] = g; - return g; - } -protected: - GlyphRef load_glyph(FT_ULong char_code); - - FT_Face m_face; - int m_line_height; - int m_advance; - int m_baseline_offset; - bool m_loaded; - std::unordered_map m_glyphs; -}; - -typedef Ref FontRef; +void Font_Init(); #endif diff --git a/src/main.cc b/src/main.cc index f85d5c0..3634b99 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,8 +1,10 @@ #include #include "ruby.h" -#include "Window.h" -#include "GLShader.h" + +#include "Font.h" #include "GLProgram.h" +#include "GLShader.h" +#include "Window.h" using namespace std; @@ -50,9 +52,10 @@ static int bootstrap() int rv = 0; int err_state = 0; - Window_Init(); - GLShader_Init(); + Font_Init(); GLProgram_Init(); + GLShader_Init(); + Window_Init(); rb_eval_string_protect( "load File.expand_path('../../runtime/main.rb', $0)",