/* Crafter®.Graphics Copyright (C) 2026 Catcrafts® catcrafts.net */ // Backend-agnostic UIRenderer methods. FillHeader and ShapeText do not // touch any GPU API; they only read window dimensions and (for ShapeText) // the CPU-side font atlas. Split out so both Vulkan and WebGPU impls // share the same source. module Crafter.Graphics:UI_shared_impl; import :UI; import :Window; import :Font; import :FontAtlas; import :GraphicsTypes; import std; using namespace Crafter; UIDispatchHeader UIRenderer::FillHeader(std::uint32_t itemBufferSlot, std::uint32_t itemCount, std::array clipRectPx, std::uint32_t flags) const noexcept { UIDispatchHeader h{}; h.outImage = outImageSlot_; h.itemBuffer = itemBufferSlot; h.surfaceWidth = window_->width; h.surfaceHeight = window_->height; h.clipX = clipRectPx[0]; h.clipY = clipRectPx[1]; h.clipW = clipRectPx[2]; h.clipH = clipRectPx[3]; h.itemCount = itemCount; #ifndef CRAFTER_GRAPHICS_WINDOW_DOM h.frameIdx = window_->currentBuffer; #else h.frameIdx = 0; #endif h.flags = flags; h._pad = 0; return h; } std::uint32_t UIRenderer::ShapeText(Font& font, float pxSize, float x, float baselineY, std::string_view utf8, std::array color, GlyphItem* out, std::uint32_t outCapacity, float* outAdvance) { if (fontAtlas == nullptr) { std::println("UIRenderer::ShapeText: no FontAtlas (set fontAtlas before Initialize)"); std::abort(); } const float scale = pxSize / FontAtlas::kBaseSize; float cursor = x; std::uint32_t written = 0; std::size_t i = 0; while (i < utf8.size() && written < outCapacity) { std::uint32_t cp = DecodeUtf8(utf8, i); if (cp == 0) break; if (cp == '\n') { continue; } fontAtlas->Ensure(font, cp); const Glyph* g = fontAtlas->Lookup(font, cp); if (g == nullptr) continue; if (g->w > 0 && g->h > 0) { GlyphItem& gi = out[written++]; gi.x = cursor + g->xoff * scale; gi.y = baselineY + g->yoff * scale; gi.w = g->w * scale; gi.h = g->h * scale; gi.u0 = g->u0; gi.v0 = g->v0; gi.u1 = g->u1; gi.v1 = g->v1; gi.r = color[0]; gi.g = color[1]; gi.b = color[2]; gi.a = color[3]; } cursor += g->advance * scale; } if (outAdvance) *outAdvance = cursor - x; return written; }