This commit is contained in:
y5nw 2024-04-19 09:43:01 +02:00 committed by GitHub
commit 297d2342ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 88 additions and 13 deletions

View File

@ -2681,6 +2681,8 @@ Version History
* Formspec version 7 (5.8.0):
* style[]: Add focused state for buttons
* Add field_enter_after_edit[] (experimental)
* Formspec version 8 (5.9.0):
* hypertext[]: Allow `em` as a length unit
Elements
--------
@ -3535,6 +3537,10 @@ Some tags can enclose text, they open with `<tagname>` and close with `</tagname
Tags can have attributes, in that case, attributes are in the opening tag in
form of a key/value separated with equal signs. Attribute values should not be quoted.
Attributes that describe lengths (font size and image dimensions) can be a regular
number, which describes the size in pixels, or a number with the unit `em`, which
describes the size in relation to the font size of the enclosing element.
If you want to insert a literal greater-than sign or a backslash into the text,
you must escape it by preceding it with a backslash.

View File

@ -70,7 +70,9 @@ This is a normal text.
<bigger><mono>style</mono> test</bigger>
<style color=#FFFF00>Yellow text.</style> <style color=#FF0000>Red text.</style>
<style size=24>Size 24.</style> <style size=16>Size 16</style>. <style size=12>Size 12.</style>
<style size=24>Size 24.</style> <style size=16>Size 16.</style> <style size=12>Size 12.</style>
<style size=2em>Size 2em.</style> <style size=1em>Size 1em.</style> <style size=0.5em>Size 0.5em.</style>
<style size=3em>Size 3em. <style size=0.5em>Half of 3em.</style></style>
<style font=normal>Normal font.</style> <style font=mono>Mono font.</style>
<bigger>Tag test</bigger>
@ -112,6 +114,10 @@ Normal:
<img name=testformspec_item.png float=left>
<mono>float=right</mono>:
<img name=testformspec_item.png float=right>
<mono>width=1em height=2em</mono>:
<img name=testformspec_item.png width=1em height=2em>
<mono>width=2em</mono> inside <mono>width=2em</mono> (should render at <mono>width=4em</mono>):
<style size=2em><img name=testformspec_item.png width=2em></style>
<bigger><mono>item</mono> test</bigger>
Normal:

View File

@ -49,6 +49,49 @@ static bool check_integer(const std::string &str)
return *endptr == '\0';
}
static bool check_length(const std::string &str)
{
return ParsedText::LengthValue(str).isValid();
}
// -----------------------------------------------------------------------------
// LengthValue - A data structure representing a (possibly relative) length
ParsedText::LengthValue::LengthValue(const std::string &str)
{
char *unitptr = nullptr;
this->size = std::strtod(str.c_str(), &unitptr);
if (this->size <= 0)
this->size = 0;
this->unit = unitptr;
}
bool ParsedText::LengthValue::isValid()
{
return this->getAbsoluteValue(1) > 0;
}
double ParsedText::LengthValue::getAbsoluteValue(const double &em_size)
{
if (this->unit.empty())
return this->size;
else if (this->unit == "em")
return this->size * em_size;
else
return 0;
}
double ParsedText::LengthValue::getAbsoluteValue()
{
return getAbsoluteValue(0);
}
bool ParsedText::LengthValue::isAbsolute()
{
return getAbsoluteValue() > 0;
}
// -----------------------------------------------------------------------------
// ParsedText - A text parser
@ -63,7 +106,7 @@ void ParsedText::Element::setStyle(StyleList &style)
if (parseColorString(style["hovercolor"], color, false))
this->hovercolor = color;
unsigned int font_size = std::atoi(style["fontsize"].c_str());
this->font_size = std::atoi(style["fontsize"].c_str());
FontMode font_mode = FM_Standard;
if (style["fontstyle"] == "mono")
@ -72,9 +115,9 @@ void ParsedText::Element::setStyle(StyleList &style)
// hypertext[] only accepts absolute font size values and has a hardcoded
// default font size of 16. This is the only way to make hypertext[]
// respect font size settings that I can think of.
font_size = myround(font_size / 16.0f * g_fontengine->getFontSize(font_mode));
this->font_size = myround(this->font_size / 16.0f * g_fontengine->getFontSize(font_mode));
FontSpec spec(font_size, font_mode,
FontSpec spec(this->font_size, font_mode,
is_yes(style["bold"]), is_yes(style["italic"]));
// TODO: find a way to check font validity
@ -83,7 +126,7 @@ void ParsedText::Element::setStyle(StyleList &style)
if (!this->font)
printf("No font found ! Size=%d, mode=%d, bold=%s, italic=%s\n",
font_size, font_mode, style["bold"].c_str(),
this->font_size, font_mode, style["bold"].c_str(),
style["italic"].c_str());
}
@ -341,9 +384,8 @@ void ParsedText::parseGenericStyleAttr(
style[name] = is_yes(value);
} else if (name == "size") {
if (check_integer(value))
if (check_length(value))
style["fontsize"] = value;
} else if (name == "font") {
if (value == "mono" || value == "normal")
style["fontstyle"] = value;
@ -512,13 +554,13 @@ u32 ParsedText::parseTag(const wchar_t *text, u32 cursor)
}
if (attrs.count("width")) {
int width = stoi(attrs["width"]);
int width = LengthValue(attrs["width"]).getAbsoluteValue(m_element->font_size);
if (width > 0)
m_element->dim.Width = width;
}
if (attrs.count("height")) {
int height = stoi(attrs["height"]);
int height = LengthValue(attrs["height"]).getAbsoluteValue(m_element->font_size);
if (height > 0)
m_element->dim.Height = height;
}
@ -595,9 +637,18 @@ u32 ParsedText::parseTag(const wchar_t *text, u32 cursor)
// Update styles accordingly
m_style.clear();
for (auto tag = m_active_tags.crbegin(); tag != m_active_tags.crend(); ++tag)
for (const auto &prop : (*tag)->style)
m_style[prop.first] = prop.second;
unsigned int font_size = 0;
for (auto tag = m_active_tags.crbegin(); tag != m_active_tags.crend(); ++tag) {
for (const auto &prop : (*tag)->style) {
if (prop.first == "fontsize") {
// resolve font size
font_size = LengthValue(prop.second).getAbsoluteValue(font_size);
} else {
m_style[prop.first] = prop.second;
}
}
}
m_style["fontsize"] = std::to_string(font_size);
return cursor;
}

View File

@ -76,6 +76,17 @@ public:
typedef std::unordered_map<std::string, std::string> StyleList;
typedef std::unordered_map<std::string, std::string> AttrsList;
struct LengthValue
{
double size;
std::string unit;
LengthValue(const std::string &str);
bool isValid();
bool isAbsolute();
double getAbsoluteValue();
double getAbsoluteValue(const double &em_size);
};
struct Tag
{
std::string name;
@ -98,6 +109,7 @@ public:
ValignType valign;
gui::IGUIFont *font;
unsigned int font_size;
irr::video::SColor color;
irr::video::SColor hovercolor;

View File

@ -244,7 +244,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// base64-encoded SHA-1 (27+\0).
// See also formspec [Version History] in doc/lua_api.md
#define FORMSPEC_API_VERSION 7
#define FORMSPEC_API_VERSION 8
#define TEXTURENAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-"