@ -23,11 +23,18 @@ struct TimeBasedDrawnSectionMetaData {
std : : int64_t endTimestamp { } ;
std : : int64_t endTimestamp { } ;
} ;
} ;
struct MultiTimeBasedDrawnSectionMetaData {
AlwaysDrawnSectionMetaData base ;
std : : size_t rangeCount { } ;
std : : span < std : : byte const > rangeData ;
} ;
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 > 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 > 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 > 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 > 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 > 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 > handleBox ( 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 > 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 > 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 < 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 ) ;
@ -124,6 +131,62 @@ static std::expected<TimeBasedDrawnSectionMetaData, ParseError> parseTimeBasedDr
return result ;
return result ;
}
}
static std : : expected < MultiTimeBasedDrawnSectionMetaData , ParseError > parseMultiTimeBasedDrawnSection ( std : : span < std : : byte const > & data , std : : uint32_t formatVersion ) {
std : : ignore = formatVersion ;
auto type = readU8LE ( data ) ;
if ( ! type ) {
return std : : unexpected ( type . error ( ) ) ;
}
if ( * type ! = static_cast < std : : uint8_t > ( SectionType : : MultiTimeBasedDrawn ) ) {
return std : : unexpected ( ParseError : : InvalidValue ) ;
}
auto size = readU24LE ( data ) ;
if ( ! size ) {
return std : : unexpected ( size . error ( ) ) ;
}
if ( * size < 12 ) {
return std : : unexpected ( ParseError : : InvalidValue ) ;
}
auto flags = readU16LE ( data ) ;
if ( ! flags ) {
return std : : unexpected ( flags . error ( ) ) ;
}
auto elementCount = readU16LE ( data ) ;
if ( ! elementCount ) {
return std : : unexpected ( elementCount . error ( ) ) ;
}
auto rangeCount = readU16LE ( data ) ;
if ( ! rangeCount ) {
return std : : unexpected ( rangeCount . error ( ) ) ;
}
if ( ( ( * rangeCount ) * 16u + 12u ) > * size ) {
return std : : unexpected ( ParseError : : InvalidValue ) ;
}
auto reserved1 = readU16LE ( data ) ;
if ( ! reserved1 ) {
return std : : unexpected ( reserved1 . error ( ) ) ;
}
auto sectionData = data . subspan ( 0 , * size - 12 - 16 * ( * rangeCount ) ) ;
auto rangeData = data . subspan ( 12 , 16 * ( * rangeCount ) ) ;
data = data . subspan ( * size - 12 - 16 * ( * rangeCount ) ) ;
MultiTimeBasedDrawnSectionMetaData result ;
result . base . drawOnFront = isBitSet ( * flags , 0 ) ;
result . base . drawOnBack = isBitSet ( * flags , 1 ) ;
result . base . clearBeforeDrawing = isBitSet ( * flags , 2 ) ;
result . base . elementData = sectionData ;
result . rangeCount = * rangeCount ;
result . rangeData = rangeData ;
# if defined(DEBUG)
std : : cerr < < " [Debug] MultiTimeBasedDrawnSection, drawOnFront = " < < result . base . drawOnFront < < " , drawOnBack = " < < result . base . drawOnBack < < " , clearBeforeDrawing = " < < result . base . clearBeforeDrawing < < " , element data size = " < < result . base . elementData . size ( ) < < " bytes, # timestamps = " < < result . rangeCount < < std : : endl ;
# endif
return result ;
}
static std : : expected < std : : span < std : : byte const > , ParseError > parseCustomFontSection ( std : : span < std : : byte const > & data , std : : uint32_t formatVersion ) {
static std : : expected < std : : span < std : : byte const > , ParseError > parseCustomFontSection ( std : : span < std : : byte const > & data , std : : uint32_t formatVersion ) {
std : : ignore = formatVersion ;
std : : ignore = formatVersion ;
@ -176,7 +239,7 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
if ( ! version ) {
if ( ! version ) {
return std : : unexpected ( version . error ( ) ) ;
return std : : unexpected ( version . error ( ) ) ;
}
}
if ( * version ! = 1 ) {
if ( * version < 1 | | * version > 2 ) {
return std : : unexpected ( ParseError : : InvalidValue ) ;
return std : : unexpected ( ParseError : : InvalidValue ) ;
}
}
auto sectionCount = readU16LE ( data ) ;
auto sectionCount = readU16LE ( data ) ;
@ -211,6 +274,9 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
customFonts [ customFontIndex + + ] = * fontData ;
customFonts [ customFontIndex + + ] = * fontData ;
}
}
continue ;
continue ;
} else if ( static_cast < SectionType > ( * sectionType ) = = SectionType : : ExpiryDate ) {
// Ignore expiry date sections here
continue ;
}
}
AlwaysDrawnSectionMetaData section ;
AlwaysDrawnSectionMetaData section ;
@ -229,6 +295,30 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
continue ;
continue ;
}
}
section = metaData - > base ;
section = metaData - > base ;
} else if ( static_cast < SectionType > ( * sectionType ) = = SectionType : : MultiTimeBasedDrawn ) {
auto metaData = parseMultiTimeBasedDrawnSection ( * rawSectionData , * version ) ;
if ( ! metaData ) {
return std : : unexpected ( metaData . error ( ) ) ;
}
bool inRange = false ;
for ( std : : size_t i = 0 ; i < metaData - > rangeCount ; + + i ) {
auto startTimestamp = readU64LE ( metaData - > rangeData ) ;
if ( ! startTimestamp ) {
return std : : unexpected ( startTimestamp . error ( ) ) ;
}
auto endTimestamp = readU64LE ( metaData - > rangeData ) ;
if ( ! endTimestamp ) {
return std : : unexpected ( endTimestamp . error ( ) ) ;
}
if ( currentTimestamp > = std : : bit_cast < std : : int64_t > ( * startTimestamp ) & & currentTimestamp < std : : bit_cast < std : : int64_t > ( * endTimestamp ) ) {
inRange = true ;
break ;
}
}
if ( ! inRange ) {
continue ;
}
section = metaData - > base ;
} else {
} else {
continue ;
continue ;
}
}
@ -260,6 +350,7 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
case ElementType : : HScrollImage : parseResult = handleHScrollImage ( 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 : : 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 : : Line : parseResult = handleLine ( section . elementData , screen , animationTick , currentTimestamp , std : : span { customFonts } . subspan ( 0 , customFontIndex ) , * version ) ; break ;
case ElementType : : Box : parseResult = handleBox ( 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 : : 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 : : 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 ;
case ElementType : : CurrentTime : parseResult = handleCurrentTime ( section . elementData , screen , animationTick , currentTimestamp , std : : span { customFonts } . subspan ( 0 , customFontIndex ) , * version ) ; break ;
@ -275,6 +366,70 @@ std::expected<void, ParseError> parseAndApply(std::span<std::byte const> data, O
return { } ;
return { } ;
}
}
std : : expected < bool , ParseError > parseAndCheckExpiry ( std : : span < std : : byte const > data , std : : int64_t currentTimestamp ) {
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 ) {
// Version 1 doesn't ever expire
return false ;
}
if ( * version < 1 | | * version > 2 ) {
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 ( ) ) ;
}
for ( std : : size_t i = 0 ; i < * sectionCount ; + + i ) {
auto sectionType = peekU8LE ( data ) ;
if ( ! sectionType ) {
return std : : unexpected ( sectionType . error ( ) ) ;
}
auto sectionSize = peekU24LE ( data . subspan ( 1 ) ) ;
if ( ! sectionSize ) {
return std : : unexpected ( sectionSize . error ( ) ) ;
}
auto rawSectionData = readBuffer ( data , * sectionSize ) ;
if ( ! rawSectionData ) {
return std : : unexpected ( rawSectionData . error ( ) ) ;
}
if ( static_cast < SectionType > ( * sectionType ) ! = SectionType : : ExpiryDate ) {
// Ignore expiry date sections here
continue ;
}
auto headerData = rawSectionData - > subspan ( 4 ) ;
auto expiryDate = readU64LE ( headerData ) ;
if ( ! expiryDate ) {
return std : : unexpected ( expiryDate . error ( ) ) ;
}
if ( currentTimestamp > = std : : bit_cast < std : : int64_t > ( * expiryDate ) ) {
return true ;
}
// Don't abort here, there could be multiple expiry dates in the file
}
// The file isn't expired
return false ;
}
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 : : 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 ;
std : : ignore = formatVersion ;
@ -785,11 +940,10 @@ std::expected<void, ParseError> handleLine(std::span<std::byte const>& buffer, O
# endif
# endif
LineFlags lineFlags { * flags } ;
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 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 ) ;
std : : int32_t dy = static_cast < std : : int32_t > ( * targetY ) - static_cast < std : : int32_t > ( * originY ) ;
bool value = true ;
bool value = ! lineFlags . dark ;
if ( dx = = 0 ) {
if ( dx = = 0 ) {
for ( std : : int32_t i = 0 ; i < = dy ; + + i ) {
for ( std : : int32_t i = 0 ; i < = dy ; + + i ) {
@ -810,6 +964,66 @@ std::expected<void, ParseError> handleLine(std::span<std::byte const>& buffer, O
return { } ;
return { } ;
}
}
std : : expected < void , ParseError > handleBox ( 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 ;
auto type = readU16LE ( buffer ) ;
if ( ! type ) {
return std : : unexpected ( type . error ( ) ) ;
}
if ( * type ! = static_cast < std : : uint16_t > ( ElementType : : Box ) ) {
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 fillPattern = readU8LE ( buffer ) ;
if ( ! fillPattern ) {
return std : : unexpected ( fillPattern . error ( ) ) ;
}
if ( * fillPattern ! = static_cast < std : : uint8_t > ( FillPattern : : Solid ) ) {
return std : : unexpected ( ParseError : : InvalidValue ) ;
}
auto flags = readU8LE ( buffer ) ;
if ( ! flags ) {
return std : : unexpected ( flags . error ( ) ) ;
}
# if defined(DEBUG)
std : : cerr < < " [Debug] - Box, x = " < < ( * x ) < < " , y = " < < ( * y ) < < " , width = " < < ( * width ) < < " , height = " < < ( * height )
< < " , fillPattern = " < < int ( * fillPattern )
< < std : : endl ;
# endif
FillFlags fillFlags { * flags } ;
bool value = ! fillFlags . dark ;
for ( std : : int32_t dy = 0 ; dy < * height ; + + dy ) {
for ( std : : int32_t dx = 0 ; dx < * width ; + + dx ) {
screen - > setPixel ( dx + * x , dy + * y , value ) ;
}
}
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 : : uint32_t formatVersion ) {
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 = formatVersion ;
std : : ignore = animationTick ;
std : : ignore = animationTick ;
@ -838,6 +1052,18 @@ std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& bu
if ( ! height ) {
if ( ! height ) {
return std : : unexpected ( height . error ( ) ) ;
return std : : unexpected ( height . error ( ) ) ;
}
}
std : : expected < std : : uint8_t , ParseError > textFlags_ = 0 ;
if ( formatVersion > = 2 ) {
textFlags_ = readU8LE ( buffer ) ;
if ( ! textFlags_ ) {
return std : : unexpected ( textFlags_ . error ( ) ) ;
}
auto reserved1 = readU8LE ( buffer ) ;
if ( ! reserved1 ) {
return std : : unexpected ( reserved1 . error ( ) ) ;
}
}
TextFlags textFlags { * textFlags_ } ;
auto fontIndex = readU16LE ( buffer ) ;
auto fontIndex = readU16LE ( buffer ) ;
if ( ! fontIndex ) {
if ( ! fontIndex ) {
return std : : unexpected ( fontIndex . error ( ) ) ;
return std : : unexpected ( fontIndex . error ( ) ) ;
@ -847,6 +1073,9 @@ std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& bu
return std : : unexpected ( textLength . error ( ) ) ;
return std : : unexpected ( textLength . error ( ) ) ;
}
}
std : : size_t alignedRoundedUp = ( * textLength + 2 + 4 - 1 ) / 4 * 4 - 2 ;
std : : size_t alignedRoundedUp = ( * textLength + 2 + 4 - 1 ) / 4 * 4 - 2 ;
if ( formatVersion > = 2 ) {
alignedRoundedUp = ( * textLength + 4 - 1 ) / 4 * 4 ;
}
auto textData = readBuffer ( buffer , alignedRoundedUp ) ;
auto textData = readBuffer ( buffer , alignedRoundedUp ) ;
if ( ! textData ) {
if ( ! textData ) {
return std : : unexpected ( textData . error ( ) ) ;
return std : : unexpected ( textData . error ( ) ) ;
@ -873,9 +1102,14 @@ std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& bu
if ( fontData . size ( ) < 23 ) {
if ( fontData . size ( ) < 23 ) {
return { } ;
return { } ;
}
}
std : : optional < bool > bgColor ;
bgColor = textFlags . dark ;
bool fgColor = ! textFlags . dark ;
ClippedImage target { screen , * x , * y , * width , * height } ;
ClippedImage target { screen , * x , * y , * width , * height } ;
auto renderer = FontRenderer { fontData } . withIgnoreUnknownChars ( true ) ;
auto renderer = FontRenderer { fontData } . withIgnoreUnknownChars ( true ) ;
renderer . render ( text , Point { 0 , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , true , false ) ;
renderer . render ( text , Point { 0 , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , fgColor , bgColor ) ;
return { } ;
return { } ;
}
}
@ -907,6 +1141,18 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
if ( ! height ) {
if ( ! height ) {
return std : : unexpected ( height . error ( ) ) ;
return std : : unexpected ( height . error ( ) ) ;
}
}
std : : expected < std : : uint8_t , ParseError > textFlags_ = 0 ;
if ( formatVersion > = 2 ) {
textFlags_ = readU8LE ( buffer ) ;
if ( ! textFlags_ ) {
return std : : unexpected ( textFlags_ . error ( ) ) ;
}
auto reserved1 = readU8LE ( buffer ) ;
if ( ! reserved1 ) {
return std : : unexpected ( reserved1 . error ( ) ) ;
}
}
TextFlags textFlags { * textFlags_ } ;
auto flags = readU8LE ( buffer ) ;
auto flags = readU8LE ( buffer ) ;
if ( ! flags ) {
if ( ! flags ) {
return std : : unexpected ( flags . error ( ) ) ;
return std : : unexpected ( flags . error ( ) ) ;
@ -915,6 +1161,12 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
if ( ! scrollSpeed ) {
if ( ! scrollSpeed ) {
return std : : unexpected ( scrollSpeed . error ( ) ) ;
return std : : unexpected ( scrollSpeed . error ( ) ) ;
}
}
if ( formatVersion > = 2 ) {
auto reserved2 = readU16LE ( buffer ) ;
if ( ! reserved2 ) {
return std : : unexpected ( reserved2 . error ( ) ) ;
}
}
auto fontIndex = readU16LE ( buffer ) ;
auto fontIndex = readU16LE ( buffer ) ;
if ( ! fontIndex ) {
if ( ! fontIndex ) {
return std : : unexpected ( fontIndex . error ( ) ) ;
return std : : unexpected ( fontIndex . error ( ) ) ;
@ -967,6 +1219,10 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
ScrollFlags scrollFlags { * flags } ;
ScrollFlags scrollFlags { * flags } ;
std : : optional < bool > bgColor ;
bgColor = textFlags . dark ;
bool fgColor = ! textFlags . dark ;
bool restarting = ! scrollFlags . endless ;
bool restarting = ! scrollFlags . endless ;
bool invert = scrollFlags . invertDirection ;
bool invert = scrollFlags . invertDirection ;
bool padBefore = scrollFlags . padBefore ;
bool padBefore = scrollFlags . padBefore ;
@ -974,7 +1230,7 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
if ( ! padBefore & & ! padAfter & & contentWidth < * width ) {
if ( ! padBefore & & ! padAfter & & contentWidth < * width ) {
std : : uint16_t offset = invert ? ( * width - contentWidth ) : 0 ;
std : : uint16_t offset = invert ? ( * width - contentWidth ) : 0 ;
renderer . render ( text , Point { offset , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , true , false ) ;
renderer . render ( text , Point { offset , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , fgColor , bgColor ) ;
return { } ;
return { } ;
}
}
@ -998,45 +1254,51 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
std : : int32_t partOffset = 0 ;
std : : int32_t partOffset = 0 ;
if ( padBefore ) {
if ( padBefore ) {
if ( bgColor ) {
for ( std : : int32_t dy = 0 ; dy < * height ; + + dy ) {
for ( std : : int32_t dy = 0 ; dy < * height ; + + dy ) {
for ( std : : int32_t dx = 0 ; dx < * width ; + + dx ) {
for ( std : : int32_t dx = 0 ; dx < * width ; + + dx ) {
std : : int32_t ddx = dx + partOffset ;
std : : int32_t ddx = dx + partOffset ;
if ( ( ddx - offset ) < 0 ) {
if ( ( ddx - offset ) < 0 ) {
continue ;
continue ;
}
}
target . setPixel ( ddx - offset , dy , false ) ;
target . setPixel ( ddx - offset , dy , * bgColor ) ;
}
}
}
}
}
partOffset + = * width ;
partOffset + = * width ;
}
}
renderer . render ( text , Point { partOffset - offset , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , true , false ) ;
renderer . render ( text , Point { partOffset - offset , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , fgColor , bgColor ) ;
partOffset + = contentWidth ;
partOffset + = contentWidth ;
if ( padAfter ) {
if ( padAfter ) {
if ( bgColor ) {
for ( std : : int32_t dy = 0 ; dy < * height ; + + dy ) {
for ( std : : int32_t dy = 0 ; dy < * height ; + + dy ) {
for ( std : : int32_t dx = 0 ; dx < * width ; + + dx ) {
for ( std : : int32_t dx = 0 ; dx < * width ; + + dx ) {
std : : int32_t ddx = dx + partOffset ;
std : : int32_t ddx = dx + partOffset ;
if ( ( ddx - offset ) < 0 ) {
if ( ( ddx - offset ) < 0 ) {
continue ;
continue ;
}
}
target . setPixel ( ddx - offset , dy , false ) ;
target . setPixel ( ddx - offset , dy , * bgColor ) ;
}
}
}
}
}
partOffset + = * width ;
partOffset + = * width ;
}
}
if ( ! restarting ) {
if ( ! restarting ) {
if ( padBefore ) {
if ( padBefore ) {
if ( bgColor ) {
for ( std : : int32_t dy = 0 ; dy < * height ; + + dy ) {
for ( std : : int32_t dy = 0 ; dy < * height ; + + dy ) {
for ( std : : int32_t dx = 0 ; dx < * width ; + + dx ) {
for ( std : : int32_t dx = 0 ; dx < * width ; + + dx ) {
std : : int32_t ddx = dx + partOffset ;
std : : int32_t ddx = dx + partOffset ;
if ( ( ddx - offset ) < 0 ) {
if ( ( ddx - offset ) < 0 ) {
continue ;
continue ;
}
}
target . setPixel ( ddx - offset , dy , false ) ;
target . setPixel ( ddx - offset , dy , * bgColor ) ;
}
}
}
}
}
partOffset + = * width ;
partOffset + = * width ;
}
}
renderer . render ( text , Point { partOffset - offset , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , true , false ) ;
renderer . render ( text , Point { partOffset - offset , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , fgColor , bgColor ) ;
}
}
return { } ;
return { } ;
@ -1069,6 +1331,18 @@ std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& bu
if ( ! height ) {
if ( ! height ) {
return std : : unexpected ( height . error ( ) ) ;
return std : : unexpected ( height . error ( ) ) ;
}
}
std : : expected < std : : uint8_t , ParseError > textFlags_ = 0 ;
if ( formatVersion > = 2 ) {
textFlags_ = readU8LE ( buffer ) ;
if ( ! textFlags_ ) {
return std : : unexpected ( textFlags_ . error ( ) ) ;
}
auto reserved1 = readU8LE ( buffer ) ;
if ( ! reserved1 ) {
return std : : unexpected ( reserved1 . error ( ) ) ;
}
}
TextFlags textFlags { * textFlags_ } ;
auto fontIndex = readU16LE ( buffer ) ;
auto fontIndex = readU16LE ( buffer ) ;
if ( ! fontIndex ) {
if ( ! fontIndex ) {
return std : : unexpected ( fontIndex . error ( ) ) ;
return std : : unexpected ( fontIndex . error ( ) ) ;
@ -1081,6 +1355,12 @@ std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& bu
if ( ! flags ) {
if ( ! flags ) {
return std : : unexpected ( flags . error ( ) ) ;
return std : : unexpected ( flags . error ( ) ) ;
}
}
if ( formatVersion > = 2 ) {
auto reserved2 = readU16LE ( buffer ) ;
if ( ! reserved2 ) {
return std : : unexpected ( reserved2 . error ( ) ) ;
}
}
# if defined(DEBUG)
# if defined(DEBUG)
std : : cerr < < " [Debug] - CurrentTime, x = " < < ( * x ) < < " , y = " < < ( * y ) < < " , width = " < < ( * width ) < < " , height = " < < ( * height )
std : : cerr < < " [Debug] - CurrentTime, x = " < < ( * x ) < < " , y = " < < ( * y ) < < " , width = " < < ( * width ) < < " , height = " < < ( * height )
@ -1103,6 +1383,11 @@ std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& bu
if ( fontData . size ( ) < 23 ) {
if ( fontData . size ( ) < 23 ) {
return { } ;
return { } ;
}
}
std : : optional < bool > bgColor ;
bgColor = textFlags . dark ;
bool fgColor = ! textFlags . dark ;
ClippedImage target { screen , * x , * y , * width , * height } ;
ClippedImage target { screen , * x , * y , * width , * height } ;
TimeDisplayFlags timeDisplayFlags { * flags } ;
TimeDisplayFlags timeDisplayFlags { * flags } ;
@ -1144,7 +1429,7 @@ std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& bu
return { } ;
return { } ;
}
}
renderer . render ( text , Point { 0 , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , true , false ) ;
renderer . render ( text , Point { 0 , static_cast < std : : int32_t > ( renderer . lineHeight ( ) - 1 ) } , target , fgColor , bgColor ) ;
return { } ;
return { } ;
}
}