36 panic(
"unhandled Layer value");
56 return "northwest(" + std::to_string(
static_cast<std::uint8_t
>(layer)) +
")";
58 return "northeast(" + std::to_string(
static_cast<std::uint8_t
>(layer)) +
")";
60 return "southwest(" + std::to_string(
static_cast<std::uint8_t
>(layer)) +
")";
62 return "southeast(" + std::to_string(
static_cast<std::uint8_t
>(layer)) +
")";
64 panic(
"unhandled Subtile value");
90[[nodiscard]]
inline std::tuple<std::size_t, Layer, Subtile>
from_tile_index(std::size_t tile_index)
97 return {metatile_index, layer, subtile};
120 panic(
"tile_index (" + std::to_string(tile_index) +
") >= tiles_per_metatile");
127 return {layer, subtile};
135 std::size_t subtile_row,
136 std::size_t subtile_col)
139 "{} {}({})|{}|{}|{},{}",
149[[nodiscard]]
inline std::string
185template <SupportsTransparency PixelType>
202 requires requires(const PixelType &p) { p.is_transparent(); }
204 const bool bottom_transparent =
205 std::ranges::all_of(
bottom(), [](
const auto &tile) {
return tile.is_transparent(); });
206 const bool middle_transparent =
207 std::ranges::all_of(
middle(), [](
const auto &tile) {
return tile.is_transparent(); });
208 const bool top_transparent = std::ranges::all_of(
top(), [](
const auto &tile) {
return tile.is_transparent(); });
209 return bottom_transparent && middle_transparent && top_transparent;
224 requires requires(
const PixelType &p) { p.is_transparent(p); }
226 const bool bottom_transparent =
227 std::ranges::all_of(
bottom(), [=](
const auto &tile) {
return tile.is_transparent(extrinsic); });
228 const bool middle_transparent =
229 std::ranges::all_of(
middle(), [=](
const auto &tile) {
return tile.is_transparent(extrinsic); });
230 const bool top_transparent =
231 std::ranges::all_of(
top(), [=](
const auto &tile) {
return tile.is_transparent(extrinsic); });
232 return bottom_transparent && middle_transparent && top_transparent;
247 auto out_it = tiles.begin();
248 out_it = std::ranges::copy(
bottom(), out_it).out;
249 out_it = std::ranges::copy(
middle(), out_it).out;
250 std::ranges::copy(
top(), out_it);
265 requires requires(const PixelType &p) { p.is_transparent(); }
267 return infer_layer_mode_impl([](
const PixelType &pixel) {
return pixel.is_transparent(); });
281 requires requires(
const PixelType &p) { p.is_transparent(p); }
283 return infer_layer_mode_impl([&extrinsic](
const PixelType &pixel) {
return pixel.is_transparent(extrinsic); });
301 requires requires(const PixelType &p) { p.is_transparent(); }
303 return infer_layer_type_impl([](
const PixelType &pixel) {
return pixel.is_transparent(); });
322 requires requires(
const PixelType &p) { p.is_transparent(p); }
324 return infer_layer_type_impl([&extrinsic](
const PixelType &pixel) {
return pixel.is_transparent(extrinsic); });
339 panic(std::format(
"index {} out of bounds: must be [0,3]", i));
369 panic(std::format(
"index {} out of bounds: must be [0,3]", i));
371 bottom_[i] = std::move(tile);
386 panic(std::format(
"index {} out of bounds: must be [0,3]", i));
416 panic(std::format(
"index {} out of bounds: must be [0,3]", i));
418 middle_[i] = std::move(tile);
433 panic(std::format(
"index {} out of bounds: must be [0,3]", i));
463 panic(std::format(
"index {} out of bounds: must be [0,3]", i));
465 top_[i] = std::move(tile);
480 template <
typename TransparencyPredicate>
481 [[nodiscard]]
bool layer_has_content(
483 TransparencyPredicate is_transparent_pred)
const
485 return std::ranges::any_of(layer, [&is_transparent_pred](
const auto &tile) {
486 return std::ranges::any_of(
487 tile.pix(), [&is_transparent_pred](
const auto &pixel) { return !is_transparent_pred(pixel); });
501 template <
typename TransparencyPredicate>
502 [[nodiscard]]
LayerMode infer_layer_mode_impl(TransparencyPredicate is_transparent_pred)
const
504 const bool bottom_has_content = layer_has_content(bottom_, is_transparent_pred);
505 const bool middle_has_content = layer_has_content(middle_, is_transparent_pred);
506 const bool top_has_content = layer_has_content(top_, is_transparent_pred);
508 if (bottom_has_content && middle_has_content && top_has_content) {
524 template <
typename TransparencyPredicate>
525 [[nodiscard]]
LayerType infer_layer_type_impl(TransparencyPredicate is_transparent_pred)
const
528 const LayerMode mode = infer_layer_mode_impl(is_transparent_pred);
534 const bool bottom_has_content = layer_has_content(bottom_, is_transparent_pred);
535 const bool middle_has_content = layer_has_content(middle_, is_transparent_pred);
536 const bool top_has_content = layer_has_content(top_, is_transparent_pred);
539 if (bottom_has_content && !middle_has_content && top_has_content) {
543 if (bottom_has_content && (middle_has_content || !top_has_content)) {
565[[nodiscard]] std::vector<PixelTile<T>> decompose(
const std::vector<Metatile<T>> &metatiles)
567 std::vector<PixelTile<T>> tiles;
569 for (
const auto &mt : metatiles) {
570 tiles.append_range(mt.decompose());
An 8x8 tile backed by literal-array-based per-pixel storage of an arbitrary pixel type.
Abstract base class for applying text styling with context-aware formatting.
virtual std::string format(const std::string &format_str, const std::vector< FormatParam > ¶ms) const
Formats a string with styled parameters using fmtlib syntax.
constexpr std::size_t side_length_pix
LayerMode
Specifies whether a metatile uses dual-layer or triple-layer mode.
void panic(const StringViewSourceLoc &s)
Unconditionally terminates the program with a panic message.
std::string int_to_hex_str(T t)
Converts an integer value to a hexadecimal string with "0x" prefix.
LayerType
Specifies which layers of a metatile are used for rendering.
Utility functions for string manipulation and formatting.