refactor(render): TextBackend owns its atlas, and staged glyphs carry a rotation basis
This commit is contained in:
1 parent
90e17a0a11
commit
e074f57ddf
23 files changed
+1073
-227
No files matched your search
@@ -0,0 +1,48 @@
|
||||
#include <plot/render/text.hpp>
|
||||
|
||||
namespace plot::render {
|
||||
|
||||
// The decoder lives with the interface, not with a font, because it is what keeps
|
||||
// "what a string is worth" (`TextBackend::measure`) and "what a string draws"
|
||||
// (`TextBatch::add_text`) the same thing: both walk a label with this function, so
|
||||
// neither can disagree with the other about where a codepoint starts or how many
|
||||
// bytes a malformed sequence costs.
|
||||
u32 next_codepoint(const char*& p) noexcept {
|
||||
const auto b0 = static_cast<u32>(static_cast<unsigned char>(p[0]));
|
||||
if (b0 < 0x80u) {
|
||||
++p;
|
||||
return b0;
|
||||
}
|
||||
u32 codepoint = 0;
|
||||
u32 extra = 0;
|
||||
if ((b0 & 0xE0u) == 0xC0u) {
|
||||
codepoint = b0 & 0x1Fu;
|
||||
extra = 1u;
|
||||
} else if ((b0 & 0xF0u) == 0xE0u) {
|
||||
codepoint = b0 & 0x0Fu;
|
||||
extra = 2u;
|
||||
} else if ((b0 & 0xF8u) == 0xF0u) {
|
||||
codepoint = b0 & 0x07u;
|
||||
extra = 3u;
|
||||
} else {
|
||||
++p;
|
||||
return kInvalidCodepoint;
|
||||
}
|
||||
for (u32 i = 1; i <= extra; ++i) {
|
||||
const auto b = static_cast<u32>(static_cast<unsigned char>(p[i]));
|
||||
if ((b & 0xC0u) != 0x80u) { // truncated: stop before the terminator
|
||||
++p;
|
||||
return kInvalidCodepoint;
|
||||
}
|
||||
codepoint = (codepoint << 6) | (b & 0x3Fu);
|
||||
}
|
||||
p += extra + 1u;
|
||||
constexpr u32 kMinForLength[4] = {0u, 0x80u, 0x800u, 0x10000u};
|
||||
if (codepoint < kMinForLength[extra] || codepoint > 0x10FFFFu ||
|
||||
(codepoint >= 0xD800u && codepoint <= 0xDFFFu)) {
|
||||
return kInvalidCodepoint; // overlong, out of range or a surrogate
|
||||
}
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
} // namespace plot::render
|
||||
Reference in new issue
Block a user