Compare commits

..

No commits in common. '7c371b04e302fdc6461d6a283ddc4c013be1470e' and '2a96abf2a1bf1bab57e4a933d18cda8b52e6e022' have entirely different histories.

  1. 2
      Specification.rst
  2. 21
      cpp/src/monoformat_fontreader.hpp
  3. 66
      cpp/src/monoformat_parseonly.cpp
  4. 3
      cpp/src/monoformat_schema.hpp
  5. 72
      cpp/src/monoformat_structured.cpp

@ -491,8 +491,6 @@ Text Flags
+===========+===================================================+
| ``0`` | Text is dark, background is white |
+-----------+---------------------------------------------------+
| ``1`` | Enable automatic word wrap |
+-----------+---------------------------------------------------+
| ``1`` .. | Reserved for future use |
| ``7`` | |
+-----------+---------------------------------------------------+

@ -527,10 +527,9 @@ public:
continue;
}
// FIXME: newline support
if (cp == '\n') {
advance.x = 0;
advance.y += m_font.lineHeight();
continue;
cp = ' ';
}
auto dims = renderGlyph(cp, position + advance, m_font, display, fontColor, bgColor);
@ -558,11 +557,10 @@ public:
continue;
}
// FIXME: newline support
// also FIXME: call ensureAdvance when handling newline
if (cp == '\n') {
ensureAdvance(boundingBox, advance);
advance.x = 0;
advance.y += m_font.lineHeight();
continue;
cp = ' ';
}
auto dims = computeGlyphDimensions(cp, position + advance, m_font);
@ -629,14 +627,15 @@ private:
return std::nullopt;
}
// FIXME: once we support multi-line also handle y component
auto bottomRight = a->getBottomRight();
if ((bottomRight.x + 1) < advance.x) {
bottomRight.x = advance.x - 1;
return Rectangle::fromCorners(a->topLeft, bottomRight);
} else {
return a;
}
if ((bottomRight.y + 1) < advance.y) {
bottomRight.y = advance.y - 1;
}
return Rectangle::fromCorners(a->topLeft, bottomRight);
}
template<typename Display>

@ -1109,61 +1109,7 @@ std::expected<void, ParseError> handleClippedText(std::span<std::byte const>& bu
ClippedImage target{screen, *x, *y, *width, *height};
auto renderer = FontRenderer{fontData}.withIgnoreUnknownChars(true);
if (textFlags.autoWordWrap) {
auto dimensions = renderer.getRenderedDimensions(text, Point{0, 0});
if (!dimensions) {
return {};
}
std::int32_t y = 0;
while (dimensions->boundingBox && dimensions->boundingBox->size.width > (*width)) {
std::size_t pos = text.find('\n');
if (pos == std::string_view::npos) {
pos = text.size();
}
std::string_view currentLine = text.substr(0, pos);
if (pos < text.size()) {
text = text.substr(pos + 1);
} else {
text = text.substr(pos);
}
while (currentLine.size() > 0) {
dimensions = renderer.getRenderedDimensions(currentLine, Point{0, 0});
if (!dimensions) {
return {};
}
std::size_t pos = currentLine.size();
while (pos > 0 && dimensions->boundingBox && dimensions->boundingBox->size.width > (*width)) {
std::size_t prevPos = pos;
pos = currentLine.rfind(' ', prevPos - 1);
if (pos == std::string_view::npos) {
pos = prevPos;
break;
}
dimensions = renderer.getRenderedDimensions(currentLine.substr(0, pos), Point{0, 0});
if (!dimensions) {
return {};
}
}
renderer.render(currentLine.substr(0, pos), Point{0, y + static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
y += renderer.lineHeight();
if (pos < currentLine.size()) {
currentLine = currentLine.substr(pos + 1);
} else {
currentLine = currentLine.substr(pos);
}
}
dimensions = renderer.getRenderedDimensions(text, Point{0, 0});
if (!dimensions) {
return {};
}
}
if (text.size() > 0) {
renderer.render(text, Point{0, y + static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
y += renderer.lineHeight();
}
} else {
renderer.render(text, Point{0, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
}
renderer.render(text, Point{0, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
return {};
}
@ -1260,7 +1206,7 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
}
ClippedImage target{screen, *x, *y, *width, *height};
auto renderer = FontRenderer{fontData}.withIgnoreUnknownChars(true);
auto dimensions = renderer.getRenderedDimensions(text, {0, static_cast<std::int32_t>(renderer.lineHeight() - 2)});
auto dimensions = renderer.getRenderedDimensions(text, {0, static_cast<std::int32_t>(renderer.lineHeight() - 1)});
if (!dimensions || !dimensions->boundingBox) {
return {};
}
@ -1284,7 +1230,7 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
if (!padBefore && !padAfter && contentWidth < *width) {
std::uint16_t offset = invert ? (*width - contentWidth) : 0;
renderer.render(text, Point{offset, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
renderer.render(text, Point{offset, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
return {};
}
@ -1321,7 +1267,7 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
}
partOffset += *width;
}
renderer.render(text, Point{partOffset - offset, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
renderer.render(text, Point{partOffset - offset, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
partOffset += contentWidth;
if (padAfter) {
if (bgColor) {
@ -1352,7 +1298,7 @@ std::expected<void, ParseError> handleHScrollText(std::span<std::byte const>& bu
}
partOffset += *width;
}
renderer.render(text, Point{partOffset - offset, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
renderer.render(text, Point{partOffset - offset, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
}
return {};
@ -1483,7 +1429,7 @@ std::expected<void, ParseError> handleCurrentTime(std::span<std::byte const>& bu
return {};
}
renderer.render(text, Point{0, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
renderer.render(text, Point{0, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
return {};
}

@ -101,20 +101,17 @@ struct FillFlags {
struct TextFlags {
bool dark{};
bool autoWordWrap{};
TextFlags() = default;
explicit TextFlags(std::uint8_t flags) noexcept
: dark{isBitSet(flags, 0)}
, autoWordWrap{isBitSet(flags, 1)}
{
}
explicit operator std::uint8_t() const noexcept {
std::uint8_t result{};
maybeSetBit(result, 0, dark);
maybeSetBit(result, 1, autoWordWrap);
return result;
}
};

@ -42,7 +42,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(FillPattern, {
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(ScrollFlags, endless, invertDirection, padBefore, padAfter)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(LineFlags, dark)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(FillFlags, dark)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(TextFlags, dark, autoWordWrap)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(TextFlags, dark)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(TimeDisplayFlags, use12h, showHours, showMinutes, showSeconds)
ImageElement::ImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height)
@ -1466,62 +1466,7 @@ void ClippedTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
bool fgColor = !m_textFlags.dark;
auto renderer = FontRenderer{fontData}.withIgnoreUnknownChars(true);
if (m_textFlags.autoWordWrap) {
std::string_view text = m_text;
auto dimensions = renderer.getRenderedDimensions(text, Point{0, 0});
if (!dimensions) {
return;
}
std::int32_t y = 0;
while (dimensions->boundingBox && dimensions->boundingBox->size.width > m_width) {
std::size_t pos = text.find('\n');
if (pos == std::string_view::npos) {
pos = text.size();
}
std::string_view currentLine = text.substr(0, pos);
if (pos < text.size()) {
text = text.substr(pos + 1);
} else {
text = text.substr(pos);
}
while (currentLine.size() > 0) {
dimensions = renderer.getRenderedDimensions(currentLine, Point{0, 0});
if (!dimensions) {
return;
}
std::size_t pos = currentLine.size();
while (pos > 0 && dimensions->boundingBox && dimensions->boundingBox->size.width > m_width) {
std::size_t prevPos = pos;
pos = currentLine.rfind(' ', prevPos - 1);
if (pos == std::string_view::npos) {
pos = prevPos;
break;
}
dimensions = renderer.getRenderedDimensions(currentLine.substr(0, pos), Point{0, 0});
if (!dimensions) {
return;
}
}
renderer.render(currentLine.substr(0, pos), Point{0, y + static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
y += renderer.lineHeight();
if (pos < currentLine.size()) {
currentLine = currentLine.substr(pos + 1);
} else {
currentLine = currentLine.substr(pos);
}
}
dimensions = renderer.getRenderedDimensions(text, Point{0, 0});
if (!dimensions) {
return;
}
}
if (text.size() > 0) {
renderer.render(text, Point{0, y + static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
y += renderer.lineHeight();
}
} else {
renderer.render(m_text, Point{0, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
}
renderer.render(m_text, Point{0, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
}
std::expected<std::unique_ptr<ClippedTextElement>, ParseError> ClippedTextElement::parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion) {
@ -1568,9 +1513,6 @@ std::expected<std::unique_ptr<ClippedTextElement>, ParseError> ClippedTextElemen
return std::unexpected(textLength.error());
}
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);
if (!textData) {
return std::unexpected(textData.error());
@ -1719,7 +1661,7 @@ void HScrollTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
}
auto renderer = FontRenderer{fontData}.withIgnoreUnknownChars(true);
auto dimensions = renderer.getRenderedDimensions(m_text, {0, static_cast<std::int32_t>(renderer.lineHeight() - 2)});
auto dimensions = renderer.getRenderedDimensions(m_text, {0, static_cast<std::int32_t>(renderer.lineHeight() - 1)});
if (!dimensions || !dimensions->boundingBox) {
return;
}
@ -1743,7 +1685,7 @@ void HScrollTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
if (!padBefore && !padAfter && contentWidth < m_width) {
std::uint16_t offset = invert ? (m_width - contentWidth) : 0;
renderer.render(m_text, Point{offset, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
renderer.render(m_text, Point{offset, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
return;
}
@ -1780,7 +1722,7 @@ void HScrollTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
}
partOffset += m_width;
}
renderer.render(m_text, Point{partOffset - offset, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
renderer.render(m_text, Point{partOffset - offset, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
partOffset += contentWidth;
if (padAfter) {
if (bgColor) {
@ -1811,7 +1753,7 @@ void HScrollTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
}
partOffset += m_width;
}
renderer.render(m_text, Point{partOffset - offset, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
renderer.render(m_text, Point{partOffset - offset, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
}
}
@ -2058,7 +2000,7 @@ void CurrentTimeElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
return;
}
renderer.render(text, Point{0, static_cast<std::int32_t>(renderer.lineHeight() - 2)}, target, fgColor, bgColor);
renderer.render(text, Point{0, static_cast<std::int32_t>(renderer.lineHeight() - 1)}, target, fgColor, bgColor);
}
std::expected<std::unique_ptr<CurrentTimeElement>, ParseError> CurrentTimeElement::parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion) {

Loading…
Cancel
Save