24using std::string_view;
31 , fontFile(
"skins/Vera.ttf.gz")
38 if (propName ==
"-text") {
46 }
else if (propName ==
"-font") {
48 if (fontFile != val) {
56 }
else if (propName ==
"-size") {
57 int size2 = value.
getInt(interp);
62 }
else if (propName ==
"-wrap") {
64 WrapMode wrapMode2 = [&] {
67 }
else if (val ==
"word") {
69 }
else if (val ==
"char") {
73 "expected one of 'none word char', but got '",
77 if (wrapMode != wrapMode2) {
81 }
else if (propName ==
"-wrapw") {
82 float wrapw2 = value.
getFloat(interp);
83 if (wrapw != wrapw2) {
87 }
else if (propName ==
"-wraprelw") {
88 float wraprelw2 = value.
getFloat(interp);
89 if (wraprelw != wraprelw2) {
100 if (propName ==
"-text") {
102 }
else if (propName ==
"-font") {
104 }
else if (propName ==
"-size") {
106 }
else if (propName ==
"-wrap") {
109 case NONE: wrapString =
"none";
break;
110 case WORD: wrapString =
"word";
break;
111 case CHAR: wrapString =
"char";
break;
115 }
else if (propName ==
"-wrapw") {
117 }
else if (propName ==
"-wraprelw") {
124void OSDText::invalidateLocal()
147uint8_t OSDText::getFadedAlpha()
const
152template<
typename IMAGE> std::unique_ptr<BaseImage> OSDText::create(
153 OutputSurface& output)
156 return std::make_unique<IMAGE>(output,
ivec2(), 0);
163 }
catch (MSXException&
e) {
164 throw MSXException(
"Couldn't open font: ",
e.getMessage());
169 int maxWidth = narrow_cast<int>(lrintf(wrapw * narrow<float>(
scale) + wraprelw * pSize[0]));
175 unsigned textRgba =
getRGBA(0);
177 if (wrapMode == NONE) {
179 }
else if (wrapMode == WORD) {
180 wrappedText = getWordWrappedText(text, maxWidth);
181 }
else if (wrapMode == CHAR) {
182 wrappedText = getCharWrappedText(text, maxWidth);
190 narrow_cast<uint8_t>(textRgba >> 24),
191 narrow_cast<uint8_t>(textRgba >> 16),
192 narrow_cast<uint8_t>(textRgba >> 8)));
194 return std::make_unique<IMAGE>(output, std::move(surface));
196 return std::make_unique<IMAGE>(output,
ivec2(), 0);
198 }
catch (MSXException&
e) {
199 throw MSXException(
"Couldn't render text: ",
e.getMessage());
207static constexpr size_t findCharSplitPoint(string_view line,
size_t min,
size_t max)
209 auto pos = (
min +
max) / 2;
210 auto beginIt = line.data();
211 auto posIt = beginIt + pos;
214 auto maxIt = beginIt +
max;
215 assert(fwdIt <= maxIt);
216 if (fwdIt != maxIt) {
217 return fwdIt - beginIt;
221 auto minIt = beginIt +
min;
222 assert(minIt <= bwdIt); (void)minIt;
223 return bwdIt - beginIt;
231static constexpr size_t findWordSplitPoint(string_view line,
size_t min,
size_t max)
233 constexpr const char*
const delimiters =
" -/";
237 size_t pos = (
min +
max) / 2;
245 if (
auto pos2 = line.substr(
min, pos -
min).find_last_of(delimiters);
246 pos2 != string_view::npos) {
254 if (
auto pos2 = line.substr(pos,
max - pos).find_first_of(delimiters);
255 pos2 != string_view::npos) {
267static constexpr size_t takeSingleChar(string_view ,
unsigned )
272template<
typename FindSplitPo
intFunc,
typename CantSplitFunc>
273size_t OSDText::split(
const string& line,
unsigned maxWidth,
274 FindSplitPointFunc findSplitPoint,
275 CantSplitFunc cantSplit,
276 bool removeTrailingSpaces)
const
284 unsigned width = font.
getSize(line)[0];
285 if (width <= maxWidth) {
293 size_t max = line.size();
296 size_t cur = findSplitPoint(line,
min,
max);
300 return cantSplit(line, maxWidth);
305 string curStr = line.substr(0, cur);
306 if (removeTrailingSpaces) {
309 unsigned width2 = font.
getSize(curStr)[0];
310 if (width2 <= maxWidth) {
312 size_t next = findSplitPoint(line, cur,
max);
320 size_t next = findSplitPoint(line,
min, cur);
325 return cantSplit(line, maxWidth);
335size_t OSDText::splitAtChar(
const std::string& line,
unsigned maxWidth)
const
337 return split(line, maxWidth, findCharSplitPoint, takeSingleChar,
false);
343 return osdText.splitAtChar(line, maxWidth);
347size_t OSDText::splitAtWord(
const std::string& line,
unsigned maxWidth)
const
349 return split(line, maxWidth, findWordSplitPoint,
SplitAtChar(*
this),
true);
352string OSDText::getCharWrappedText(
const string& txt,
unsigned maxWidth)
const
354 std::vector<string_view> wrappedLines;
357 auto p = splitAtChar(
string(line), maxWidth);
358 wrappedLines.push_back(line.substr(0, p));
359 line = line.substr(p);
360 }
while (!line.empty());
362 return join(wrappedLines,
'\n');
365string OSDText::getWordWrappedText(
const string& txt,
unsigned maxWidth)
const
367 std::vector<string_view> wrappedLines;
370 auto p = splitAtWord(
string(line), maxWidth);
371 string_view first = line.substr(0, p);
373 wrappedLines.push_back(first);
374 line = line.substr(p);
376 }
while (!line.empty());
378 return join(wrappedLines,
'\n');
381std::unique_ptr<BaseImage> OSDText::createSDL(OutputSurface& output)
383 return create<SDLImage>(output);
386std::unique_ptr<BaseImage> OSDText::createGL(OutputSurface& output)
389 return create<GLImage>(output);
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, char c)
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)