23using std::string_view;
30 , fontFile(
"skins/DejaVuSans.ttf.gz")
37 if (propName ==
"-text") {
45 }
else if (propName ==
"-font") {
47 if (fontFile != val) {
55 }
else if (propName ==
"-size") {
56 int size2 = value.
getInt(interp);
61 }
else if (propName ==
"-wrap") {
63 WrapMode wrapMode2 = [&] {
66 }
else if (val ==
"word") {
68 }
else if (val ==
"char") {
72 "expected one of 'none word char', but got '",
76 if (wrapMode != wrapMode2) {
80 }
else if (propName ==
"-wrapw") {
81 float wrapw2 = value.
getFloat(interp);
82 if (wrapw != wrapw2) {
86 }
else if (propName ==
"-wraprelw") {
87 float wraprelw2 = value.
getFloat(interp);
88 if (wraprelw != wraprelw2) {
99 if (propName ==
"-text") {
101 }
else if (propName ==
"-font") {
103 }
else if (propName ==
"-size") {
105 }
else if (propName ==
"-wrap") {
108 case NONE: wrapString =
"none";
break;
109 case WORD: wrapString =
"word";
break;
110 case CHAR: wrapString =
"char";
break;
114 }
else if (propName ==
"-wrapw") {
116 }
else if (propName ==
"-wraprelw") {
123void OSDText::invalidateLocal()
146uint8_t OSDText::getFadedAlpha()
const
151std::unique_ptr<GLImage> OSDText::create(OutputSurface& output)
154 return std::make_unique<GLImage>(
ivec2(), 0);
161 }
catch (MSXException& e) {
162 throw MSXException(
"Couldn't open font: ",
e.getMessage());
167 int maxWidth = narrow_cast<int>(lrintf(wrapw * narrow<float>(
scale) + wraprelw * pSize.x));
170 maxWidth = std::max(0, maxWidth);
173 unsigned textRgba =
getRGBA(0);
175 if (wrapMode == NONE) {
177 }
else if (wrapMode == WORD) {
178 wrappedText = getWordWrappedText(text, maxWidth);
179 }
else if (wrapMode == CHAR) {
180 wrappedText = getCharWrappedText(text, maxWidth);
188 narrow_cast<uint8_t>(textRgba >> 24),
189 narrow_cast<uint8_t>(textRgba >> 16),
190 narrow_cast<uint8_t>(textRgba >> 8)));
192 return std::make_unique<GLImage>(std::move(surface));
194 return std::make_unique<GLImage>(
ivec2(), 0);
196 }
catch (MSXException& e) {
197 throw MSXException(
"Couldn't render text: ",
e.getMessage());
205static constexpr size_t findCharSplitPoint(string_view line,
size_t min,
size_t max)
207 auto pos = (
min +
max) / 2;
208 auto beginIt = line.data();
209 auto posIt = beginIt + pos;
212 auto maxIt = beginIt +
max;
213 assert(fwdIt <= maxIt);
214 if (fwdIt != maxIt) {
215 return fwdIt - beginIt;
219 auto minIt = beginIt +
min;
220 assert(minIt <= bwdIt); (void)minIt;
221 return bwdIt - beginIt;
229static constexpr size_t findWordSplitPoint(string_view line,
size_t min,
size_t max)
231 constexpr const char*
const delimiters =
" -/";
235 size_t pos = (
min +
max) / 2;
243 if (
auto pos2 = line.substr(
min, pos -
min).find_last_of(delimiters);
244 pos2 != string_view::npos) {
252 if (
auto pos2 = line.substr(pos,
max - pos).find_first_of(delimiters);
253 pos2 != string_view::npos) {
265static constexpr size_t takeSingleChar(string_view ,
unsigned )
270template<
typename FindSplitPo
intFunc,
typename CantSplitFunc>
271size_t OSDText::split(
const string& line,
unsigned maxWidth,
272 FindSplitPointFunc findSplitPoint,
273 CantSplitFunc cantSplit,
274 bool removeTrailingSpaces)
const
282 if (
unsigned width = font.
getSize(line).x; width <= maxWidth) {
290 size_t max = line.size();
293 size_t cur = findSplitPoint(line,
min,
max);
297 return cantSplit(line, maxWidth);
302 string curStr = line.substr(0, cur);
303 if (removeTrailingSpaces) {
306 unsigned width2 = font.
getSize(curStr).x;
307 if (width2 <= maxWidth) {
309 size_t next = findSplitPoint(line, cur,
max);
317 size_t next = findSplitPoint(line,
min, cur);
322 return cantSplit(line, maxWidth);
332size_t OSDText::splitAtChar(
const std::string& line,
unsigned maxWidth)
const
334 return split(line, maxWidth, findCharSplitPoint, takeSingleChar,
false);
339 [[nodiscard]]
size_t operator()(
const string& line,
unsigned maxWidth)
const {
340 return osdText.splitAtChar(line, maxWidth);
344size_t OSDText::splitAtWord(
const std::string& line,
unsigned maxWidth)
const
346 return split(line, maxWidth, findWordSplitPoint,
SplitAtChar(*
this),
true);
349string OSDText::getCharWrappedText(
const string& txt,
unsigned maxWidth)
const
351 std::vector<string_view> wrappedLines;
352 for (
auto line :
StringOp::split_view(txt,
'\n')) {
354 auto p = splitAtChar(
string(line), maxWidth);
355 wrappedLines.push_back(line.substr(0, p));
356 line = line.substr(p);
357 }
while (!line.empty());
359 return join(wrappedLines,
'\n');
362string OSDText::getWordWrappedText(
const string& txt,
unsigned maxWidth)
const
364 std::vector<string_view> wrappedLines;
367 auto p = splitAtWord(
string(line), maxWidth);
368 string_view first = line.substr(0, p);
370 wrappedLines.push_back(first);
371 line = line.substr(p);
373 }
while (!line.empty());
375 return join(wrappedLines,
'\n');
Wrapper around a SDL_Surface.
Represents the output window/screen of openMSX.
OSDText(Display &display, const TclObject &name)
friend struct SplitAtChar
void getProperty(std::string_view name, TclObject &result) const override
void setProperty(Interpreter &interp, std::string_view name, const TclObject &value) override
std::string_view getType() const override
A frame buffer where pixels can be written to.
bool empty() const
Is this an empty font? (a default constructed object).
SDLSurfacePtr render(std::string text, uint8_t r, uint8_t g, uint8_t b) const
Render the given text to a new SDL_Surface.
gl::ivec2 getSize(zstring_view text) const
Return the size in pixels of the text if it would be rendered.
float getFloat(Interpreter &interp) const
int getInt(Interpreter &interp) const
zstring_view getString() const
detail::Joiner< Collection, Separator > join(Collection &&col, Separator &&sep)
void trimRight(string &str, const char *chars)
void trimLeft(string &str, const char *chars)
auto split_view(std::string_view str, Separators separators)
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr mat4 scale(const vec3 &xyz)
bool isRegularFile(const Stat &st)
This file implemented 3 utility functions:
const FileContext & systemFileContext()
constexpr octet_iterator sync_backward(octet_iterator it)
constexpr octet_iterator sync_forward(octet_iterator it)
uint32_t next(octet_iterator &it, octet_iterator end)
SplitAtChar(const OSDText &osdText_)
size_t operator()(const string &line, unsigned maxWidth) const