From dbb42e741d29ab213f2a51fc8d9568c02f844647 Mon Sep 17 00:00:00 2001 From: fschildt Date: Sat, 27 Sep 2025 12:40:31 +0200 Subject: add font glyph drawing --- src/common/Font.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/common/Font.hpp | 43 +++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 src/common/Font.cpp create mode 100644 src/common/Font.hpp (limited to 'src/common') diff --git a/src/common/Font.cpp b/src/common/Font.cpp new file mode 100644 index 0000000..31a6720 --- /dev/null +++ b/src/common/Font.cpp @@ -0,0 +1,117 @@ +#include + +#include +#include + + +Font::~Font() +{ + Deinit(); +} + + +bool +Font::Init(const char* path, int font_size) +{ + std::ifstream file(path, std::ios::in|std::ios::binary|std::ios::ate); + if (!file.is_open()) { + return false; + } + + + std::streampos end = file.tellg(); + size_t size = static_cast(end); + char *content = new char[size + 1]; + + file.seekg(0, std::ios::beg); + file.read(content, end); + file.close(); + content[size] = '\0'; + + + // set font info + if (!stbtt_InitFont(&m_font_info, (unsigned char*)content, 0)) + { + std::cout << "stbtt_InitFont failed.\n"; + printf("stbtt_InitFont failed\n"); + delete[] content; + return false; + } + + + // font settings (scale + vmetrics) + float scale = stbtt_ScaleForPixelHeight(&m_font_info, (float)font_size); + int baseline, ascent, descent, line_gap; + stbtt_GetFontVMetrics(&m_font_info, &ascent, &descent, &line_gap); + baseline = int(scale * (float)-descent); + ascent = int(scale * (float)ascent); + descent = int(scale * (float)descent); + line_gap = int(scale * (float)line_gap); + + + m_font_scale = scale; + m_font_baseline = baseline; + m_font_yadvance = ascent - descent + line_gap; + m_file_content = content; + + + return true; +} + + +void +Font::LoadGlyph(Glyph& glyph, uint32_t codepoint) +{ + int bbx0, bby0, bbx1, bby1; + stbtt_GetCodepointBitmapBox(&m_font_info, (int)codepoint, m_font_scale, m_font_scale, &bbx0, &bby0, &bbx1, &bby1); + int width = bbx1 - bbx0; + int height = bby1 - bby0; + + + size_t size = size_t(width * height); + uint8_t* bitmap_flipped = new uint8_t[size]; + uint8_t* bitmap_correct = new uint8_t[size]; + + + stbtt_MakeCodepointBitmap(&m_font_info, bitmap_flipped, width, height, width, m_font_scale, m_font_scale, (int)codepoint); + + uint8_t* dest = bitmap_correct; + for (int y = 0; y < height; ++y) + { + uint8_t* src = bitmap_flipped + size_t((height-1-y)*width); + for (int x = 0; x < width; ++x) + { + *dest++ = *src++; + } + } + delete[] bitmap_flipped; + + glyph.bitmap.width = width; + glyph.bitmap.height = height; + glyph.bitmap.pixels = std::unique_ptr(bitmap_correct); + + + int xadvance; + int left_side_bearing; + stbtt_GetCodepointHMetrics(&m_font_info, (int)codepoint, &xadvance, &left_side_bearing); + xadvance = (int)(m_font_scale * (float)xadvance); + left_side_bearing = (int)(m_font_scale * (float)left_side_bearing); + + + glyph.xoff = static_cast(m_font_scale * (float)bbx0) + left_side_bearing; + glyph.yoff = -bby1; + glyph.xadvance = xadvance; + +} + + +void +Font::Deinit() +{ + if (m_file_content) { + delete[] m_file_content; + m_file_content = nullptr; + } +} + + diff --git a/src/common/Font.hpp b/src/common/Font.hpp new file mode 100644 index 0000000..a594add --- /dev/null +++ b/src/common/Font.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + + +struct MonoBitmap { + int32_t width; + int32_t height; + std::unique_ptr pixels; +}; + + +struct Glyph { + int32_t xoff; + int32_t yoff; + int32_t xadvance; + MonoBitmap bitmap; +}; + + +class Font { +public: + ~Font(); + + bool Init(const char* path, int font_size); + void Deinit(); + + void LoadGlyph(Glyph& glyph, uint32_t codepoint); + + +private: + const char* m_file_content = nullptr; + + float m_font_scale; + int m_font_baseline; + int m_font_yadvance; + + stbtt_fontinfo m_font_info; + Glyph m_glyphs['~' - ' ' + 1]; +}; + + -- cgit v1.2.3