#include "Font.h" #define round_up_26_6(val) (((val) + 63) >> 6u) static FT_Library ft_library_handle; static bool ft_initialized; bool Initialize_FreeType() { if (ft_initialized) { return true; } if (FT_Init_FreeType(&ft_library_handle) != 0) { return false; } ft_initialized = true; return true; } bool Font::load(const char * fname, int size) { if (!Initialize_FreeType()) { return false; } if (FT_New_Face(ft_library_handle, fname, 0, &m_face) != 0) { return false; } FT_Set_Pixel_Sizes(m_face, 0, size); return preload_glyphs(); } bool Font::preload_glyphs() { static const char preload_glyph_list[] = "HMgjqxy_|^"; int max_top = -9999; int min_bottom = 9999; m_advance = 0; for (size_t i = 0u; i < sizeof(preload_glyph_list) - 1u; i++) { std::shared_ptr g = get_glyph(preload_glyph_list[i]); if (g == NULL) { return false; } if (m_face->glyph->bitmap_top > max_top) { max_top = m_face->glyph->bitmap_top; } int bitmap_bottom = m_face->glyph->bitmap_top - m_face->glyph->bitmap.rows; if (bitmap_bottom < min_bottom) { min_bottom = bitmap_bottom; } if (g->get_advance() > m_advance) { m_advance = g->get_advance(); } } m_line_height = round_up_26_6(m_face->size->metrics.height); m_baseline_offset = (m_line_height - (max_top - min_bottom)) / 2 - min_bottom; return true; } std::shared_ptr Font::get_glyph(FT_ULong character) { auto it = m_glyphs.find(character); if (it != m_glyphs.end()) { return it->second; } std::shared_ptr glyph = std::make_shared(); if (!glyph->load(m_face, character)) { glyph = nullptr; } m_glyphs[character] = glyph; return glyph; }