Merge remote-tracking branch 'origin/master' into claude/issue-123
# Conflicts: # implementations/Crafter.Graphics-UI-Shared.cpp # interfaces/Crafter.Graphics-UI.cppm
This commit is contained in:
commit
88541bf44e
5 changed files with 99 additions and 30 deletions
|
|
@ -350,25 +350,63 @@ export namespace Crafter {
|
|||
// only needs a translate by (x + alignShift, baselineY). The full
|
||||
// string is part of the key (compared on lookup) so hash collisions
|
||||
// can't return the wrong run.
|
||||
//
|
||||
// The map owns its key string, but lookups happen every frame on the
|
||||
// onBuild path. To avoid copying the string into a key on each cache
|
||||
// hit, the hash and equality functors are transparent (is_transparent)
|
||||
// and accept a borrowing view key whose text is a std::string_view;
|
||||
// the owning std::string is only materialised on a miss, for emplace.
|
||||
struct ShapedRunKey {
|
||||
const Font* font;
|
||||
float pxSize;
|
||||
std::array<float, 4> color;
|
||||
std::string text;
|
||||
bool operator==(const ShapedRunKey&) const = default;
|
||||
};
|
||||
struct ShapedRunViewKey {
|
||||
const Font* font;
|
||||
float pxSize;
|
||||
std::array<float, 4> color;
|
||||
std::string_view text;
|
||||
};
|
||||
struct ShapedRunKeyHash {
|
||||
std::size_t operator()(const ShapedRunKey& k) const noexcept {
|
||||
std::size_t h = std::hash<const void*>{}(k.font);
|
||||
using is_transparent = void;
|
||||
static std::size_t Hash(const Font* font, float pxSize,
|
||||
const std::array<float, 4>& color,
|
||||
std::string_view text) noexcept {
|
||||
std::size_t h = std::hash<const void*>{}(font);
|
||||
auto mix = [&h](std::size_t v) noexcept {
|
||||
h ^= v + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);
|
||||
};
|
||||
mix(std::hash<std::uint32_t>{}(std::bit_cast<std::uint32_t>(k.pxSize)));
|
||||
for (float c : k.color)
|
||||
mix(std::hash<std::uint32_t>{}(std::bit_cast<std::uint32_t>(pxSize)));
|
||||
for (float c : color)
|
||||
mix(std::hash<std::uint32_t>{}(std::bit_cast<std::uint32_t>(c)));
|
||||
mix(std::hash<std::string_view>{}(k.text));
|
||||
mix(std::hash<std::string_view>{}(text));
|
||||
return h;
|
||||
}
|
||||
std::size_t operator()(const ShapedRunKey& k) const noexcept {
|
||||
return Hash(k.font, k.pxSize, k.color, k.text);
|
||||
}
|
||||
std::size_t operator()(const ShapedRunViewKey& k) const noexcept {
|
||||
return Hash(k.font, k.pxSize, k.color, k.text);
|
||||
}
|
||||
};
|
||||
struct ShapedRunKeyEqual {
|
||||
using is_transparent = void;
|
||||
static bool Eq(const Font* fa, float pa, const std::array<float, 4>& ca,
|
||||
std::string_view ta,
|
||||
const Font* fb, float pb, const std::array<float, 4>& cb,
|
||||
std::string_view tb) noexcept {
|
||||
return fa == fb && pa == pb && ca == cb && ta == tb;
|
||||
}
|
||||
bool operator()(const ShapedRunKey& a, const ShapedRunKey& b) const noexcept {
|
||||
return Eq(a.font, a.pxSize, a.color, a.text, b.font, b.pxSize, b.color, b.text);
|
||||
}
|
||||
bool operator()(const ShapedRunViewKey& a, const ShapedRunKey& b) const noexcept {
|
||||
return Eq(a.font, a.pxSize, a.color, a.text, b.font, b.pxSize, b.color, b.text);
|
||||
}
|
||||
bool operator()(const ShapedRunKey& a, const ShapedRunViewKey& b) const noexcept {
|
||||
return Eq(a.font, a.pxSize, a.color, a.text, b.font, b.pxSize, b.color, b.text);
|
||||
}
|
||||
};
|
||||
struct ShapedRun {
|
||||
std::vector<GlyphItem> glyphs; // origin-relative
|
||||
|
|
@ -387,7 +425,7 @@ export namespace Crafter {
|
|||
// unaffected either way; this just avoids the periodic full-UI reshape
|
||||
// spike the old clear() caused.
|
||||
static constexpr std::size_t kMaxShapedRuns = 8192;
|
||||
std::unordered_map<ShapedRunKey, ShapedRun, ShapedRunKeyHash> shapedRuns_;
|
||||
std::unordered_map<ShapedRunKey, ShapedRun, ShapedRunKeyHash, ShapedRunKeyEqual> shapedRuns_;
|
||||
// LRU recency order for shapedRuns_; front = most recently used. Holds
|
||||
// pointers to the keys owned by the map — stable across rehash because
|
||||
// unordered_map is node-based — so eviction never re-hashes the world.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue