Implemented rich text rendering

This commit is contained in:
2021-09-05 19:16:46 +02:00
parent 03572b03f8
commit 941156a291
4 changed files with 151 additions and 1 deletions

View File

@ -13,6 +13,7 @@ set(headers
src/iconinterface.h
src/menudisplay.h
src/menuitem.h
src/richtextrenderer.h
src/screenmanager.h
src/tftinstance.h
src/textinterface.h
@ -39,6 +40,7 @@ set(sources
src/changevaluedisplay_sntp_sync_mode_t.cpp
src/menudisplay.cpp
src/screenmanager.cpp
src/richtextrenderer.cpp
src/tftinstance.cpp
src/icons/back.cpp
src/icons/checked.cpp

129
src/richtextrenderer.cpp Normal file
View File

@ -0,0 +1,129 @@
#include "richtextrenderer.h"
// system includes
#include <string_view>
// 3rdparty lib includes
#include <strutils.h>
namespace espgui {
void richTextEscape(std::string &subject)
{
cpputils::stringReplaceAll('&', "&&", subject);
}
std::string richTextEscape(std::string_view subject)
{
return cpputils::stringReplaceAll('&', "&&", subject);
}
int16_t renderRichText(std::string_view str, int32_t poX, int32_t poY)
{
return renderRichText(str, poX, poY, tft.textfont);
}
int16_t renderRichText(std::string_view str, int32_t poX, int32_t poY, uint8_t font)
{
if (str.empty())
return 0;
const auto oldColor = tft.textcolor;
int16_t width{};
again:
if (const auto index = str.find('&'); index != std::string_view::npos)
{
{
std::string_view tempStr{std::begin(str), index};
if (!tempStr.empty())
{
const auto addedWith = tft.drawString(tempStr, poX, poY, font);
poX += addedWith;
width += addedWith;
}
}
auto newIter = std::begin(str) + index + 1;
if (newIter != std::end(str))
{
switch (const auto controlChar = *newIter)
{
case '0':
case '1':
case '2':
{
const auto color = [&controlChar](){
switch (controlChar)
{
case '0': return TFT_RED;
case '1': return TFT_GREEN;
case '2': return TFT_BLUE;
}
__builtin_unreachable();
}();
tft.setTextColor(color, tft.textbgcolor);
auto newNewIter = newIter + 1;
if (newNewIter != std::end(str))
{
str = std::string_view(newNewIter, std::distance(newNewIter, std::end(str)));
goto again;
}
break;
}
// case '&':
// {
// const char buf[1] = { '&' };
// const auto addedWith = tft.drawString(std::string_view{buf, std::size(buf)}, poX, poY, font);
// poX += addedWith;
// width += addedWith;
// auto newNewIter = newIter + 1;
// if (newNewIter != std::end(str))
// {
// str = std::string_view(newNewIter, std::distance(newNewIter, std::end(str)));
// goto again;
// }
// break;
// }
default:
{
const char buf[2] = { '&', controlChar };
const auto addedWith = tft.drawString(std::string_view{buf, std::size(buf)}, poX, poY, font);
poX += addedWith;
width += addedWith;
auto newNewIter = newIter + 1;
if (newNewIter != std::end(str))
{
str = std::string_view(newNewIter, std::distance(newNewIter, std::end(str)));
goto again;
}
break;
}
}
}
else
{
const char buf[1] = { '&' };
const auto addedWith = tft.drawString(std::string_view{buf, std::size(buf)}, poX, poY, font);
poX += addedWith;
width += addedWith;
}
}
else if (!str.empty())
{
const auto addedWith = tft.drawString(str, poX, poY, font);
poX += addedWith;
width += addedWith;
}
tft.setTextColor(oldColor, tft.textbgcolor);
return width;
}
} // namespace espgui

18
src/richtextrenderer.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
// system includes
#include <string_view>
#include <string>
// local includes
#include "tftinstance.h"
namespace espgui {
void richTextEscape(std::string &subject);
std::string richTextEscape(std::string_view subject);
int16_t renderRichText(std::string_view str, int32_t poX, int32_t poY);
int16_t renderRichText(std::string_view str, int32_t poX, int32_t poY, uint8_t font);
} // namespace espgui

View File

@ -2,6 +2,7 @@
// local includes
#include "tftinstance.h"
#include "richtextrenderer.h"
namespace espgui {
Label::Label(int x, int y) :
@ -28,7 +29,7 @@ void Label::redraw(std::string_view str, bool forceRedraw)
!forceRedraw)
return;
const auto renderedWidth = str.empty() ? 0 : tft.drawString(str.data(), m_x, m_y);
const auto renderedWidth = renderRichText(str, m_x, m_y);
const auto renderedHeight = tft.fontHeight();
if (renderedWidth < m_lastWidth)