86 lines
2.7 KiB
C++
86 lines
2.7 KiB
C++
|
|
/*
|
||
|
|
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<float,4> 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<float,4> 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;
|
||
|
|
}
|