The repository had no licence at all, so every source was all-rights-reserved by default. Add the verbatim MIT text at LICENSE (Copyright (c) 2026 Martino Ferrari) and a two-line SPDX header to each of the 113 first-party sources -- 48 include/plot, 26 src, 10 adapters, 5 examples, 21 tests, 3 tools -- so the grant travels with each file rather than relying on the root document alone. Scripts keep their shebang on line 1; the SPDX lines follow it. Genuinely vendored code is untouched: third_party/stb_truetype.h carries no header of ours. src/render/embedded_mono_font.cpp is generated, so tools/fonts/gen_atlas.py emit() now writes the two lines into its header comment and the file was regenerated -- gen_atlas.py --check passes and the regeneration adds only those comment lines to the previously committed file. README's provenance section now states MIT and links LICENSE. No code, test or public API change.
52 lines
1.6 KiB
C++
52 lines
1.6 KiB
C++
// SPDX-License-Identifier: MIT
|
|
// SPDX-FileCopyrightText: 2026 Martino Ferrari
|
|
|
|
#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
|