|
|
|
@ -114,6 +114,12 @@ ConstMemoryOneBitBuffer ImageElement::image() const noexcept { |
|
|
|
return ConstMemoryOneBitBuffer{m_buffer, m_width, m_height}; |
|
|
|
return ConstMemoryOneBitBuffer{m_buffer, m_width, m_height}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ImageElement::updateBuffer(std::span<std::byte const> newBufferData) { |
|
|
|
|
|
|
|
std::size_t n = std::min(m_buffer.size(), newBufferData.size()); |
|
|
|
|
|
|
|
std::copy(newBufferData.begin(), newBufferData.begin() + n, m_buffer.begin()); |
|
|
|
|
|
|
|
std::fill(m_buffer.begin() + n, m_buffer.end(), std::byte{}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ImageElement::~ImageElement() { |
|
|
|
ImageElement::~ImageElement() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -138,7 +144,46 @@ void ImageElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t animat |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<ImageElement>, ParseError> ImageElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<ImageElement>, ParseError> ImageElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: parse
|
|
|
|
auto type = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint16_t>(ElementType::Image)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto x = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!x) { |
|
|
|
|
|
|
|
return std::unexpected(x.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto y = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!y) { |
|
|
|
|
|
|
|
return std::unexpected(y.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto width = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!width) { |
|
|
|
|
|
|
|
return std::unexpected(width.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto height = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!height) { |
|
|
|
|
|
|
|
return std::unexpected(height.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto reserved_ = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!reserved_) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t imageSize = ((*width) * (*height) + 8 - 1) / 8; |
|
|
|
|
|
|
|
auto imageData = readBuffer(buffer, imageSize); |
|
|
|
|
|
|
|
if (!imageData) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4; |
|
|
|
|
|
|
|
if (imageSize < rounded) { |
|
|
|
|
|
|
|
buffer = buffer.subspan(rounded - imageSize); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto result = std::make_unique<ImageElement>(*x, *y, *width, *height); |
|
|
|
|
|
|
|
result->updateBuffer(*imageData); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
AnimationElement::AnimationElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t numberOfFrames, std::uint16_t updateInterval) |
|
|
|
AnimationElement::AnimationElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t numberOfFrames, std::uint16_t updateInterval) |
|
|
|
@ -209,6 +254,12 @@ ConstMemoryOneBitBuffer AnimationElement::image(std::uint16_t frameIndex) const |
|
|
|
return ConstMemoryOneBitBuffer{buffer(frameIndex), m_width, m_height}; |
|
|
|
return ConstMemoryOneBitBuffer{buffer(frameIndex), m_width, m_height}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void AnimationElement::updateBuffer(std::span<std::byte const> newBufferData) { |
|
|
|
|
|
|
|
std::size_t n = std::min(m_buffer.size(), newBufferData.size()); |
|
|
|
|
|
|
|
std::copy(newBufferData.begin(), newBufferData.begin() + n, m_buffer.begin()); |
|
|
|
|
|
|
|
std::fill(m_buffer.begin() + n, m_buffer.end(), std::byte{}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
AnimationElement::~AnimationElement() { |
|
|
|
AnimationElement::~AnimationElement() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -235,7 +286,54 @@ void AnimationElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t an |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<AnimationElement>, ParseError> AnimationElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<AnimationElement>, ParseError> AnimationElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: implement this
|
|
|
|
auto type = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint16_t>(ElementType::Animation)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto x = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!x) { |
|
|
|
|
|
|
|
return std::unexpected(x.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto y = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!y) { |
|
|
|
|
|
|
|
return std::unexpected(y.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto width = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!width) { |
|
|
|
|
|
|
|
return std::unexpected(width.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto height = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!height) { |
|
|
|
|
|
|
|
return std::unexpected(height.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto numberOfFrames = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!numberOfFrames) { |
|
|
|
|
|
|
|
return std::unexpected(numberOfFrames.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto updateInterval = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!updateInterval) { |
|
|
|
|
|
|
|
return std::unexpected(updateInterval.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto reserved_ = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!reserved_) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t imageSize = ((*width) * (*height) + 8 - 1) / 8; |
|
|
|
|
|
|
|
auto imageData = readBuffer(buffer, imageSize); |
|
|
|
|
|
|
|
if (!imageData) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4; |
|
|
|
|
|
|
|
if (imageSize < rounded) { |
|
|
|
|
|
|
|
buffer = buffer.subspan(rounded - imageSize); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto result = std::make_unique<AnimationElement>(*x, *y, *width, *height, *numberOfFrames, *updateInterval); |
|
|
|
|
|
|
|
result->updateBuffer(*imageData); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HScrollImageElement::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::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) |
|
|
|
@ -295,6 +393,12 @@ ConstMemoryOneBitBuffer HScrollImageElement::image() const noexcept { |
|
|
|
return ConstMemoryOneBitBuffer{m_buffer, m_contentWidth, m_height}; |
|
|
|
return ConstMemoryOneBitBuffer{m_buffer, m_contentWidth, m_height}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void HScrollImageElement::updateBuffer(std::span<std::byte const> newBufferData) { |
|
|
|
|
|
|
|
std::size_t n = std::min(m_buffer.size(), newBufferData.size()); |
|
|
|
|
|
|
|
std::copy(newBufferData.begin(), newBufferData.begin() + n, m_buffer.begin()); |
|
|
|
|
|
|
|
std::fill(m_buffer.begin() + n, m_buffer.end(), std::byte{}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HScrollImageElement::~HScrollImageElement() { |
|
|
|
HScrollImageElement::~HScrollImageElement() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -322,7 +426,58 @@ void HScrollImageElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<HScrollImageElement>, ParseError> HScrollImageElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<HScrollImageElement>, ParseError> HScrollImageElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME parse
|
|
|
|
auto type = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint16_t>(ElementType::HScrollImage)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto x = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!x) { |
|
|
|
|
|
|
|
return std::unexpected(x.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto y = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!y) { |
|
|
|
|
|
|
|
return std::unexpected(y.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto width = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!width) { |
|
|
|
|
|
|
|
return std::unexpected(width.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto height = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!height) { |
|
|
|
|
|
|
|
return std::unexpected(height.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto contentWidth = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!contentWidth) { |
|
|
|
|
|
|
|
return std::unexpected(contentWidth.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto flags = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!flags) { |
|
|
|
|
|
|
|
return std::unexpected(flags.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto scrollSpeed = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!scrollSpeed) { |
|
|
|
|
|
|
|
return std::unexpected(scrollSpeed.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto reserved_ = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!reserved_) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t imageSize = ((*contentWidth) * (*height) + 8 - 1) / 8; |
|
|
|
|
|
|
|
auto imageData = readBuffer(buffer, imageSize); |
|
|
|
|
|
|
|
if (!imageData) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4; |
|
|
|
|
|
|
|
if (imageSize < rounded) { |
|
|
|
|
|
|
|
buffer = buffer.subspan(rounded - imageSize); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto result = std::make_unique<HScrollImageElement>(*x, *y, *width, *height, *contentWidth, *flags, *scrollSpeed); |
|
|
|
|
|
|
|
result->updateBuffer(*imageData); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
VScrollImageElement::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::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) |
|
|
|
@ -382,6 +537,12 @@ ConstMemoryOneBitBuffer VScrollImageElement::image() const noexcept { |
|
|
|
return ConstMemoryOneBitBuffer{m_buffer, m_width, m_contentHeight}; |
|
|
|
return ConstMemoryOneBitBuffer{m_buffer, m_width, m_contentHeight}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void VScrollImageElement::updateBuffer(std::span<std::byte const> newBufferData) { |
|
|
|
|
|
|
|
std::size_t n = std::min(m_buffer.size(), newBufferData.size()); |
|
|
|
|
|
|
|
std::copy(newBufferData.begin(), newBufferData.begin() + n, m_buffer.begin()); |
|
|
|
|
|
|
|
std::fill(m_buffer.begin() + n, m_buffer.end(), std::byte{}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
VScrollImageElement::~VScrollImageElement() { |
|
|
|
VScrollImageElement::~VScrollImageElement() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -409,7 +570,58 @@ void VScrollImageElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<VScrollImageElement>, ParseError> VScrollImageElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<VScrollImageElement>, ParseError> VScrollImageElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME parse
|
|
|
|
auto type = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint16_t>(ElementType::VScrollImage)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto x = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!x) { |
|
|
|
|
|
|
|
return std::unexpected(x.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto y = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!y) { |
|
|
|
|
|
|
|
return std::unexpected(y.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto width = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!width) { |
|
|
|
|
|
|
|
return std::unexpected(width.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto height = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!height) { |
|
|
|
|
|
|
|
return std::unexpected(height.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto contentHeight = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!contentHeight) { |
|
|
|
|
|
|
|
return std::unexpected(contentHeight.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto flags = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!flags) { |
|
|
|
|
|
|
|
return std::unexpected(flags.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto scrollSpeed = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!scrollSpeed) { |
|
|
|
|
|
|
|
return std::unexpected(scrollSpeed.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto reserved_ = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!reserved_) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t imageSize = ((*width) * (*contentHeight) + 8 - 1) / 8; |
|
|
|
|
|
|
|
auto imageData = readBuffer(buffer, imageSize); |
|
|
|
|
|
|
|
if (!imageData) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4; |
|
|
|
|
|
|
|
if (imageSize < rounded) { |
|
|
|
|
|
|
|
buffer = buffer.subspan(rounded - imageSize); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto result = std::make_unique<VScrollImageElement>(*x, *y, *width, *height, *contentHeight, *flags, *scrollSpeed); |
|
|
|
|
|
|
|
result->updateBuffer(*imageData); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -471,7 +683,42 @@ void LineElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t animati |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<LineElement>, ParseError> LineElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<LineElement>, ParseError> LineElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: parse
|
|
|
|
auto type = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint16_t>(ElementType::Line)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto originX = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!originX) { |
|
|
|
|
|
|
|
return std::unexpected(originX.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto originY = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!originY) { |
|
|
|
|
|
|
|
return std::unexpected(originY.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto targetX = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!targetX) { |
|
|
|
|
|
|
|
return std::unexpected(targetX.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto targetY = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!targetY) { |
|
|
|
|
|
|
|
return std::unexpected(targetY.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto lineStyle = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!lineStyle) { |
|
|
|
|
|
|
|
return std::unexpected(lineStyle.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*lineStyle != static_cast<std::uint8_t>(LineStyle::Solid)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto flags = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!flags) { |
|
|
|
|
|
|
|
return std::unexpected(flags.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto result = std::make_unique<LineElement>(*originX, *originY, *targetX, *targetY, static_cast<LineStyle>(*lineStyle), *flags); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ClippedTextElement::ClippedTextElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t fontIndex, std::string text) |
|
|
|
ClippedTextElement::ClippedTextElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t fontIndex, std::string text) |
|
|
|
@ -533,7 +780,45 @@ void ClippedTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<ClippedTextElement>, ParseError> ClippedTextElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<ClippedTextElement>, ParseError> ClippedTextElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: parse
|
|
|
|
auto type = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint16_t>(ElementType::ClippedText)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto x = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!x) { |
|
|
|
|
|
|
|
return std::unexpected(x.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto y = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!y) { |
|
|
|
|
|
|
|
return std::unexpected(y.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto width = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!width) { |
|
|
|
|
|
|
|
return std::unexpected(width.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto height = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!height) { |
|
|
|
|
|
|
|
return std::unexpected(height.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto fontIndex = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!fontIndex) { |
|
|
|
|
|
|
|
return std::unexpected(fontIndex.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto textLength = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!textLength) { |
|
|
|
|
|
|
|
return std::unexpected(textLength.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t alignedRoundedUp = (*textLength + 2 + 4 - 1) / 4 * 4 - 2; |
|
|
|
|
|
|
|
auto textData = readBuffer(buffer, alignedRoundedUp); |
|
|
|
|
|
|
|
if (!textData) { |
|
|
|
|
|
|
|
return std::unexpected(textData.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::string_view text{reinterpret_cast<char const*>(textData->data()), *textLength}; |
|
|
|
|
|
|
|
auto result = std::make_unique<ClippedTextElement>(*x, *y, *width, *height, *fontIndex, std::string{text}); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HScrollTextElement::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::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) |
|
|
|
@ -607,7 +892,53 @@ void HScrollTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<HScrollTextElement>, ParseError> HScrollTextElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<HScrollTextElement>, ParseError> HScrollTextElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: parse
|
|
|
|
auto type = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint16_t>(ElementType::HScrollText)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto x = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!x) { |
|
|
|
|
|
|
|
return std::unexpected(x.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto y = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!y) { |
|
|
|
|
|
|
|
return std::unexpected(y.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto width = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!width) { |
|
|
|
|
|
|
|
return std::unexpected(width.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto height = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!height) { |
|
|
|
|
|
|
|
return std::unexpected(height.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto flags = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!flags) { |
|
|
|
|
|
|
|
return std::unexpected(flags.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto scrollSpeed = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!scrollSpeed) { |
|
|
|
|
|
|
|
return std::unexpected(scrollSpeed.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto fontIndex = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!fontIndex) { |
|
|
|
|
|
|
|
return std::unexpected(fontIndex.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto textLength = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!textLength) { |
|
|
|
|
|
|
|
return std::unexpected(textLength.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::size_t alignedRoundedUp = (*textLength + 4 - 1) / 4 * 4; |
|
|
|
|
|
|
|
auto textData = readBuffer(buffer, alignedRoundedUp); |
|
|
|
|
|
|
|
if (!textData) { |
|
|
|
|
|
|
|
return std::unexpected(textData.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::string_view text{reinterpret_cast<char const*>(textData->data()), *textLength}; |
|
|
|
|
|
|
|
auto result = std::make_unique<HScrollTextElement>(*x, *y, *width, *height, *flags, *scrollSpeed, *fontIndex, std::string{text}); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CurrentTimeElement::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::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) |
|
|
|
@ -674,7 +1005,43 @@ void CurrentTimeElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<CurrentTimeElement>, ParseError> CurrentTimeElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<CurrentTimeElement>, ParseError> CurrentTimeElement::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: current time
|
|
|
|
auto type = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint16_t>(ElementType::CurrentTime)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto x = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!x) { |
|
|
|
|
|
|
|
return std::unexpected(x.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto y = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!y) { |
|
|
|
|
|
|
|
return std::unexpected(y.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto width = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!width) { |
|
|
|
|
|
|
|
return std::unexpected(width.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto height = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!height) { |
|
|
|
|
|
|
|
return std::unexpected(height.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto fontIndex = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!fontIndex) { |
|
|
|
|
|
|
|
return std::unexpected(fontIndex.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto utcOffset = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!utcOffset) { |
|
|
|
|
|
|
|
return std::unexpected(utcOffset.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto flags = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!flags) { |
|
|
|
|
|
|
|
return std::unexpected(flags.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto result = std::make_unique<CurrentTimeElement>(*x, *y, *width, *height, *fontIndex, *utcOffset, *flags); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
AlwaysDrawnSection::~AlwaysDrawnSection() { |
|
|
|
AlwaysDrawnSection::~AlwaysDrawnSection() { |
|
|
|
@ -780,7 +1147,59 @@ std::size_t AlwaysDrawnSection::serializeTo(std::span<std::byte> target) const { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<AlwaysDrawnSection>, ParseError> AlwaysDrawnSection::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<AlwaysDrawnSection>, ParseError> AlwaysDrawnSection::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: parse
|
|
|
|
auto type = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint8_t>(SectionType::AlwaysDrawn)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto size = readU24LE(buffer); |
|
|
|
|
|
|
|
if (!size) { |
|
|
|
|
|
|
|
return std::unexpected(size.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*size < 8) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto flags = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!flags) { |
|
|
|
|
|
|
|
return std::unexpected(flags.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto elementCount = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!elementCount) { |
|
|
|
|
|
|
|
return std::unexpected(elementCount.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto sectionData = buffer.subspan(0, *size - 8); |
|
|
|
|
|
|
|
buffer = buffer.subspan(*size - 8); |
|
|
|
|
|
|
|
auto section = std::make_unique<AlwaysDrawnSection>(); |
|
|
|
|
|
|
|
section->setDrawOnFront(((*flags) >> 0u) & 0x01u == 0x01u); |
|
|
|
|
|
|
|
section->setDrawOnBack(((*flags) >> 1u) & 0x01u == 0x01u); |
|
|
|
|
|
|
|
section->setClearBeforeDrawing(((*flags) >> 2u) & 0x01u == 0x01u); |
|
|
|
|
|
|
|
section->m_elements.reserve(*elementCount); |
|
|
|
|
|
|
|
for (std::size_t i = 0; i < *elementCount; ++i) { |
|
|
|
|
|
|
|
auto type = peekU16LE(sectionData); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::expected<std::unique_ptr<Element>, ParseError> element; |
|
|
|
|
|
|
|
switch (static_cast<ElementType>(*type)) { |
|
|
|
|
|
|
|
case ElementType::Image: element = ImageElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::Animation: element = AnimationElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::HScrollImage: element = HScrollImageElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::VScrollImage: element = VScrollImageElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::Line: element = LineElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::ClippedText: element = ClippedTextElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::HScrollText: element = HScrollTextElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::CurrentTime: element = CurrentTimeElement::parse(sectionData); break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!element) { |
|
|
|
|
|
|
|
return std::unexpected(element.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
section->m_elements.push_back(std::move(*element)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return section; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TimeBasedDrawnSection::~TimeBasedDrawnSection() { |
|
|
|
TimeBasedDrawnSection::~TimeBasedDrawnSection() { |
|
|
|
@ -904,7 +1323,69 @@ std::size_t TimeBasedDrawnSection::serializeTo(std::span<std::byte> target) cons |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<TimeBasedDrawnSection>, ParseError> TimeBasedDrawnSection::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<TimeBasedDrawnSection>, ParseError> TimeBasedDrawnSection::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: parse
|
|
|
|
auto type = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint8_t>(SectionType::TimeBasedDrawn)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto size = readU24LE(buffer); |
|
|
|
|
|
|
|
if (!size) { |
|
|
|
|
|
|
|
return std::unexpected(size.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*size < 24) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto flags = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!flags) { |
|
|
|
|
|
|
|
return std::unexpected(flags.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto elementCount = readU16LE(buffer); |
|
|
|
|
|
|
|
if (!elementCount) { |
|
|
|
|
|
|
|
return std::unexpected(elementCount.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto startTimestamp = readU64LE(buffer); |
|
|
|
|
|
|
|
if (!startTimestamp) { |
|
|
|
|
|
|
|
return std::unexpected(startTimestamp.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto endTimestamp = readU64LE(buffer); |
|
|
|
|
|
|
|
if (!endTimestamp) { |
|
|
|
|
|
|
|
return std::unexpected(endTimestamp.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto sectionData = buffer.subspan(0, *size - 24); |
|
|
|
|
|
|
|
buffer = buffer.subspan(*size - 24); |
|
|
|
|
|
|
|
auto section = std::make_unique<TimeBasedDrawnSection>(); |
|
|
|
|
|
|
|
section->setDrawOnFront(((*flags) >> 0u) & 0x01u == 0x01u); |
|
|
|
|
|
|
|
section->setDrawOnBack(((*flags) >> 1u) & 0x01u == 0x01u); |
|
|
|
|
|
|
|
section->setClearBeforeDrawing(((*flags) >> 2u) & 0x01u == 0x01u); |
|
|
|
|
|
|
|
section->setStartTimestamp(std::bit_cast<std::int64_t>(*startTimestamp)); |
|
|
|
|
|
|
|
section->setEndTimestamp(std::bit_cast<std::int64_t>(*endTimestamp)); |
|
|
|
|
|
|
|
section->m_elements.reserve(*elementCount); |
|
|
|
|
|
|
|
for (std::size_t i = 0; i < *elementCount; ++i) { |
|
|
|
|
|
|
|
auto type = peekU16LE(sectionData); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::expected<std::unique_ptr<Element>, ParseError> element; |
|
|
|
|
|
|
|
switch (static_cast<ElementType>(*type)) { |
|
|
|
|
|
|
|
case ElementType::Image: element = ImageElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::Animation: element = AnimationElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::HScrollImage: element = HScrollImageElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::VScrollImage: element = VScrollImageElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::Line: element = LineElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::ClippedText: element = ClippedTextElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::HScrollText: element = HScrollTextElement::parse(sectionData); break; |
|
|
|
|
|
|
|
case ElementType::CurrentTime: element = CurrentTimeElement::parse(sectionData); break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!element) { |
|
|
|
|
|
|
|
return std::unexpected(element.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
section->m_elements.push_back(std::move(*element)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return section; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CustomFontSection::~CustomFontSection() { |
|
|
|
CustomFontSection::~CustomFontSection() { |
|
|
|
@ -937,7 +1418,39 @@ std::size_t CustomFontSection::serializeTo(std::span<std::byte> target) const { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<CustomFontSection>, ParseError> CustomFontSection::parse(std::span<std::byte const>& buffer) { |
|
|
|
std::expected<std::unique_ptr<CustomFontSection>, ParseError> CustomFontSection::parse(std::span<std::byte const>& buffer) { |
|
|
|
// FIXME: parse
|
|
|
|
auto type = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!type) { |
|
|
|
|
|
|
|
return std::unexpected(type.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*type != static_cast<std::uint8_t>(SectionType::CustomFont)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto size = readU24LE(buffer); |
|
|
|
|
|
|
|
if (!size) { |
|
|
|
|
|
|
|
return std::unexpected(size.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*size < 8) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto actualSize = readU24LE(buffer); |
|
|
|
|
|
|
|
if (!actualSize) { |
|
|
|
|
|
|
|
return std::unexpected(actualSize.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto reserved_ = readU8LE(buffer); |
|
|
|
|
|
|
|
if (!reserved_) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto fontData = buffer.subspan(0, *size - 8); |
|
|
|
|
|
|
|
buffer = buffer.subspan(*size - 8); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto actualFontData = readBuffer(fontData, *actualSize); |
|
|
|
|
|
|
|
if (!actualFontData) { |
|
|
|
|
|
|
|
return std::unexpected(actualFontData.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto section = std::make_unique<CustomFontSection>(); |
|
|
|
|
|
|
|
section->setFontData(*actualFontData); |
|
|
|
|
|
|
|
return section; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::size_t serializeFile(std::span<std::byte>& buffer, File const& file) { |
|
|
|
std::size_t serializeFile(std::span<std::byte>& buffer, File const& file) { |
|
|
|
@ -961,7 +1474,51 @@ std::size_t serializeFile(std::span<std::byte>& buffer, File const& file) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::expected<File, ParseError> parseFile(std::span<std::byte const> data) { |
|
|
|
std::expected<File, ParseError> parseFile(std::span<std::byte const> data) { |
|
|
|
// FIXME: parse
|
|
|
|
auto magic = readU32LE(data); |
|
|
|
|
|
|
|
if (!magic) { |
|
|
|
|
|
|
|
return std::unexpected(magic.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*magic != UINT32_C(0x632B7EAF)) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto version = readU32LE(data); |
|
|
|
|
|
|
|
if (!version) { |
|
|
|
|
|
|
|
return std::unexpected(version.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (*version != 1) { |
|
|
|
|
|
|
|
return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto sectionCount = readU16LE(data); |
|
|
|
|
|
|
|
if (!sectionCount) { |
|
|
|
|
|
|
|
return std::unexpected(sectionCount.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auto reserved_ = readU16LE(data); |
|
|
|
|
|
|
|
if (!reserved_) { |
|
|
|
|
|
|
|
return std::unexpected(reserved_.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
File result; |
|
|
|
|
|
|
|
result.sections.reserve(*sectionCount); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < *sectionCount; ++i) { |
|
|
|
|
|
|
|
auto sectionType = peekU8LE(data); |
|
|
|
|
|
|
|
if (!sectionType) { |
|
|
|
|
|
|
|
return std::unexpected(sectionType.error()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::expected<std::unique_ptr<Section>, ParseError> section; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (static_cast<SectionType>(*sectionType)) { |
|
|
|
|
|
|
|
case SectionType::AlwaysDrawn: section = AlwaysDrawnSection::parse(data); break; |
|
|
|
|
|
|
|
case SectionType::TimeBasedDrawn: section = TimeBasedDrawnSection::parse(data); break; |
|
|
|
|
|
|
|
case SectionType::CustomFont: section = CustomFontSection::parse(data); break; |
|
|
|
|
|
|
|
default: return std::unexpected(ParseError::InvalidValue); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.sections.push_back(std::move(*section)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} // namespace monoformat
|
|
|
|
} // namespace monoformat
|
|
|
|
|