// SPDX-License-Identifier: GPL-3.0-or-later // Copyright (C) 2026 steredbits and Pelagia contributors #include "ui/font.h" #include // stb_truetype implementation compiled here, exactly once. Third-party code: // its warnings do not concern the project. #if defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif #define STB_TRUETYPE_IMPLEMENTATION #define STBTT_STATIC #include "stb/stb_truetype.h" #if defined(__GNUC__) #pragma GCC diagnostic pop #endif namespace ui { struct FontImpl { stbtt_fontinfo info; }; Font::Font() {} Font::~Font() {} bool Font::load(const unsigned char* data, size_t size) { impl_.reset(); if (!data || size < 12) { return false; } std::unique_ptr impl(new FontImpl); const int offset = stbtt_GetFontOffsetForIndex(data, 0); if (offset < 0 || !stbtt_InitFont(&impl->info, data, offset)) { return false; } impl_ = std::move(impl); return true; } float Font::scale(int px) const { return stbtt_ScaleForMappingEmToPixels(&impl_->info, static_cast(px)); } int Font::glyph_index(uint32_t cp) const { return impl_ ? stbtt_FindGlyphIndex(&impl_->info, static_cast(cp)) : 0; } void Font::vertical_metrics(int px, int* ascent, int* descent, int* line_gap) const { int a = 0, d = 0, g = 0; stbtt_GetFontVMetrics(&impl_->info, &a, &d, &g); const float s = scale(px); *ascent = static_cast(std::lround(a * s)); *descent = static_cast(std::lround(d * s)); *line_gap = static_cast(std::lround(g * s)); } float Font::advance(int glyph, int px) const { int adv = 0, lsb = 0; stbtt_GetGlyphHMetrics(&impl_->info, glyph, &adv, &lsb); return adv * scale(px); } float Font::kerning(int glyph1, int glyph2, int px) const { return stbtt_GetGlyphKernAdvance(&impl_->info, glyph1, glyph2) * scale(px); } void Font::rasterize(int glyph, int px, std::vector* bitmap, int* w, int* h, int* xoff, int* yoff) const { const float s = scale(px); int x0 = 0, y0 = 0, x1 = 0, y1 = 0; stbtt_GetGlyphBitmapBox(&impl_->info, glyph, s, s, &x0, &y0, &x1, &y1); *w = x1 - x0; *h = y1 - y0; *xoff = x0; *yoff = y0; if (*w <= 0 || *h <= 0) { *w = *h = 0; bitmap->clear(); return; } bitmap->assign(static_cast(*w) * *h, 0); stbtt_MakeGlyphBitmap(&impl_->info, bitmap->data(), *w, *h, *w, s, s, glyph); } } // namespace ui