/* Crafter®.Graphics Copyright (C) 2026 Catcrafts® Catcrafts.net This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ module; #include "../lib/stb_truetype.h" export module Crafter.Graphics:Font; import std; namespace Crafter { // Decode the UTF-8 codepoint at `text[i]` and advance `i` past it. // Returns 0 once `i` reaches the end. Malformed sequences yield U+FFFD // and the index is moved past one byte to keep iteration finite. export inline std::uint32_t DecodeUtf8(std::string_view text, std::size_t& i) { if (i >= text.size()) return 0; std::uint8_t b0 = static_cast(text[i]); if (b0 < 0x80) { ++i; return b0; } int extra; std::uint32_t cp; if ((b0 & 0xE0) == 0xC0) { extra = 1; cp = b0 & 0x1F; } else if ((b0 & 0xF0) == 0xE0) { extra = 2; cp = b0 & 0x0F; } else if ((b0 & 0xF8) == 0xF0) { extra = 3; cp = b0 & 0x07; } else { ++i; return 0xFFFD; } ++i; for (int k = 0; k < extra; ++k) { if (i >= text.size()) return 0xFFFD; std::uint8_t b = static_cast(text[i]); if ((b & 0xC0) != 0x80) return 0xFFFD; cp = (cp << 6) | (b & 0x3Fu); ++i; } return cp; } export class Font { public: std::vector fontBuffer; std::int_fast32_t ascent; std::int_fast32_t descent; std::int_fast32_t lineGap; stbtt_fontinfo font; Font(const std::filesystem::path& font); std::uint32_t GetLineWidth(const std::string_view text, float size); float LineHeight(float size); float AscentPx(float size); float ScaleForSize(float size); }; }