/* 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 version 3.0 as published by the Free Software Foundation; 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; #ifndef CRAFTER_GRAPHICS_WINDOW_DOM #include "vulkan/vulkan.h" #endif export module Crafter.Graphics:FontAtlas; import std; import :Font; import :GraphicsTypes; #ifndef CRAFTER_GRAPHICS_WINDOW_DOM import :ImageVulkan; import :Device; #else import :WebGPU; #endif export namespace Crafter { // Per-glyph metrics. UVs are 0..1 in atlas space; on-screen sizes / // offsets / advance are in *atlas pixels at the base size* and scale // linearly with the requested font size at draw time. struct Glyph { float u0 = 0, v0 = 0; float u1 = 0, v1 = 0; float w = 0, h = 0; float xoff = 0, yoff = 0; float advance = 0; }; class FontAtlas { public: static constexpr int kAtlasSize = 1024; static constexpr float kBaseSize = 32.0f; static constexpr int kPadding = 4; static constexpr int kOnEdgeValue = 128; static constexpr float kPixelDistScale = 32.0f; #ifndef CRAFTER_GRAPHICS_WINDOW_DOM ImageVulkan image; #else WebGPUTextureRef textureHandle = 0; std::vector staging; #endif bool dirty = false; void Initialize(GraphicsCommandBuffer cmd); // Returns the row-major byte pointer the CPU writes pixels into. // Same shape on both backends. std::uint8_t* PixelPtr() noexcept; bool Ensure(Font& font, std::uint32_t codepoint); const Glyph* Lookup(Font& font, std::uint32_t codepoint) const; void Update(GraphicsCommandBuffer cmd); private: struct Shelf { int y = 0; int height = 0; int cursorX = 0; }; std::vector shelves_; int nextShelfY_ = 0; struct Key { const Font* font; std::uint32_t cp; bool operator==(const Key&) const = default; }; struct KeyHash { std::size_t operator()(const Key& k) const noexcept { std::size_t h1 = std::hash{}(k.font); std::size_t h2 = std::hash{}(k.cp); return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); } }; std::unordered_map cache_; bool ShelfPlace(int w, int h, int& outX, int& outY); }; }