// ================================================================================ // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås == // == See tb_core.h for more information. == // ================================================================================ #include "tb_font_renderer.h" #include "tb_renderer.h" #include "tb_system.h" #ifdef TB_FONT_RENDERER_STB using namespace tb; #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation #include "../../ThirdParty/STB/stb_truetype.h" /** STBFontRenderer renders fonts using stb_truetype.h (http://nothings.org/) */ class STBFontRenderer : public TBFontRenderer { public: STBFontRenderer(); ~STBFontRenderer(); bool Load(const char *filename, int size); virtual TBFontFace *Create(TBFontManager *font_manager, const char *filename, const TBFontDescription &font_desc); virtual TBFontMetrics GetMetrics(); virtual bool RenderGlyph(TBFontGlyphData *dst_bitmap, UCS4 cp); virtual void GetGlyphMetrics(TBGlyphMetrics *metrics, UCS4 cp); private: stbtt_fontinfo font; unsigned char *ttf_buffer; unsigned char *render_data; int font_size; float scale; }; STBFontRenderer::STBFontRenderer() : ttf_buffer(nullptr) , render_data(nullptr) { } STBFontRenderer::~STBFontRenderer() { delete [] ttf_buffer; delete [] render_data; } TBFontMetrics STBFontRenderer::GetMetrics() { TBFontMetrics metrics; int ascent, descent, lineGap; stbtt_GetFontVMetrics(&font, &ascent, &descent, &lineGap); metrics.ascent = (int) (ascent * scale + 0.5f); metrics.descent = (int) ((-descent) * scale + 0.5f); metrics.height = (int) ((ascent - descent + lineGap) * scale + 0.5f); return metrics; } bool STBFontRenderer::RenderGlyph(TBFontGlyphData *data, UCS4 cp) { delete [] render_data; render_data = stbtt_GetCodepointBitmap(&font, 0, scale, cp, &data->w, &data->h, 0, 0); data->data8 = render_data; data->stride = data->w; data->rgb = false; return data->data8 ? true : false; } void STBFontRenderer::GetGlyphMetrics(TBGlyphMetrics *metrics, UCS4 cp) { int advanceWidth, leftSideBearing; stbtt_GetCodepointHMetrics(&font, cp, &advanceWidth, &leftSideBearing); metrics->advance = (int) (advanceWidth * scale + 0.5f); int ix0, iy0, ix1, iy1; stbtt_GetCodepointBitmapBox(&font, cp, 0, scale, &ix0, &iy0, &ix1, &iy1); metrics->x = ix0; metrics->y = iy0; } bool STBFontRenderer::Load(const char *filename, int size) { TBFile *f = TBFile::Open(filename, TBFile::MODE_READ); if (!f) return false; size_t ttf_buf_size = f->Size(); ttf_buffer = new unsigned char[ttf_buf_size]; if (ttf_buffer) ttf_buf_size = f->Read(ttf_buffer, 1, ttf_buf_size); delete f; if (!ttf_buffer) return false; stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer, 0)); font_size = (int) (size * 1.3f); // FIX: Constant taken out of thin air because fonts get too small. scale = stbtt_ScaleForPixelHeight(&font, (float)font_size); return true; } TBFontFace *STBFontRenderer::Create(TBFontManager *font_manager, const char *filename, const TBFontDescription &font_desc) { if (STBFontRenderer *fr = new STBFontRenderer()) { if (fr->Load(filename, (int) font_desc.GetSize())) if (TBFontFace *font = new TBFontFace(font_manager->GetGlyphCache(), fr, font_desc)) return font; delete fr; } return nullptr; } void register_stb_font_renderer() { if (STBFontRenderer *fr = new STBFontRenderer) g_font_manager->AddRenderer(fr); } #endif // TB_FONT_RENDERER_STB