Compare commits

...

5 Commits

Author SHA1 Message Date
Christian Seiler 5e66961854 C++: add JSON serialization and parsing support 2 weeks ago
Christian Seiler ecf835175c C++: serialization: add version-dependent serialization support 2 weeks ago
Christian Seiler efc4ed8de4 C++: parser code: propagate format version into individual parsing methods 2 weeks ago
Christian Seiler c77efa8461 C++: refactor flags into their own structs (for better code readability) 2 weeks ago
Christian Seiler 6602bec421 C++: refactor bit manipulation into discrete functions 2 weeks ago
  1. 5
      cpp/src/CMakeLists.txt
  2. 96
      cpp/src/monoformat_bithelpers.hpp
  3. 222
      cpp/src/monoformat_parseonly.cpp
  4. 11
      cpp/src/monoformat_schema.cpp
  5. 69
      cpp/src/monoformat_schema.hpp
  6. 910
      cpp/src/monoformat_structured.cpp
  7. 119
      cpp/src/monoformat_structured.hpp

@ -15,6 +15,8 @@ set(monoformat_HEADERS
option(MONOFORMAT_EMBEDDED "Only build for embedded devices" FALSE)
if(NOT MONOFORMAT_EMBEDDED)
find_package(nlohmann_json REQUIRED)
list(APPEND monoformat_SOURCES
monoformat_structured.cpp
)
@ -28,6 +30,9 @@ add_library(monoformat ${monoformat_SOURCES} ${monoformat_HEADERS})
target_compile_features(monoformat PUBLIC cxx_std_23)
target_include_directories(monoformat PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
if(NOT MONOFORMAT_EMBEDDED)
target_link_libraries(monoformat PUBLIC nlohmann_json::nlohmann_json)
endif()
install(TARGETS monoformat
RUNTIME DESTINATION bin

@ -0,0 +1,96 @@
#ifndef MONOFORMAT_BITHELPERS_HPP
#define MONOFORMAT_BITHELPERS_HPP
#include <cstddef>
#include <cstdint>
#include <climits>
#include <concepts>
namespace monoformat {
template<std::integral Int, std::integral OtherInt>
constexpr inline bool isBitSet(Int value, OtherInt bit) {
if (bit < 0 || bit >= static_cast<Int>(sizeof(Int) * CHAR_BIT)) [[unlikely]] {
return false;
}
Int mask = Int{1} << static_cast<Int>(bit);
return (value & mask) == mask;
}
template<std::integral OtherInt>
constexpr inline bool isBitSet(std::byte value, OtherInt bit) {
return isBitSet(static_cast<std::uint8_t>(value), bit);
}
template<std::integral Int, std::integral OtherInt>
constexpr inline void setBit(Int& value, OtherInt bit) {
if (bit < 0 || bit >= static_cast<Int>(sizeof(Int) * CHAR_BIT)) [[unlikely]] {
return;
}
Int mask = Int{1} << static_cast<Int>(bit);
value |= mask;
}
template<std::integral OtherInt>
constexpr inline void setBit(std::byte& value, OtherInt bit) {
if (bit < 0 || bit >= CHAR_BIT) [[unlikely]] {
return;
}
std::uint8_t mask = std::uint8_t{1} << static_cast<std::uint8_t>(bit);
value = static_cast<std::byte>(static_cast<std::uint8_t>(value) | mask);
}
template<std::integral Int, std::integral OtherInt>
constexpr inline void unsetBit(Int& value, OtherInt bit) {
if (bit < 0 || bit >= static_cast<Int>(sizeof(Int) * CHAR_BIT)) [[unlikely]] {
return;
}
Int mask = Int{1} << static_cast<Int>(bit);
value &= ~mask;
}
template<std::integral OtherInt>
constexpr inline void unsetBit(std::byte& value, OtherInt bit) {
if (bit < 0 || bit >= CHAR_BIT) [[unlikely]] {
return;
}
std::uint8_t mask = std::uint8_t{1} << static_cast<std::uint8_t>(bit);
value = static_cast<std::byte>(static_cast<std::uint8_t>(value) & ~mask);
}
template<std::integral Int, std::integral OtherInt>
constexpr inline void maybeSetBit(Int& value, OtherInt bit, bool set) {
if (bit < 0 || bit >= static_cast<Int>(sizeof(Int) * CHAR_BIT)) [[unlikely]] {
return;
}
Int mask = Int{1} << static_cast<Int>(bit);
if (set) {
value |= mask;
} else {
value &= ~mask;
}
}
template<std::integral OtherInt>
constexpr inline void maybeSetBit(std::byte& value, OtherInt bit, bool set) {
if (bit < 0 || bit >= CHAR_BIT) [[unlikely]] {
return;
}
std::uint8_t mask = std::uint8_t{1} << static_cast<std::uint8_t>(bit);
if (set) {
value = static_cast<std::byte>(static_cast<std::uint8_t>(value) | mask);
} else {
value = static_cast<std::byte>(static_cast<std::uint8_t>(value) & ~mask);
}
}
} // namespace monoformat
#endif // MONOFORMAT_BITHELPERS_HPP

@ -1,6 +1,7 @@
#include "monoformat_parseonly.hpp"
#include "monoformat_parsehelpers.hpp"
#include "monoformat_fontreader.hpp"
#include "monoformat_bithelpers.hpp"
#include <string_view>
#include <string>
@ -22,16 +23,18 @@ struct TimeBasedDrawnSectionMetaData {
std::int64_t endTimestamp{};
};
static std::expected<void, ParseError> handleImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts);
static std::expected<void, ParseError> handleAnimation(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts);
static std::expected<void, ParseError> handleHScrollImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts);
static std::expected<void, ParseError> handleVScrollImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts);
static std::expected<void, ParseError> handleLine(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts);
static std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts);
static std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts);
static std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts);
static std::expected<void, ParseError> handleImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion);
static std::expected<void, ParseError> handleAnimation(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion);
static std::expected<void, ParseError> handleHScrollImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion);
static std::expected<void, ParseError> handleVScrollImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion);
static std::expected<void, ParseError> handleLine(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion);
static std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion);
static std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion);
static std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion);
static std::expected<AlwaysDrawnSectionMetaData, ParseError> parseAlwaysDrawnSection(std::span<std::byte const>& data, std::uint32_t formatVersion) {
std::ignore = formatVersion;
static std::expected<AlwaysDrawnSectionMetaData, ParseError> parseAlwaysDrawnSection(std::span<std::byte const>& data) {
auto type = readU8LE(data);
if (!type) {
return std::unexpected(type.error());
@ -58,14 +61,21 @@ static std::expected<AlwaysDrawnSectionMetaData, ParseError> parseAlwaysDrawnSec
data = data.subspan(*size - 8);
AlwaysDrawnSectionMetaData result;
result.drawOnFront = (((*flags) >> 0u) & 0x01u) == 0x01u;
result.drawOnBack = (((*flags) >> 0u) & 0x02u) == 0x02u;
result.clearBeforeDrawing = (((*flags) >> 0u) & 0x04u) == 0x04u;
result.drawOnFront = isBitSet(*flags, 0);
result.drawOnBack = isBitSet(*flags, 1);
result.clearBeforeDrawing = isBitSet(*flags, 2);
result.elementData = sectionData;
#if defined(DEBUG)
std::cerr << "[Debug] AlwaysDrawnSection, drawOnFront = " << result.drawOnFront << ", drawOnBack = " << result.drawOnBack << ", clearBeforeDrawing = " << result.clearBeforeDrawing << ", element data size = " << result.elementData.size() << " bytes" << std::endl;
#endif
return result;
}
static std::expected<TimeBasedDrawnSectionMetaData, ParseError> parseTimeBasedDrawnSection(std::span<std::byte const>& data) {
static std::expected<TimeBasedDrawnSectionMetaData, ParseError> parseTimeBasedDrawnSection(std::span<std::byte const>& data, std::uint32_t formatVersion) {
std::ignore = formatVersion;
auto type = readU8LE(data);
if (!type) {
return std::unexpected(type.error());
@ -100,16 +110,23 @@ static std::expected<TimeBasedDrawnSectionMetaData, ParseError> parseTimeBasedDr
data = data.subspan(*size - 24);
TimeBasedDrawnSectionMetaData result;
result.base.drawOnFront = (((*flags) >> 0u) & 0x01u) == 0x01u;
result.base.drawOnBack = (((*flags) >> 0u) & 0x02u) == 0x02u;
result.base.clearBeforeDrawing = (((*flags) >> 0u) & 0x04u) == 0x04u;
result.base.drawOnFront = isBitSet(*flags, 0);
result.base.drawOnBack = isBitSet(*flags, 1);
result.base.clearBeforeDrawing = isBitSet(*flags, 2);
result.base.elementData = sectionData;
result.startTimestamp = std::bit_cast<std::int64_t>(*startTimestamp);
result.endTimestamp = std::bit_cast<std::int64_t>(*endTimestamp);
#if defined(DEBUG)
std::cerr << "[Debug] TimeBasedDrawnSection, drawOnFront = " << result.base.drawOnFront << ", drawOnBack = " << result.base.drawOnBack << ", clearBeforeDrawing = " << result.base.clearBeforeDrawing << ", element data size = " << result.base.elementData.size() << " bytes, timestamp between " << result.startTimestamp << " and " << result.endTimestamp << std::endl;
#endif
return result;
}
static std::expected<std::span<std::byte const>, ParseError> parseCustomFontSection(std::span<std::byte const>& data) {
static std::expected<std::span<std::byte const>, ParseError> parseCustomFontSection(std::span<std::byte const>& data, std::uint32_t formatVersion) {
std::ignore = formatVersion;
auto type = readU8LE(data);
if (!type) {
return std::unexpected(type.error());
@ -135,6 +152,10 @@ static std::expected<std::span<std::byte const>, ParseError> parseCustomFontSect
auto fontData = data.subspan(0, *size - 8);
data = data.subspan(*size - 8);
#if defined(DEBUG)
std::cerr << "[Debug] CustomFontSection, font data size = " << *actualSize << " bytes" << std::endl;
#endif
return readBuffer(fontData, *actualSize);
}
@ -182,7 +203,7 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
}
if (static_cast<SectionType>(*sectionType) == SectionType::CustomFont) {
auto fontData = parseCustomFontSection(*rawSectionData);
auto fontData = parseCustomFontSection(*rawSectionData, *version);
if (!fontData) {
return std::unexpected(fontData.error());
}
@ -194,13 +215,13 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
AlwaysDrawnSectionMetaData section;
if (static_cast<SectionType>(*sectionType) == SectionType::AlwaysDrawn) {
auto metaData = parseAlwaysDrawnSection(*rawSectionData);
auto metaData = parseAlwaysDrawnSection(*rawSectionData, *version);
if (!metaData) {
return std::unexpected(metaData.error());
}
section = *metaData;
} else if (static_cast<SectionType>(*sectionType) == SectionType::TimeBasedDrawn) {
auto metaData = parseTimeBasedDrawnSection(*rawSectionData);
auto metaData = parseTimeBasedDrawnSection(*rawSectionData, *version);
if (!metaData) {
return std::unexpected(metaData.error());
}
@ -234,14 +255,14 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
auto eType = static_cast<ElementType>(*type);
std::expected<void, ParseError> parseResult;
switch (eType) {
case ElementType::Image: parseResult = handleImage(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex)); break;
case ElementType::Animation: parseResult = handleAnimation(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex)); break;
case ElementType::HScrollImage: parseResult = handleHScrollImage(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex)); break;
case ElementType::VScrollImage: parseResult = handleVScrollImage(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex)); break;
case ElementType::Line: parseResult = handleLine(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex)); break;
case ElementType::ClippedText: parseResult = handleClippedText(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex)); break;
case ElementType::HScrollText: parseResult = handleHScrollText(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex)); break;
case ElementType::CurrentTime: parseResult = handleCurrentTime(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex)); break;
case ElementType::Image: parseResult = handleImage(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex), *version); break;
case ElementType::Animation: parseResult = handleAnimation(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex), *version); break;
case ElementType::HScrollImage: parseResult = handleHScrollImage(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex), *version); break;
case ElementType::VScrollImage: parseResult = handleVScrollImage(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex), *version); break;
case ElementType::Line: parseResult = handleLine(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex), *version); break;
case ElementType::ClippedText: parseResult = handleClippedText(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex), *version); break;
case ElementType::HScrollText: parseResult = handleHScrollText(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex), *version); break;
case ElementType::CurrentTime: parseResult = handleCurrentTime(section.elementData, screen, animationTick, currentTimestamp, std::span{customFonts}.subspan(0, customFontIndex), *version); break;
default: parseResult = std::unexpected(ParseError::InvalidValue);
}
@ -254,7 +275,9 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
return {};
}
std::expected<void, ParseError> handleImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts) {
std::expected<void, ParseError> handleImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion) {
std::ignore = formatVersion;
auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
@ -292,6 +315,10 @@ std::expected<void, ParseError> handleImage(std::span<std::byte const>& buffer,
buffer = buffer.subspan(rounded - imageSize);
}
#if defined(DEBUG)
std::cerr << "[Debug] - Image, x = " << (*x) << ", y = " << (*y) << ", width = " << (*width) << ", height = " << (*height) << std::endl;
#endif
std::ignore = animationTick;
std::ignore = currentTimestamp;
std::ignore = customFonts;
@ -305,7 +332,8 @@ std::expected<void, ParseError> handleImage(std::span<std::byte const>& buffer,
return {};
}
std::expected<void, ParseError> handleAnimation(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts) {
std::expected<void, ParseError> handleAnimation(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion) {
std::ignore = formatVersion;
std::ignore = currentTimestamp;
std::ignore = customFonts;
@ -345,15 +373,22 @@ std::expected<void, ParseError> handleAnimation(std::span<std::byte const>& buff
return std::unexpected(reserved_.error());
}
std::size_t imageSize = ((*width) * (*height) + 8 - 1) / 8;
auto imageData = readBuffer(buffer, imageSize);
auto imageData = readBuffer(buffer, imageSize * (*numberOfFrames));
if (!imageData) {
return std::unexpected(reserved_.error());
}
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4;
if (imageSize < rounded) {
buffer = buffer.subspan(rounded - imageSize);
std::size_t rounded = (imageSize * (*numberOfFrames) + 4 - 1) / 4 * 4;
if (imageSize * (*numberOfFrames) < rounded) {
buffer = buffer.subspan(rounded - imageSize * (*numberOfFrames));
}
#if defined(DEBUG)
std::cerr << "[Debug] - Animation, x = " << (*x) << ", y = " << (*y) << ", width = " << (*width) << ", height = " << (*height)
<< ", numberOfFrames = " << (*numberOfFrames)
<< ", updateInterval = " << (*updateInterval)
<< std::endl;
#endif
if (*numberOfFrames == 0) {
return {};
}
@ -370,7 +405,8 @@ std::expected<void, ParseError> handleAnimation(std::span<std::byte const>& buff
return {};
}
std::expected<void, ParseError> handleHScrollImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts) {
std::expected<void, ParseError> handleHScrollImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion) {
std::ignore = formatVersion;
std::ignore = currentTimestamp;
std::ignore = customFonts;
@ -426,14 +462,24 @@ std::expected<void, ParseError> handleHScrollImage(std::span<std::byte const>& b
auto ownImage = ConstMemoryOneBitBuffer{*imageData, *contentWidth, *height};
ClippedImage target{screen, *x, *y, *width, *height};
#if defined(DEBUG)
std::cerr << "[Debug] - HScrollImage, x = " << (*x) << ", y = " << (*y) << ", width = " << (*width) << ", height = " << (*height)
<< ", contentWidth = " << (*contentWidth)
<< ", scrollSpeed = " << int(*scrollSpeed)
<< ", flags = " << int(*flags)
<< std::endl;
#endif
if (*contentWidth == 0) {
return {};
}
bool restarting = ((*flags) & 0x01) == 0x00;
bool invert = ((*flags) & 0x02) == 0x02;
bool padBefore = ((*flags) & 0x04) == 0x04;
bool padAfter = ((*flags) & 0x08) == 0x08;
ScrollFlags scrollFlags{*flags};
bool restarting = !scrollFlags.endless;
bool invert = scrollFlags.invertDirection;
bool padBefore = scrollFlags.padBefore;
bool padAfter = scrollFlags.padAfter;
if (!padBefore && !padAfter && *contentWidth < *width) {
std::int16_t offset = invert ? (*width - *contentWidth) : 0;
@ -525,7 +571,8 @@ std::expected<void, ParseError> handleHScrollImage(std::span<std::byte const>& b
return {};
}
std::expected<void, ParseError> handleVScrollImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts) {
std::expected<void, ParseError> handleVScrollImage(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion) {
std::ignore = formatVersion;
std::ignore = currentTimestamp;
std::ignore = customFonts;
@ -581,14 +628,24 @@ std::expected<void, ParseError> handleVScrollImage(std::span<std::byte const>& b
auto ownImage = ConstMemoryOneBitBuffer{*imageData, *width, *contentHeight};
ClippedImage target{screen, *x, *y, *width, *height};
#if defined(DEBUG)
std::cerr << "[Debug] - VScrollImage, x = " << (*x) << ", y = " << (*y) << ", width = " << (*width) << ", height = " << (*height)
<< ", contentHeight = " << (*contentHeight)
<< ", scrollSpeed = " << int(*scrollSpeed)
<< ", flags = " << int(*flags)
<< std::endl;
#endif
if (*contentHeight == 0) {
return {};
}
bool restarting = ((*flags) & 0x01) == 0x00;
bool invert = ((*flags) & 0x02) == 0x02;
bool padBefore = ((*flags) & 0x04) == 0x04;
bool padAfter = ((*flags) & 0x08) == 0x08;
ScrollFlags scrollFlags{*flags};
bool restarting = !scrollFlags.endless;
bool invert = scrollFlags.invertDirection;
bool padBefore = scrollFlags.padBefore;
bool padAfter = scrollFlags.padAfter;
if (!padBefore && !padAfter && *contentHeight < *height) {
std::int16_t offset = invert ? (*height - *contentHeight) : 0;
@ -680,7 +737,8 @@ std::expected<void, ParseError> handleVScrollImage(std::span<std::byte const>& b
return {};
}
std::expected<void, ParseError> handleLine(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts) {
std::expected<void, ParseError> handleLine(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion) {
std::ignore = formatVersion;
std::ignore = animationTick;
std::ignore = currentTimestamp;
std::ignore = customFonts;
@ -720,6 +778,15 @@ std::expected<void, ParseError> handleLine(std::span<std::byte const>& buffer, O
return std::unexpected(flags.error());
}
#if defined(DEBUG)
std::cerr << "[Debug] - Line, originX = " << (*originX) << ", originY = " << (*originY) << ", targetX = " << (*targetX) << ", targetY = " << (*targetY)
<< ", lineStyle = " << int(*lineStyle)
<< std::endl;
#endif
LineFlags lineFlags{*flags};
std::ignore = lineFlags;
std::int32_t dx = static_cast<std::int32_t>(*targetX) - static_cast<std::int32_t>(*originX);
std::int32_t dy = static_cast<std::int32_t>(*targetY) - static_cast<std::int32_t>(*originY);
bool value = true;
@ -743,7 +810,8 @@ std::expected<void, ParseError> handleLine(std::span<std::byte const>& buffer, O
return {};
}
std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts) {
std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion) {
std::ignore = formatVersion;
std::ignore = animationTick;
std::ignore = currentTimestamp;
@ -785,9 +853,16 @@ std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& bu
}
std::string_view text{reinterpret_cast<char const*>(textData->data()), *textLength};
#if defined(DEBUG)
std::cerr << "[Debug] - ClippedText, x = " << (*x) << ", y = " << (*y) << ", width = " << (*width) << ", height = " << (*height)
<< ", fontIndex = " << int(*fontIndex)
<< ", text = \"" << text << "\""
<< std::endl;
#endif
std::span<std::byte const> fontData;
if ((*fontIndex) & 0x8000u) {
fontIndex = (*fontIndex) & ~0x8000u;
if (isBitSet(*fontIndex, 15)) {
unsetBit(*fontIndex, 15);
if (*fontIndex >= customFonts.size()) {
return {};
}
@ -805,7 +880,8 @@ std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& bu
return {};
}
std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts) {
std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion) {
std::ignore = formatVersion;
std::ignore = currentTimestamp;
auto type = readU16LE(buffer);
@ -854,9 +930,18 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
}
std::string_view text{reinterpret_cast<char const*>(textData->data()), *textLength};
#if defined(DEBUG)
std::cerr << "[Debug] - HScrollText, x = " << (*x) << ", y = " << (*y) << ", width = " << (*width) << ", height = " << (*height)
<< ", scrollSpeed = " << int(*scrollSpeed)
<< ", flags = " << int(*flags)
<< ", fontIndex = " << int(*fontIndex)
<< ", text = \"" << text << "\""
<< std::endl;
#endif
std::span<std::byte const> fontData;
if ((*fontIndex) & 0x8000u) {
fontIndex = (*fontIndex) & ~0x8000u;
if (isBitSet(*fontIndex, 15)) {
unsetBit(*fontIndex, 15);
if (*fontIndex >= customFonts.size()) {
return {};
}
@ -880,10 +965,12 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
return {};
}
bool restarting = ((*flags) & 0x01) == 0x00;
bool invert = ((*flags) & 0x02) == 0x02;
bool padBefore = ((*flags) & 0x04) == 0x04;
bool padAfter = ((*flags) & 0x08) == 0x08;
ScrollFlags scrollFlags{*flags};
bool restarting = !scrollFlags.endless;
bool invert = scrollFlags.invertDirection;
bool padBefore = scrollFlags.padBefore;
bool padAfter = scrollFlags.padAfter;
if (!padBefore && !padAfter && contentWidth < *width) {
std::uint16_t offset = invert ? (*width - contentWidth) : 0;
@ -955,7 +1042,8 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
return {};
}
std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts) {
std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& buffer, OneBitBufferInterface* screen, std::size_t animationTick, std::int64_t currentTimestamp, std::span<std::span<std::byte const>> customFonts, std::uint32_t formatVersion) {
std::ignore = formatVersion;
std::ignore = animationTick;
auto type = readU16LE(buffer);
@ -994,9 +1082,17 @@ std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& bu
return std::unexpected(flags.error());
}
#if defined(DEBUG)
std::cerr << "[Debug] - CurrentTime, x = " << (*x) << ", y = " << (*y) << ", width = " << (*width) << ", height = " << (*height)
<< ", fontIndex = " << int(*fontIndex)
<< ", utcOffset = " << int(*utcOffset)
<< ", flags = " << int(*flags)
<< std::endl;
#endif
std::span<std::byte const> fontData;
if ((*fontIndex) & 0x8000u) {
fontIndex = (*fontIndex) & ~0x8000u;
if (isBitSet(*fontIndex, 15)) {
unsetBit(*fontIndex, 15);
if (*fontIndex >= customFonts.size()) {
return {};
}
@ -1009,10 +1105,12 @@ std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& bu
}
ClippedImage target{screen, *x, *y, *width, *height};
bool use12h = ((*flags) & 0x01u) == 0x01u;
bool showHours = ((*flags) & 0x02u) == 0x02u;
bool showMinutes = ((*flags) & 0x04u) == 0x04u;
bool showSeconds = ((*flags) & 0x08u) == 0x08u;
TimeDisplayFlags timeDisplayFlags{*flags};
bool use12h = timeDisplayFlags.use12h;
bool showHours = timeDisplayFlags.showHours;
bool showMinutes = timeDisplayFlags.showMinutes;
bool showSeconds = timeDisplayFlags.showSeconds;
if (showHours && showSeconds) {
showMinutes = true;
}

@ -1,4 +1,5 @@
#include "monoformat_schema.hpp"
#include "monoformat_bithelpers.hpp"
#include <tuple>
@ -26,7 +27,7 @@ bool MemoryOneBitBuffer::isPixelSet(std::uint16_t x, std::uint16_t y) const {
std::size_t pxIndex = static_cast<std::size_t>(y) * m_width + x;
std::size_t byteIndex = pxIndex / 8;
std::size_t bitIndex = pxIndex % 8;
return ((static_cast<std::uint8_t>(m_buffer[byteIndex]) >> bitIndex) & 0x01) == 0x01;
return isBitSet(m_buffer[byteIndex], bitIndex);
}
void MemoryOneBitBuffer::setPixel(std::uint16_t x, std::uint16_t y, bool value) {
@ -36,11 +37,7 @@ void MemoryOneBitBuffer::setPixel(std::uint16_t x, std::uint16_t y, bool value)
std::size_t pxIndex = static_cast<std::size_t>(y) * m_width + x;
std::size_t byteIndex = pxIndex / 8;
std::size_t bitIndex = pxIndex % 8;
if (value) {
m_buffer[byteIndex] = static_cast<std::byte>(static_cast<std::uint8_t>(m_buffer[byteIndex]) | (1u << bitIndex));
} else {
m_buffer[byteIndex] = static_cast<std::byte>(static_cast<std::uint8_t>(m_buffer[byteIndex]) & ~(1u << bitIndex));
}
maybeSetBit(m_buffer[byteIndex], bitIndex, value);
}
ConstMemoryOneBitBuffer::ConstMemoryOneBitBuffer(std::span<std::byte const> buffer, std::uint16_t width, std::uint16_t height)
@ -65,7 +62,7 @@ bool ConstMemoryOneBitBuffer::isPixelSet(std::uint16_t x, std::uint16_t y) const
std::size_t pxIndex = static_cast<std::size_t>(y) * m_width + x;
std::size_t byteIndex = pxIndex / 8;
std::size_t bitIndex = pxIndex % 8;
return ((static_cast<std::uint8_t>(m_buffer[byteIndex]) >> bitIndex) & 0x01) == 0x01;
return isBitSet(m_buffer[byteIndex], bitIndex);
}
void ConstMemoryOneBitBuffer::setPixel(std::uint16_t x, std::uint16_t y, bool value) {

@ -1,9 +1,12 @@
#ifndef MONOFORMAT_SCHEMA_HPP
#define MONOFORMAT_SCHEMA_HPP
#include "monoformat_bithelpers.hpp"
#include <cstddef>
#include <cstdint>
#include <span>
#include <tuple>
namespace monoformat {
@ -29,6 +32,72 @@ enum class LineStyle : std::uint8_t {
Solid = 0,
};
struct ScrollFlags {
bool endless{};
bool invertDirection{};
bool padBefore{};
bool padAfter{};
ScrollFlags() = default;
explicit ScrollFlags(std::uint8_t flags) noexcept
: endless{isBitSet(flags, 0)}
, invertDirection{isBitSet(flags, 1)}
, padBefore{isBitSet(flags, 2)}
, padAfter{isBitSet(flags, 3)}
{
}
explicit operator std::uint8_t() const noexcept {
std::uint8_t result{};
maybeSetBit(result, 0, endless);
maybeSetBit(result, 1, invertDirection);
maybeSetBit(result, 2, padBefore);
maybeSetBit(result, 3, padAfter);
return result;
}
};
struct LineFlags {
LineFlags() = default;
explicit LineFlags(std::uint8_t flags) noexcept
{
std::ignore = flags;
}
explicit operator std::uint8_t() const noexcept {
std::uint8_t result{};
return result;
}
};
struct TimeDisplayFlags {
bool use12h{};
bool showHours{};
bool showMinutes{};
bool showSeconds{};
TimeDisplayFlags() = default;
explicit TimeDisplayFlags(std::uint16_t flags) noexcept
: use12h{isBitSet(flags, 0)}
, showHours{isBitSet(flags, 1)}
, showMinutes{isBitSet(flags, 2)}
, showSeconds{isBitSet(flags, 3)}
{
}
explicit operator std::uint16_t() const noexcept {
std::uint16_t result{};
maybeSetBit(result, 0, use12h);
maybeSetBit(result, 1, showHours);
maybeSetBit(result, 2, showMinutes);
maybeSetBit(result, 3, showSeconds);
return result;
}
};
struct OneBitBufferInterface {
using Color = bool;

File diff suppressed because it is too large Load Diff

@ -4,6 +4,8 @@
#include "monoformat_parsehelpers.hpp"
#include "monoformat_schema.hpp"
#include <nlohmann/json.hpp>
#include <cstddef>
#include <cstdint>
#include <memory>
@ -15,7 +17,9 @@ namespace monoformat {
struct Section {
virtual ~Section() = default;
virtual SectionType sectionType() const = 0;
virtual std::size_t serializeTo(std::span<std::byte> target) const = 0;
virtual std::uint32_t minimumFormatVersion() const = 0;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const = 0;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const = 0;
protected:
Section() = default;
@ -26,7 +30,9 @@ class CustomFontSection;
struct Element {
virtual ~Element() = default;
virtual ElementType elementType() const = 0;
virtual std::size_t serializeTo(std::span<std::byte> target) const = 0;
virtual std::uint32_t minimumFormatVersion() const = 0;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const = 0;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const = 0;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) = 0;
protected:
@ -48,10 +54,13 @@ struct ImageElement : public Element {
virtual ~ImageElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<ImageElement>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<ImageElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<ImageElement> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::uint16_t m_x{};
@ -80,10 +89,13 @@ struct AnimationElement : public Element {
virtual ~AnimationElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<AnimationElement>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<AnimationElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<AnimationElement> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::uint16_t m_x{};
@ -96,14 +108,14 @@ private:
};
struct HScrollImageElement : public Element {
HScrollImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t contentWidth, std::uint8_t flags, std::uint8_t scrollSpeed);
HScrollImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t contentWidth, ScrollFlags flags, std::uint8_t scrollSpeed);
std::uint16_t x() const noexcept;
std::uint16_t y() const noexcept;
std::uint16_t width() const noexcept;
std::uint16_t height() const noexcept;
std::uint16_t contentWidth() const noexcept;
std::uint8_t flags() const noexcept;
ScrollFlags flags() const noexcept;
std::uint8_t scrollSpeed() const noexcept;
std::span<std::byte> buffer() noexcept;
std::span<std::byte const> buffer() const noexcept;
@ -113,10 +125,13 @@ struct HScrollImageElement : public Element {
virtual ~HScrollImageElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<HScrollImageElement>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<HScrollImageElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<HScrollImageElement> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::uint16_t m_x{};
@ -124,20 +139,20 @@ private:
std::uint16_t m_width{};
std::uint16_t m_height{};
std::uint16_t m_contentWidth{};
std::uint8_t m_flags{};
ScrollFlags m_flags;
std::uint8_t m_scrollSpeed{};
std::vector<std::byte> m_buffer;
};
struct VScrollImageElement : public Element {
VScrollImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t contentHeight, std::uint8_t flags, std::uint8_t scrollSpeed);
VScrollImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t contentHeight, ScrollFlags flags, std::uint8_t scrollSpeed);
std::uint16_t x() const noexcept;
std::uint16_t y() const noexcept;
std::uint16_t width() const noexcept;
std::uint16_t height() const noexcept;
std::uint16_t contentHeight() const noexcept;
std::uint8_t flags() const noexcept;
ScrollFlags flags() const noexcept;
std::uint8_t scrollSpeed() const noexcept;
std::span<std::byte> buffer() noexcept;
std::span<std::byte const> buffer() const noexcept;
@ -147,10 +162,13 @@ struct VScrollImageElement : public Element {
virtual ~VScrollImageElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<VScrollImageElement>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<VScrollImageElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<VScrollImageElement> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::uint16_t m_x{};
@ -158,27 +176,30 @@ private:
std::uint16_t m_width{};
std::uint16_t m_height{};
std::uint16_t m_contentHeight{};
std::uint8_t m_flags{};
ScrollFlags m_flags;
std::uint8_t m_scrollSpeed{};
std::vector<std::byte> m_buffer;
};
struct LineElement : public Element {
LineElement(std::uint16_t originX, std::uint16_t originY, std::uint16_t targetX, std::uint16_t targetY, LineStyle lineStyle, std::uint8_t flags);
LineElement(std::uint16_t originX, std::uint16_t originY, std::uint16_t targetX, std::uint16_t targetY, LineStyle lineStyle, LineFlags flags);
std::uint16_t originX() const noexcept;
std::uint16_t originY() const noexcept;
std::uint16_t targetX() const noexcept;
std::uint16_t targetY() const noexcept;
LineStyle lineStyle() const noexcept;
std::uint8_t flags() const noexcept;
LineFlags flags() const noexcept;
virtual ~LineElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<LineElement>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<LineElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<LineElement> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::uint16_t m_originX{};
@ -186,7 +207,7 @@ private:
std::uint16_t m_targetX{};
std::uint16_t m_targetY{};
LineStyle m_lineStyle{};
std::uint8_t m_flags{};
LineFlags m_flags;
};
struct ClippedTextElement : public Element {
@ -201,10 +222,13 @@ struct ClippedTextElement : public Element {
virtual ~ClippedTextElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<ClippedTextElement>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<ClippedTextElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<ClippedTextElement> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::uint16_t m_x{};
@ -216,37 +240,40 @@ private:
};
struct HScrollTextElement : public Element {
HScrollTextElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint8_t flags, std::uint8_t scrollSpeed, std::uint16_t fontIndex, std::string text);
HScrollTextElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, ScrollFlags flags, std::uint8_t scrollSpeed, std::uint16_t fontIndex, std::string text);
std::uint16_t x() const noexcept;
std::uint16_t y() const noexcept;
std::uint16_t width() const noexcept;
std::uint16_t height() const noexcept;
std::uint8_t flags() const noexcept;
ScrollFlags flags() const noexcept;
std::uint8_t scrollSpeed() const noexcept;
std::uint16_t fontIndex() const noexcept;
std::string text() const;
virtual ~HScrollTextElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<HScrollTextElement>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<HScrollTextElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<HScrollTextElement> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::uint16_t m_x{};
std::uint16_t m_y{};
std::uint16_t m_width{};
std::uint16_t m_height{};
std::uint8_t m_flags{};
ScrollFlags m_flags;
std::uint8_t m_scrollSpeed{};
std::uint16_t m_fontIndex{};
std::string m_text;
};
struct CurrentTimeElement : public Element {
CurrentTimeElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t fontIndex, std::uint16_t utcOffset, std::uint16_t flags);
CurrentTimeElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t fontIndex, std::uint16_t utcOffset, TimeDisplayFlags flags);
std::uint16_t x() const noexcept;
std::uint16_t y() const noexcept;
@ -254,14 +281,17 @@ struct CurrentTimeElement : public Element {
std::uint16_t height() const noexcept;
std::uint16_t fontIndex() const noexcept;
std::uint16_t utcOffset() const noexcept;
std::uint16_t flags() const noexcept;
TimeDisplayFlags flags() const noexcept;
virtual ~CurrentTimeElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<CurrentTimeElement>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<CurrentTimeElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<CurrentTimeElement> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::uint16_t m_x{};
@ -270,7 +300,7 @@ private:
std::uint16_t m_height{};
std::uint16_t m_fontIndex{};
std::uint16_t m_utcOffset{};
std::uint16_t m_flags{};
TimeDisplayFlags m_flags;
};
struct AlwaysDrawnSection : public Section {
@ -294,9 +324,12 @@ struct AlwaysDrawnSection : public Section {
std::unique_ptr<Element> eraseElement(std::size_t index);
virtual SectionType sectionType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
static std::expected<std::unique_ptr<AlwaysDrawnSection>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<AlwaysDrawnSection>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<AlwaysDrawnSection> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::vector<std::unique_ptr<Element>> m_elements;
@ -331,9 +364,12 @@ struct TimeBasedDrawnSection : public Section {
void setEndTimestamp(std::int64_t value);
virtual SectionType sectionType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
static std::expected<std::unique_ptr<TimeBasedDrawnSection>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<TimeBasedDrawnSection>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<TimeBasedDrawnSection> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::vector<std::unique_ptr<Element>> m_elements;
@ -352,9 +388,12 @@ struct CustomFontSection : public Section {
void setFontData(std::span<std::byte const> fontData);
virtual SectionType sectionType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual nlohmann::json serializeJSON(std::uint32_t formatVersion) const override;
static std::expected<std::unique_ptr<CustomFontSection>, ParseError> parse(std::span<std::byte const>& buffer);
static std::expected<std::unique_ptr<CustomFontSection>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
static std::unique_ptr<CustomFontSection> parseJSON(nlohmann::json const& j, std::uint32_t formatVersion);
private:
std::vector<std::byte> m_fontData;
@ -365,7 +404,9 @@ struct File {
};
extern std::size_t serializeFile(std::span<std::byte>& buffer, File const& file);
extern nlohmann::json serializeFileJSON(File const& file);
extern std::expected<File, ParseError> parseFile(std::span<std::byte const> data);
extern File parseFileJSON(nlohmann::json const& j);
} // namespace monoformat

Loading…
Cancel
Save