From 2bec83eec0dc2de2d6b8fb0b827e94807ed9b0b8 Mon Sep 17 00:00:00 2001 From: v-rob Date: Sun, 12 Jul 2020 00:48:50 -0700 Subject: [PATCH] Add FormSpec font styling options (#9763) * Add FormSpec font styling options * Change multiplication to stof * Remove extraneous check --- doc/lua_api.txt | 18 ++++++++++++++ src/client/fontengine.cpp | 15 ++++++++++++ src/client/fontengine.h | 3 +++ src/gui/StyleSpec.h | 49 +++++++++++++++++++++++++++++++++++++ src/gui/guiButton.cpp | 1 + src/gui/guiFormSpecMenu.cpp | 28 +++++++++++++-------- src/gui/guiFormSpecMenu.h | 2 +- 7 files changed, 105 insertions(+), 11 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 4e6983be8..d3a367b27 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2747,6 +2747,18 @@ Some types may inherit styles from parent types. button's content when set. * bgimg_pressed - background image when pressed. Defaults to bgimg when not provided. * This is deprecated, use states instead. + * font - Sets font type. This is a comma separated list of options. Valid options: + * Main font type options. These cannot be combined with each other: + * `normal`: Default font + * `mono`: Monospaced font + * Font modification options. If used without a main font type, `normal` is used: + * `bold`: Makes font bold. + * `italic`: Makes font italic. + Default `normal`. + * font_size - Sets font size. Default is user-set. Can have multiple values: + * ``: Sets absolute font size to `number`. + * `+`/`-`: Offsets default font size by `number` points. + * `*`: Multiplies default font size by `number`, similar to CSS `em`. * border - boolean, draw border. Set to false to hide the bevelled button pane. Default true. * content_offset - 2d vector, shifts the position of the button's content without resizing it. * noclip - boolean, set to true to allow the element to exceed formspec bounds. @@ -2758,11 +2770,15 @@ Some types may inherit styles from parent types. * scrollbar * noclip - boolean, set to true to allow the element to exceed formspec bounds. * table, textlist + * font - Sets font type. See button `font` property for more information. + * font_size - Sets font size. See button `font_size` property for more information. * noclip - boolean, set to true to allow the element to exceed formspec bounds. * dropdown * noclip - boolean, set to true to allow the element to exceed formspec bounds. * field, pwdfield, textarea * border - set to false to hide the textbox background and border. Default true. + * font - Sets font type. See button `font` property for more information. + * font_size - Sets font size. See button `font_size` property for more information. * noclip - boolean, set to true to allow the element to exceed formspec bounds. * textcolor - color. Default white. * image @@ -2771,6 +2787,8 @@ Some types may inherit styles from parent types. * item_image * noclip - boolean, set to true to allow the element to exceed formspec bounds. Default to false. * label, vertlabel + * font - Sets font type. See button `font` property for more information. + * font_size - Sets font size. See button `font_size` property for more information. * noclip - boolean, set to true to allow the element to exceed formspec bounds. * image_button (additional properties) * fgimg - standard image. Defaults to none. diff --git a/src/client/fontengine.cpp b/src/client/fontengine.cpp index 61d52cc2f..a55420846 100644 --- a/src/client/fontengine.cpp +++ b/src/client/fontengine.cpp @@ -186,6 +186,21 @@ unsigned int FontEngine::getDefaultFontSize() return m_default_size[m_currentMode]; } +unsigned int FontEngine::getFontSize(FontMode mode) +{ + if (m_currentMode == FM_Simple) { + if (mode == FM_Mono || mode == FM_SimpleMono) + return m_default_size[FM_SimpleMono]; + else + return m_default_size[FM_Simple]; + } + + if (mode == FM_Unspecified) + return m_default_size[FM_Standard]; + + return m_default_size[mode]; +} + /******************************************************************************/ void FontEngine::readSettings() { diff --git a/src/client/fontengine.h b/src/client/fontengine.h index 53f14c45f..865b2d3ff 100644 --- a/src/client/fontengine.h +++ b/src/client/fontengine.h @@ -124,6 +124,9 @@ public: /** get default font size */ unsigned int getDefaultFontSize(); + /** get font size for a specific mode */ + unsigned int getFontSize(FontMode mode); + /** initialize font engine */ void initialize(Settings* main_settings, gui::IGUIEnvironment* env); diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index 3e842e826..67caf4f7b 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -18,9 +18,11 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "client/tile.h" // ITextureSource +#include "client/fontengine.h" #include "debug.h" #include "irrlichttypes_extrabloated.h" #include "util/string.h" +#include #include #pragma once @@ -46,6 +48,8 @@ public: ALPHA, CONTENT_OFFSET, PADDING, + FONT, + FONT_SIZE, NUM_PROPERTIES, NONE }; @@ -98,6 +102,10 @@ public: return CONTENT_OFFSET; } else if (name == "padding") { return PADDING; + } else if (name == "font") { + return FONT; + } else if (name == "font_size") { + return FONT_SIZE; } else { return NONE; } @@ -225,6 +233,47 @@ public: return vec; } + gui::IGUIFont *getFont() const + { + FontSpec spec(FONT_SIZE_UNSPECIFIED, FM_Standard, false, false); + + const std::string &font = properties[FONT]; + const std::string &size = properties[FONT_SIZE]; + + if (font.empty() && size.empty()) + return nullptr; + + std::vector modes = split(font, ','); + + for (size_t i = 0; i < modes.size(); i++) { + if (modes[i] == "normal") + spec.mode = FM_Standard; + else if (modes[i] == "mono") + spec.mode = FM_Mono; + else if (modes[i] == "bold") + spec.bold = true; + else if (modes[i] == "italic") + spec.italic = true; + } + + if (!size.empty()) { + int calc_size = 1; + + if (size[0] == '*') { + std::string new_size = size.substr(1); // Remove '*' (invalid for stof) + calc_size = stof(new_size) * g_fontengine->getFontSize(spec.mode); + } else if (size[0] == '+' || size[0] == '-') { + calc_size = stoi(size) + g_fontengine->getFontSize(spec.mode); + } else { + calc_size = stoi(size); + } + + spec.size = (unsigned)std::min(std::max(calc_size, 1), 999); + } + + return g_fontengine->getFont(spec); + } + video::ITexture *getTexture(Property prop, ISimpleTextureSource *tsrc, video::ITexture *def) const { diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index 6732a9233..e0d6337cd 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -788,6 +788,7 @@ void GUIButton::setFromStyle(const StyleSpec& style) setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); setDrawBorder(style.getBool(StyleSpec::BORDER, true)); setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true)); + setOverrideFont(style.getFont()); if (style.isNotDefault(StyleSpec::BGIMG)) { video::ITexture *texture = style.getTexture(StyleSpec::BGIMG, diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 9618e2134..db89d2c43 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -24,8 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "guiFormSpecMenu.h" -#include "guiScrollBar.h" -#include "guiTable.h" #include "constants.h" #include "gamedef.h" #include "client/keycode.h" @@ -64,9 +62,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiEditBoxWithScrollbar.h" #include "guiInventoryList.h" #include "guiItemImage.h" -#include "guiScrollBar.h" #include "guiScrollContainer.h" -#include "guiTable.h" #include "intlGUIEditBox.h" #include "guiHyperText.h" @@ -1482,6 +1478,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); + e->setOverrideFont(style.getFont()); irr::SEvent evt; evt.EventType = EET_KEY_INPUT_EVENT; @@ -1565,6 +1562,7 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec, if (style.get(StyleSpec::BGCOLOR, "") == "transparent") { e->setDrawBackground(false); } + e->setOverrideFont(style.getFont()); e->drop(); } @@ -1778,6 +1776,11 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) std::vector lines = split(text, '\n'); + auto style = getDefaultStyleForElement("label", ""); + gui::IGUIFont *font = style.getFont(); + if (!font) + font = m_font; + for (unsigned int i = 0; i != lines.size(); i++) { std::wstring wlabel_colors = translate_string( utf8_to_wide(unescape_string(lines[i]))); @@ -1799,7 +1802,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) rect = core::rect( pos.X, pos.Y, - pos.X + m_font->getDimension(wlabel_plain.c_str()).Width, + pos.X + font->getDimension(wlabel_plain.c_str()).Width, pos.Y + imgsize.Y); } else { @@ -1821,7 +1824,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) rect = core::rect( pos.X, pos.Y - m_btn_height, - pos.X + m_font->getDimension(wlabel_plain.c_str()).Width, + pos.X + font->getDimension(wlabel_plain.c_str()).Width, pos.Y + m_btn_height); } @@ -1837,9 +1840,9 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) spec.fid); e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER); - auto style = getDefaultStyleForElement("label", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); + e->setOverrideFont(font); m_fields.push_back(spec); @@ -1867,6 +1870,11 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen MY_CHECKPOS("vertlabel",1); + auto style = getDefaultStyleForElement("vertlabel", "", "label"); + gui::IGUIFont *font = style.getFont(); + if (!font) + font = m_font; + v2s32 pos; core::rect rect; @@ -1880,7 +1888,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen // isn't quite tall enough and cuts off the text. rect = core::rect(pos.X, pos.Y, pos.X + imgsize.X, - pos.Y + font_line_height(m_font) * + pos.Y + font_line_height(font) * (text.length() + 1)); } else { @@ -1892,7 +1900,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen rect = core::rect( pos.X, pos.Y+((imgsize.Y/2) - m_btn_height), pos.X+15, pos.Y + - font_line_height(m_font) * + font_line_height(font) * (text.length() + 1) + ((imgsize.Y/2) - m_btn_height)); } @@ -1917,9 +1925,9 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen rect, false, false, data->current_parent, spec.fid); e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); - auto style = getDefaultStyleForElement("vertlabel", spec.fname, "label"); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF))); + e->setOverrideFont(font); m_fields.push_back(spec); diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index 19026bd34..5a6b467aa 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "inventorymanager.h" #include "modalMenu.h" #include "guiInventoryList.h" +#include "guiScrollBar.h" #include "guiTable.h" #include "network/networkprotocol.h" #include "client/joystick_controller.h" @@ -37,7 +38,6 @@ with this program; if not, write to the Free Software Foundation, Inc., class InventoryManager; class ISimpleTextureSource; class Client; -class GUIScrollBar; class TexturePool; class GUIScrollContainer;