Skip to content

Commit

Permalink
Formspec: add hypertext element
Browse files Browse the repository at this point in the history
  • Loading branch information
pyrollo authored and SmallJoker committed Nov 3, 2019
1 parent 8697090 commit 72416a6
Show file tree
Hide file tree
Showing 22 changed files with 1,792 additions and 79 deletions.
38 changes: 25 additions & 13 deletions builtin/settingtypes.txt
Expand Up @@ -851,35 +851,41 @@ tooltip_append_itemname (Append item name) bool false
# If disabled, bitmap and XML vectors fonts are used instead.
freetype (FreeType fonts) bool true

# Path to the default font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# The fallback font will be used if the font cannot be loaded.
font_path (Font path) filepath fonts/liberationsans.ttf
font_bold (Font bold by default) bool false

# Font size of the default font in point (pt).
font_size (Font size) int 16 1
font_italic (Font italic by default) bool false

# Shadow offset (in pixels) of the default font. If 0, then shadow will not be drawn.
font_shadow (Font shadow) int 1

# Opaqueness (alpha) of the shadow behind the default font, between 0 and 255.
font_shadow_alpha (Font shadow alpha) int 127 0 255

# Path to the monospace font.
# Font size of the default font in point (pt).
font_size (Font size) int 16 1

# Path to the default font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# This font is used for e.g. the console and profiler screen.
mono_font_path (Monospace font path) filepath fonts/liberationmono.ttf
# The fallback font will be used if the font cannot be loaded.
font_path (Regular font path) filepath fonts/Arimo-Regular.ttf

font_path_bold (Bold font path) filepath fonts/Arimo-Bold.ttf
font_path_italic (Italic font path) filepath fonts/Arimo-Italic.ttf
font_path_bolditalic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf

# Font size of the monospace font in point (pt).
mono_font_size (Monospace font size) int 15 1

# Path of the fallback font.
# Path to the monospace font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# This font will be used for certain languages or if the default font is unavailable.
fallback_font_path (Fallback font path) filepath fonts/DroidSansFallbackFull.ttf
# This font is used for e.g. the console and profiler screen.
mono_font_path (Monospace font path) filepath fonts/Cousine-Regular.ttf

mono_font_path_bold (Bold monospace font path) filepath fonts/Cousine-Bold.ttf
mono_font_path_italic (Italic monospace font path) filepath fonts/Cousine-Italic.ttf
mono_font_path_bolditalic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf

# Font size of the fallback font in point (pt).
fallback_font_size (Fallback font size) int 15 1
Expand All @@ -890,6 +896,12 @@ fallback_font_shadow (Fallback font shadow) int 1
# Opaqueness (alpha) of the shadow behind the fallback font, between 0 and 255.
fallback_font_shadow_alpha (Fallback font shadow alpha) int 128 0 255

# Path of the fallback font.
# If “freetype” setting is enabled: Must be a TrueType font.
# If “freetype” setting is disabled: Must be a bitmap or XML vectors font.
# This font will be used for certain languages or if the default font is unavailable.
fallback_font_path (Fallback font path) filepath fonts/DroidSansFallbackFull.ttf

# Path to save screenshots at.
screenshot_path (Screenshot folder) path

Expand Down
112 changes: 110 additions & 2 deletions doc/lua_api.txt
Expand Up @@ -2189,8 +2189,13 @@ Elements
half a coordinate. With the old system, newlines are spaced 2/5 of
an inventory slot.

### `vertlabel[<X>,<Y>;<label>]`
### `hypertext[<X>,<Y>;<W>,<H>;<name>;<text>]`
* Displays a static formated text with hyperlinks.
* `x`, `y`, `w` and `h` work as per field
* `name` is the name of the field as returned in fields to `on_receive_fields` in case of action in text.
* `text` is the formatted text using `markup language` described below.

### `vertlabel[<X>,<Y>;<label>]`
* Textual label drawn vertically
* `label` is the text on the label
* **Note**: If the new coordinate system is enabled, vertlabels are
Expand Down Expand Up @@ -2534,6 +2539,110 @@ Some types may inherit styles from parent types.
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
* textcolor - color. Default white.

Markup language
---------------

Markup language used in `hypertext[]` elements uses tag that look like HTML tags. 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.

These are the technically basic tags but see below for usual tags. Base tags are:

`<style color=... font=... size=...>...</style>`

Changes the style of the text.

* `color`: Text color. Given color is a `colorspec`.
* `size`: Text size.
* `font`: Text font (`mono` or `normal`).

`<global background=... margin=... valign=... color=... hovercolor=... size=... font=... halign=... >`

Sets global style.

Global only styles:
* `background`: Text background, a `colorspec` or `none`.
* `margin`: Page margins in pixel.
* `valign`: Text vertical alignment (`top`, `middle`, `bottom`).

Inheriting styles (affects child elements):
* `color`: Default text color. Given color is a `colorspec`.
* `hovercolor`: Color of <action> tags when mouse is over.
* `size`: Default text size.
* `font`: Default text font (`mono` or `normal`).
* `halign`: Default text horizontal alignment (`left`, `right`, `center`, `justify`).

This tag needs to be placed only once as it changes the global settings of the
text. Anyway, if several tags are placed, each changed will be made in the order
tags appear.

`<tag name=... color=... hovercolor=... font=... size=...>`

Defines or redefines tag style. This can be used to define new tags.
* `name`: Name of the tag to define or change.
* `color`: Text color. Given color is a `colorspec`.
* `hovercolor`: Text color when element hovered (only for `action` tags). Given color is a `colorspec`.
* `size`: Text size.
* `font`: Text font (`mono` or `normal`).

Following tags are the usual tags for text layout. They are defined by default.
Other tags can be added using `<tag ...>` tag.

`<normal>...</normal>`: Normal size text

`<big>...</big>`: Big text

`<bigger>...</bigger>`: Bigger text

`<center>...</center>`: Centered text

`<left>...</left>`: Left-aligned text

`<right>...</right>`: Right-aligned text

`<justify>...</justify>`: Justified text

`<mono>...</mono>`: Monospaced font

`<b>...</b>`, `<i>...</i>`, `<u>...</u>`: Bold, italic, underline styles.

`<action name=...>...</action>`

Make that text a clickable text triggering an action.

* `name`: Name of the action (mandatory).

When clicked, the formspec is send to the server. The value of the text field
sent to `on_player_receive_fields` will be "action:" concatenated to the action
name.

`<img name=... float=... width=... height=...>`

Draws an image which is present in the client media cache.

* `name`: Name of the texture (mandatory).
* `float`: If present, makes the image floating (`left` or `right`).
* `width`: Force image width instead of taking texture width.
* `height`: Force image height instead of taking texture height.

If only width or height given, texture aspect is kept.

`<item name=... float=... width=... height=... rotate=...>`

Draws an item image.

* `name`: Item string of the item to draw (mandatory).
* `float`: If present, makes the image floating (`left` or `right`).
* `width`: Item image width.
* `height`: Item image height.
* `rotate`: Rotate item image if set to `yes` or `X,Y,Z`. X, Y and Z being
rotation speeds in percent of standard speed (-1000 to 1000). Works only if
`inventory_items_animations` is set to true.
* `angle`: Angle in which the item image is shown. Value has `X,Y,Z` form.
X, Y and Z being angles around each three axes. Works only if
`inventory_items_animations` is set to true.

Inventory
=========

Expand All @@ -2557,7 +2666,6 @@ Player Inventory lists
* Is not created automatically, use `InvRef:set_size`
* Is only used to enhance the empty hand's tool capabilities


Colors
======

Expand Down
Binary file added fonts/Arimo-Bold.ttf
Binary file not shown.
Binary file added fonts/Arimo-BoldItalic.ttf
Binary file not shown.
Binary file added fonts/Arimo-Italic.ttf
Binary file not shown.
Binary file added fonts/Cousine-Bold.ttf
Binary file not shown.
Binary file added fonts/Cousine-BoldItalic.ttf
Binary file not shown.
Binary file added fonts/Cousine-Italic.ttf
Binary file not shown.
70 changes: 53 additions & 17 deletions src/client/fontengine.cpp
Expand Up @@ -41,6 +41,11 @@ static void font_setting_changed(const std::string &name, void *userdata)
g_fontengine->readSettings();
}

unsigned int get_font_cache_index(FontMode mode, bool bold = false, bool italic = false)
{
return (mode << 2) | (bold << 1) | italic;
}

/******************************************************************************/
FontEngine::FontEngine(Settings* main_settings, gui::IGUIEnvironment* env) :
m_settings(main_settings),
Expand All @@ -59,7 +64,12 @@ FontEngine::FontEngine(Settings* main_settings, gui::IGUIEnvironment* env) :

if (m_currentMode == FM_Standard) {
m_settings->registerChangedCallback("font_size", font_setting_changed, NULL);
m_settings->registerChangedCallback("font_bold", font_setting_changed, NULL);
m_settings->registerChangedCallback("font_italic", font_setting_changed, NULL);
m_settings->registerChangedCallback("font_path", font_setting_changed, NULL);
m_settings->registerChangedCallback("font_path_bold", font_setting_changed, NULL);
m_settings->registerChangedCallback("font_path_italic", font_setting_changed, NULL);
m_settings->registerChangedCallback("font_path_bolditalic", font_setting_changed, NULL);
m_settings->registerChangedCallback("font_shadow", font_setting_changed, NULL);
m_settings->registerChangedCallback("font_shadow_alpha", font_setting_changed, NULL);
}
Expand Down Expand Up @@ -96,7 +106,8 @@ void FontEngine::cleanCache()
}

/******************************************************************************/
irr::gui::IGUIFont* FontEngine::getFont(unsigned int font_size, FontMode mode)
irr::gui::IGUIFont *FontEngine::getFont(unsigned int font_size, FontMode mode,
bool bold, bool italic)
{
if (mode == FM_Unspecified) {
mode = m_currentMode;
Expand All @@ -110,22 +121,30 @@ irr::gui::IGUIFont* FontEngine::getFont(unsigned int font_size, FontMode mode)
if (font_size == FONT_SIZE_UNSPECIFIED)
font_size = m_default_size[mode];

const auto &cache = m_font_cache[mode];
unsigned int cache_index = get_font_cache_index(mode, bold, italic);

const auto &cache = m_font_cache[cache_index];

if (cache.find(font_size) == cache.end()) {
if (mode == FM_Simple || mode == FM_SimpleMono)
initSimpleFont(font_size, mode);
else
initFont(font_size, mode);
initFont(font_size, mode, bold, italic);
}

if (m_font_cache[cache_index].find(font_size) ==
m_font_cache[cache_index].end())
initFont(font_size, mode, bold, italic);

const auto &font = cache.find(font_size);
return font != cache.end() ? font->second : nullptr;
}

/******************************************************************************/
unsigned int FontEngine::getTextHeight(unsigned int font_size, FontMode mode)
unsigned int FontEngine::getTextHeight(unsigned int font_size, FontMode mode,
bool bold, bool italic)
{
irr::gui::IGUIFont* font = getFont(font_size, mode);
irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic);

// use current skin font as fallback
if (font == NULL) {
Expand All @@ -138,9 +157,9 @@ unsigned int FontEngine::getTextHeight(unsigned int font_size, FontMode mode)

/******************************************************************************/
unsigned int FontEngine::getTextWidth(const std::wstring& text,
unsigned int font_size, FontMode mode)
unsigned int font_size, FontMode mode, bool bold, bool italic)
{
irr::gui::IGUIFont* font = getFont(font_size, mode);
irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic);

// use current skin font as fallback
if (font == NULL) {
Expand All @@ -153,9 +172,10 @@ unsigned int FontEngine::getTextWidth(const std::wstring& text,


/** get line height for a specific font (including empty room between lines) */
unsigned int FontEngine::getLineHeight(unsigned int font_size, FontMode mode)
unsigned int FontEngine::getLineHeight(unsigned int font_size, FontMode mode,
bool bold, bool italic)
{
irr::gui::IGUIFont* font = getFont(font_size, mode);
irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic);

// use current skin font as fallback
if (font == NULL) {
Expand Down Expand Up @@ -183,6 +203,10 @@ void FontEngine::readSettings()

m_currentMode = is_yes(gettext("needs_fallback_font")) ?
FM_Fallback : FM_Standard;

m_default_bold = m_settings->getBool("font_bold");
m_default_italic = m_settings->getBool("font_italic");

} else {
m_currentMode = FM_Simple;
}
Expand Down Expand Up @@ -226,14 +250,17 @@ void FontEngine::updateFontCache()
}

/******************************************************************************/
void FontEngine::initFont(unsigned int basesize, FontMode mode)
void FontEngine::initFont(unsigned int basesize, FontMode mode,
bool bold, bool italic)
{
assert(mode != FM_Unspecified);
assert(basesize != FONT_SIZE_UNSPECIFIED);

if (m_font_cache[mode].find(basesize) != m_font_cache[mode].end())
return;
int cache_index = get_font_cache_index(mode, bold, italic);

if (m_font_cache[cache_index].find(basesize) !=
m_font_cache[cache_index].end())
return;

std::string setting_prefix = "";

Expand All @@ -249,8 +276,13 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode)
break;
}

std::string setting_suffix = (bold) ?
((italic) ? "_bold_italic" : "_bold") :
((italic) ? "_italic" : "");

u32 size = std::floor(RenderingEngine::getDisplayDensity() *
m_settings->getFloat("gui_scaling") * basesize);

if (size == 0) {
errorstream << "FontEngine: attempt to use font size 0" << std::endl;
errorstream << " display density: " << RenderingEngine::getDisplayDensity() << std::endl;
Expand All @@ -260,10 +292,14 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode)
u16 font_shadow = 0;
u16 font_shadow_alpha = 0;
g_settings->getU16NoEx(setting_prefix + "font_shadow", font_shadow);
g_settings->getU16NoEx(setting_prefix + "font_shadow_alpha", font_shadow_alpha);
g_settings->getU16NoEx(setting_prefix + "font_shadow_alpha",
font_shadow_alpha);

std::string wanted_font_path;
wanted_font_path = g_settings->get(setting_prefix + "font_path" + setting_suffix);

std::string fallback_settings[] = {
m_settings->get(setting_prefix + "font_path"),
wanted_font_path,
m_settings->get("fallback_font_path"),
m_settings->getDefault(setting_prefix + "font_path")
};
Expand All @@ -275,7 +311,7 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode)
font_shadow_alpha);

if (font) {
m_font_cache[mode][basesize] = font;
m_font_cache[cache_index][basesize] = font;
return;
}

Expand Down Expand Up @@ -340,7 +376,7 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode)
path.str(""); // Clear
path << basename << "_" << (size + offset * sign) << ext;

if (!fs::PathExists(path.str()))
if (!fs::PathExists(path.str()))
continue;

font = m_env->getFont(path.str().c_str());
Expand All @@ -365,5 +401,5 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode)
}

if (font)
m_font_cache[mode][basesize] = font;
m_font_cache[get_font_cache_index(mode)][basesize] = font;
}

0 comments on commit 72416a6

Please sign in to comment.