Merge branch 'dev' for version 1.2.3

This commit is contained in:
Pierre-Yves Rollo 2018-12-14 11:13:37 +01:00
commit 199f9c7a13
15 changed files with 364 additions and 280 deletions

@ -30,104 +30,78 @@ Extra font mods can be found here:
### December 2018 ### December 2018
Following objects are deprecated, shows a warning in log when used: Following objects are deprecated, shows a warning in log when used:
* `display_modpack_node` group (use `display_api` group instead); * `display_modpack_node` group (use `display_api` group instead);
* `display_lib_node` group (use `display_api` group instead); * `display_lib_node` group (use `display_api` group instead);
* `display_lib` global table (use `display_api` global table instead); * `display_lib` global table (use `display_api` global table instead);
* `font_lib` global table (use `font_api` global table instead);
These objects will be removed in the future. These objects will be removed in the future.
## Changelog ## Changelog
### 2018-12-02 (Version 1.2.2) ### 2018-12-14 (Version 1.2.3)
- __display_api__: New `yaw` attributes, entities can now have different angles with node.
- __font_api__: New `Font:render` method for texture creation
- __font_api__: Specific management for fixed width font. Allows number of columns based texture width.
- __font_api__: Improve `display_api` integration into `font_api`. Display API fully optional. `font_api.on_display_update` defined only if `display_api` enabled.
- __font_api__: Improve management of invalid UTF strings (should not crash anymore)
- __font_api__: Deprecation of `font_lib`
- __signs__: Fixed craft recipe for labels
### 2018-12-02 (Version 1.2.2)
- Fixed a bug that prevented Display API from working on some systems (Raspberry Pi) - Fixed a bug that prevented Display API from working on some systems (Raspberry Pi)
### 2018-11-01 (Version 1.2.1) ### 2018-11-01 (Version 1.2.1)
- Now font can be chosen per sign / stele - Now font can be chosen per sign / stele
### 2018-11-01 (Version 1.2) ### 2018-11-01 (Version 1.2)
- Labels and woodend signs added. - Labels and woodend signs added.
- Fallback mechanism for missing chars (For example: "é" --> "e" --> "E"). - Fallback mechanism for missing chars (For example: "é" --> "e" --> "E").
- Several bug fixes by 12Me21 and naturefreshmilk. - Several bug fixes by 12Me21 and naturefreshmilk.
### 2018-07-16 (Version 1.1.1) ### 2018-07-16 (Version 1.1.1)
- Boards mod added. - Boards mod added.
- Bug fix in default font chosing when multiple font registered. - Bug fix in default font chosing when multiple font registered.
### 2018-07-13 (Version 1.1.0) ### 2018-07-13 (Version 1.1.0)
- Font API rework introducing Font class. - Font API rework introducing Font class.
- Replaced default Epilepsy Font by Metro Font for licensing purposes, - Replaced default Epilepsy Font by Metro Font for licensing purposes,
- Rework of all nodes displaying text accordingly to the Font API rework. - Rework of all nodes displaying text accordingly to the Font API rework.
As font_epilepsy mod has been replaced by font_metro mod, **don't forget to activate font_metro mod after updating** or you won't have any text displayed. As font_epilepsy mod has been replaced by font_metro mod, **don't forget to activate font_metro mod after updating** or you won't have any text displayed.
### 2018-05-30 (Version 1.0.1) ### 2018-05-30 (Version 1.0.1)
Mostly bug fixes : Mostly bug fixes :
- Fix steles orientation when placing - Fix steles orientation when placing
- Update entity on mapblock load - Update entity on mapblock load
- Use default formspec style - Use default formspec style
- Fix ndef nill value in steles mod when technics not installed - Fix ndef nill value in steles mod when technics not installed
- Seperate signs API from signs définitions - Seperate signs API from signs définitions
- Allow a greater offset between display and block - Allow a greater offset between display and block
### 2018-01-13 (Version 1.0) ### 2018-01-13 (Version 1.0)
- Switch to Epilepsy font by KREATIVE SOFTWARE - Switch to Epilepsy font by KREATIVE SOFTWARE
- Add settings "default_font" - Add settings "default_font"
- Add horizontal alignment - Add horizontal alignment
- Add tool for creating font textures from .ttf font files - Add tool for creating font textures from .ttf font files
- Fix UTF 8 to Unicode decoding - Fix UTF 8 to Unicode decoding
- Updated forum thread link in README.md - Updated forum thread link in README.md
### 2017-12-19 ### 2017-12-19
This change is a preparation to merge Andrzej Pieńkowski fork (apienk) : new font and support of UTF chars. This change is a preparation to merge Andrzej Pieńkowski fork (apienk) : new font and support of UTF chars.
- Font\_lib support for multiple fonts (nothing yet visible in mods) ; - Font\_lib support for multiple fonts (nothing yet visible in mods) ;
- Font\_lib support for Unicode characters (limited to Unicode Plane 0: 0000-FFFF, see [Wikipedia](https://en.wikipedia.org/wiki/Unicode)) ; - Font\_lib support for Unicode characters (limited to Unicode Plane 0: 0000-FFFF, see [Wikipedia](https://en.wikipedia.org/wiki/Unicode)) ;
- New "default" font with original textures from Vanessa Ezekowitz (VanessaE) ; - New "default" font with original textures from Vanessa Ezekowitz (VanessaE) ;
### 2017-12-10 ### 2017-12-10
- Compatibility of signs mod with signs_lib (thanks to gpcf) ; - Compatibility of signs mod with signs_lib (thanks to gpcf) ;
- Added large banner in road signs (thanks to gpcf) ; - Added large banner in road signs (thanks to gpcf) ;
### 2017-08-26 ### 2017-08-26
- Changed signs from wallmounted to facedir to improve textures and make it possible to use screwdriver. - Changed signs from wallmounted to facedir to improve textures and make it possible to use screwdriver.
**IMPORTANT** : Map will be updated to change to new nodes but inventory items will turn into "Unknown items" and have to be re-crafted. **IMPORTANT** : Map will be updated to change to new nodes but inventory items will turn into "Unknown items" and have to be re-crafted.
- Intllib support added with french translation (whole modpack, thanks to fat115) ; - Intllib support added with french translation (whole modpack, thanks to fat115) ;
- Punch on nodes to update entity (signs, signs_road and steles). Usefull in case of /clearobjects ; - Punch on nodes to update entity (signs, signs_road and steles). Usefull in case of /clearobjects ;
- Changed wooden direction sign textures (signs) ; - Changed wooden direction sign textures (signs) ;
- Added back and side textures to all signs (road_signs) ; - Added back and side textures to all signs (road_signs) ;
- Added more sign types : White/yellow/green signs and direction signs (signs_road) ; - Added more sign types : White/yellow/green signs and direction signs (signs_road) ;

@ -1,38 +1,38 @@
# Display Lib API # Display API
This document describes Display Lib API. Display Lib allows to add a dynamic display on a node. Display Lib limits node rotations. For wallmounted, only vertical positionning is available, and for facedir, only first four position are availabel (those with default axis). This document describes Display API. Display API allows to add a dynamic display on a node. Display API limits node rotations. For wallmounted, only vertical positionning is available. For facedir, only first four position are availabel (those with default axis).
## Provided methods ## Provided methods
### update\_entities ### update\_entities
**display\_lib.update\_entities(pos)** **display\_api.update\_entities(pos)**
This method triggers entities update for the display node at pos. Actual entity update is made by `on_display_update` callback associated to the entity. This method triggers entities update for the display node at pos. Actual entity update is made by `on_display_update` callback associated to the entity.
`pos`: Position of the node `pos`: Position of the node
### register\_display\_entity ### register\_display\_entity
**display\_lib.register\_display\_entity(entity_name)** **display\_api.register\_display\_entity(entity_name)**
This is a helper to register entities used for display. This is a helper to register entities used for display.
`entity_name`: Name of the entity to register. `entity_name`: Name of the entity to register.
## Provided callback implementations ## Provided callback implementations
### on_place ### on_place
**display\_lib.on\_place(itemstack, placer, pointed\_thing)** **display\_api.on\_place(itemstack, placer, pointed\_thing)**
`on_place` node callback implementation. Display nodes should have this callback (avoid placement of horizontal display node). `on_place` node callback implementation. Display nodes should have this callback (avoid placement of horizontal display node).
### on_construct ### on_construct
**display\_lib.on\_construct(pos)** **display\_api.on\_construct(pos)**
`on_construct` node callback implementation. Display nodes should have this callback (creates, places and updates display entities on node construction). `on_construct` node callback implementation. Display nodes should have this callback (creates, places and updates display entities on node construction).
### on_destruct ### on_destruct
**display\_lib.on_destruct(pos)** **display\_api.on_destruct(pos)**
`on_destruct` node callback implementation. Display nodes should have this callback (removes display entities on node destruction). `on_destruct` node callback implementation. Display nodes should have this callback (removes display entities on node destruction).
### on_rotate ### on_rotate
**display\_lib.on\_rotate(pos, node, user, mode, new_param2)** **display\_api.on\_rotate(pos, node, user, mode, new_param2)**
`on_rotate` node callback implementation. Display nodes should have this callback (restricts rotations and rotates display entities associated with node). `on_rotate` node callback implementation. Display nodes should have this callback (restricts rotations and rotates display entities associated with node).
### on_activate ### on_activate
**display\_lib.on_activate(entity, staticdata)** **display\_api.on_activate(entity, staticdata)**
`On_activate` entity callback implementation for display entities. No need of this method if display entities have been registered using `register_display_entity` (callback is already set). `On_activate` entity callback implementation for display entities. No need of this method if display entities have been registered using `register_display_entity` (callback is already set).
@ -40,17 +40,16 @@ This is a helper to register entities used for display.
* Register display entities with `register_display_entity` * Register display entities with `register_display_entity`
* Register node with : * Register node with :
- `on_place`, `on_construct`, `on_destruct` and `on_rotate` callbacks using display_api callbacks. - `on_place`, `on_construct`, `on_destruct` and `on_rotate` callbacks using display_api callbacks.\
- `display_api` group. This will make this node have their entities updated as soon as the mapblock is loaded (Useful after /clearobjects). - `display_api` group. This will make this node have their entities updated as soon as the mapblock is loaded (Useful after /clearobjects).\
- a `display_entities` field in node definition containing a entity name indexed table. See below for description of each display_entities fields. - a `display_entities` field in node definition containing a entity name indexed table. See below for description of each display_entities fields.\
### Display_entities fields ### Display_entities fields
`on_display_update` is a callback in charge of setting up entity texture. If not set, entity will have no texture and will be displayed as unknown item. `on_display_update` is a callback in charge of setting up entity texture. If not set, entity will have no texture and will be displayed as unknown item.\
`depth`, `right` and `height`: Entity position regarding to node facedir/wallmounted main axis.\
`depth`, `right` and `height`: Entity position regarding to node facedir/wallmounted main axis. Values for these fields can be any number between -1.5 and 1.5 (default value is 0). Position 0,0,0 is the center of the node.\
Values for these fields can be any number between -1.5 and 1.5 (default value is 0). `depth` goes from front (-0.5) to rear (0.5), `height` goes from bottom (-0.5) to top (0.5) and `right` goes from left (-0.5) to right (0.5).\
Position 0,0,0 is the center of the node. `yaw`: Entity yaw in radians, regarding to main axis. Default is 0, aligned to node face.
`depth` goes from front (-0.5) to rear (0.5), `height` goes from bottom (-0.5) to top (0.5) and `right` goes from left (-0.5) to right (0.5).
In order to avoid flickering text, it's better to have text a little behind node surface. A good spacing value is given by `display_api.entity_spacing` variable. In order to avoid flickering text, it's better to have text a little behind node surface. A good spacing value is given by `display_api.entity_spacing` variable.

@ -12,3 +12,12 @@ This library's purpose is to ease creation of nodes with one or more displays on
For more information, see the [forum topic](https://forum.minetest.net/viewtopic.php?t=19365) at the Minetest forums. For more information, see the [forum topic](https://forum.minetest.net/viewtopic.php?t=19365) at the Minetest forums.
## Deprecation notice (for modders)
### December 2018
Following objects are deprecated, shows a warning in log when used:
* `display_modpack_node` group (use `display_api` group instead);
* `display_lib_node` group (use `display_api` group instead);
* `display_lib` global table (use `display_api` global table instead);
These objects will be removed in the future.

@ -106,13 +106,12 @@ local function place_entities(pos)
y = pos.y - top, y = pos.y - top,
z = pos.z - values.dz * depth + values.rz * right}) z = pos.z - values.dz * depth + values.rz * right})
objrefs[entity_name]:setyaw(values.yaw) objrefs[entity_name]:setyaw(values.yaw + (props.yaw or 0))
end end
end end
return objrefs return objrefs
end end
--- Entity update --- Entity update
function update_entity(entity) function update_entity(entity)
if not entity then if not entity then

@ -1,5 +1,5 @@
# Font Lib API # Font API
This document describes Font Lib API. Font Lib creates textures for font display on entities. This document describes Font API. Font API creates textures for font display on entities.
## Settings ## Settings
### default_font ### default_font
@ -37,7 +37,7 @@ minetest.register_node("mymod:test_text_node", {
}) })
``` ```
At this step, your node already displays text form "display_text" (hardcoded) node meta. At this step, your node already displays text form "display_text" (by default) node meta. If you want to store your text into another meta data field, add a `meta_text` field to display entity definition.
But it uses defaults (default font, default size, default color). Likely you need something more. But it uses defaults (default font, default size, default color). Likely you need something more.
@ -59,6 +59,28 @@ Then specify the char width. Two methods available:
* `halign`: Horizontal alignment: "left", "center" or "right" (default "center"). * `halign`: Horizontal alignment: "left", "center" or "right" (default "center").
* `valign`: Vertical alignement: "top", "middle" or "bottom" (default "middle"). * `valign`: Vertical alignement: "top", "middle" or "bottom" (default "middle").
### Example
Using blue //botic// font, three lines height, aligned top left. Text stored in "text" node meta.
```
minetest.register_node("mymod:test_text_node", {
...
...
display_entities = {
["mymod:text"] = {
depth = -0.5 - display_api.entity_spacing,
on_display_update = font_api.on_display_update
meta_text = "text",
font_name = "botic",
color = "#0000FF",
maxlines = 3,
aspect_ratio = 0.5,
halign = "left",
valign = "top",
},
}
...
})
```
## Provided methods ## Provided methods
### font_api.get_default_font_name() ### font_api.get_default_font_name()
Returns de default font name. Returns de default font name.
@ -75,7 +97,7 @@ Standard on_display_update entity callback.
Node should have a corresponding display_entity with size, resolution and maxlines fields and optionally halign, valign and color fields. Node should have a corresponding display_entity with size, resolution and maxlines fields and optionally halign, valign and color fields.
### Font definition table ## Font definition table
Font definition table used by **font_api.register_font** and **font\_api.Font:new** may/can contain following elements: Font definition table used by **font_api.register_font** and **font\_api.Font:new** may/can contain following elements:
* `height` (required): Font height in pixels (all font textures should have the same height) . * `height` (required): Font height in pixels (all font textures should have the same height) .
@ -86,6 +108,14 @@ Font definition table used by **font_api.register_font** and **font\_api.Font:ne
`margintop`, `marginbottom` and `linespacing` can be negative numbers (default 0) and are to be used to adjust various font styles to each other. `margintop`, `marginbottom` and `linespacing` can be negative numbers (default 0) and are to be used to adjust various font styles to each other.
Font attributes around a single char:\
![Font attributes on a char](doc/font.svg)
Font attributes effects on several lines:\
![Font attributes on lines](doc/lines.svg)
#### Additional requirements
Font must have a char 0 which will be used to display any unknown char. Font must have a char 0 which will be used to display any unknown char.
All textures corresponding to the indexes in widths array should be present in textures directory with a name matching the pattern : All textures corresponding to the indexes in widths array should be present in textures directory with a name matching the pattern :
@ -159,19 +189,13 @@ Returns line(s) height. Takes care of top and bottom margins and line spacing.
Returns the width of a text line. Beware, if line contains any new line char, they are ignored. Returns the width of a text line. Beware, if line contains any new line char, they are ignored.
* `line`: Line of text which the width will be computed. * `line`: Line of text which the width will be computed.
### font:make_line_texture(line, texturew, x, y) ### font:renter(text, texturew, textureh, style)
Create a texture for a text line.
* `line`: Line of text to be rendered in texture.
* `texturew`: Width of the texture (extra text is not rendered).
* `x`: Starting x position in texture.
* `y`: Vertical position of the line in texture.
### font:make_text_texture(text, texturew, textureh, maxlines, halign, valign, color)
Builds texture for a multiline colored text. Builds texture for a multiline colored text.
* `text`: Text to be rendered. * `text`: Text to be rendered.
* `texturew`: Width of the texture (extra text will be truncated). * `texturew`: Width of the texture (extra text will be truncated).
* `textureh`: Height of the texture. * `textureh`: Height of the texture (extra text will be truncated).
* `maxlines`: Maximum number of lines. * `style`: A table with style indications:
* `halign`: Horizontal text align ("left"/"center"/"right") (optional). - `lines` or `maxlines`: Maximum number of lines (default none).
* `valign`: Vertical text align ("top"/"center"/"bottom") (optional). - `halign`: Horizontal text align: "left"/"center"/"right" (default "center")
* `color`: Color of the text (optional). - `valign`: Vertical text align: "top"/"middle"/"bottom" (default "middle")
- `color`: Color of the text (default black)

@ -21,3 +21,11 @@ Font mods can be found here:
* [Metro](https://github.com/pyrollo/display_modpack/tree/master/font_metro): A multipurpose font with many chars (uppercase, lowercase and accentuated latin letters, usual signs, cyrillic and greek letters). * [Metro](https://github.com/pyrollo/display_modpack/tree/master/font_metro): A multipurpose font with many chars (uppercase, lowercase and accentuated latin letters, usual signs, cyrillic and greek letters).
* [OldWizard](https://github.com/pyrollo/font_oldwizard): An old style gothic font. * [OldWizard](https://github.com/pyrollo/font_oldwizard): An old style gothic font.
* [Botic](https://github.com/pyrollo/font_botic): A scifi style font. * [Botic](https://github.com/pyrollo/font_botic): A scifi style font.
## Deprecation notice (for modders)
### December 2018
Following object is deprecate, shows a warning in log when used:
* `font_lib` global table (use `font_api` global table instead);
This object will be removed in the future.

@ -0,0 +1 @@
display_api?

54
font_api/deprecation.lua Normal file

@ -0,0 +1,54 @@
--[[
font_api mod for Minetest - Library creating textures with fonts and text
(c) Pierre-Yves Rollo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
--]]
-- Deprecation
function deprecated_global_table(deprecated_global_name, replacement_global_name)
assert(type(deprecated_global_name) == 'string', "deprecated_global_name should be a string.")
assert(type(replacement_global_name) == 'string', "replacement_global_name should be a string.")
assert(deprecated_global_name ~= '', "deprecated_global_name should not be empty.")
assert(replacement_global_name ~= '', "replacement_global_name should not be empty.")
assert(rawget(_G, deprecated_global_name) == nil, "replacement global already exists.")
if _G[replacement_global_name] == nil then
print('warn_deprecated_functions: Warning, replacement global "'..replacement_global_name..'" does not exists.')
return
end
local meta = {
deprecated = deprecated_global_name,
replacement = replacement_global_name,
__index = function(table, key)
local meta = getmetatable(table)
local dbg = debug.getinfo(2, "lS")
minetest.log("warning", string.format('Warning: Accessing deprecated "%s" table, "%s" should be used instead (%s:%d).',
meta.deprecated, meta.replacement, (dbg.short_src or 'unknown'), (dbg.currentline or 0)))
return _G[meta.replacement][key]
end,
__newindex = function(table, key, value)
local meta = getmetatable(table)
local dbg = debug.getinfo(2, "lS")
minetest.log("warning", string.format('Warning: Accessing deprecated "%s" table, "%s" should be used instead (%s:%d).',
meta.deprecated, meta.replacement, (dbg.short_src or 'unknown'), (dbg.currentline or 0)))
_G[meta.replacement][key]=value
end,
}
rawset(_G, deprecated_global_name, {})
setmetatable(_G[deprecated_global_name], meta)
end
-- deprecated(2) -- December 2018 - Deprecation of font_lib
deprecated_global_table('font_lib', 'font_api')

76
font_api/display_api.lua Normal file

@ -0,0 +1,76 @@
--[[
font_api mod for Minetest - Library creating textures with fonts and text
(c) Pierre-Yves Rollo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
--]]
-- Integration with display API
if minetest.get_modpath("display_api") then
--- Standard on_display_update entity callback.
-- Node should have properly configured display_entity.
-- @param pos Node position
-- @param objref Object reference of entity
font_api.on_display_update = function (pos, objref)
local meta = minetest.get_meta(pos)
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
local entity = objref:get_luaentity()
if not entity or not ndef.display_entities[entity.name] then
return
end
local def = ndef.display_entities[entity.name]
local font = font_api.get_font(meta:get_string("font") ~= ""
and meta:get_string("font") or def.font_name)
local text = meta:get_string(def.meta_text or "display_text")
-- Compute entity resolution accroding to given attributes
local texturew, textureh
textureh = font:get_height(def.lines or def.maxlines or 1)
if def.columns then
if font.fixedwidth then
texturew = def.columns * font.fixedwidth
if def.aspect_ratio then
minetest.log('warning', "[font_api] 'aspect_ratio' ignored because 'columns' is specified")
end
else
minetest.log('warning', "[font_api] 'columns' ignored because '"..font.name.."' is not a fixed width font.")
end
end
if not texturew then
if not def.aspect_ratio then
minetest.log('warning', "[font_api] No 'aspect_ratio' specified, using default 1.")
end
texturew = textureh * def.size.x / def.size.y / (def.aspect_ratio or 1)
end
objref:set_properties({
textures={ font:render(text, texturew, textureh, {
lines = def.maxlines or def.lines,
halign = def.halign,
valign = def.valign,
color = def.color} ) },
visual_size = def.size,
})
end
else
font_api.on_display_update = function (pos, objref)
minetest.log('error', '[font_api] font_api.on_display_update called but display_api mod not enabled.')
end
end

@ -1,6 +1,5 @@
--[[ --[[
font_api mod for Minetest - Library to add font display capability font_api mod for Minetest - Library creating textures with fonts and text
to display_api mod.
(c) Pierre-Yves Rollo (c) Pierre-Yves Rollo
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify

@ -1,6 +1,5 @@
--[[ --[[
font_api mod for Minetest - Library to add font display capability font_api mod for Minetest - Library creating textures with fonts and text
to display_api mod.
(c) Pierre-Yves Rollo (c) Pierre-Yves Rollo
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -39,14 +38,15 @@ local function char_to_codepoint(str)
local bytes = get_char_bytes(str) local bytes = get_char_bytes(str)
if bytes == 1 then if bytes == 1 then
return str:byte(1) return str:byte(1)
elseif bytes == 2 then elseif bytes == 2 and str:byte(2) ~= nil then
return (str:byte(1) - 0xC2) * 0x40 return (str:byte(1) - 0xC2) * 0x40
+ str:byte(2) + str:byte(2)
elseif bytes == 3 then elseif bytes == 3 and str:byte(2) ~= nil and str:byte(3) ~= nil then
return (str:byte(1) - 0xE0) * 0x1000 return (str:byte(1) - 0xE0) * 0x1000
+ str:byte(2) % 0x40 * 0x40 + str:byte(2) % 0x40 * 0x40
+ str:byte(3) % 0x40 + str:byte(3) % 0x40
elseif bytes == 4 then -- Not tested elseif bytes == 4 and str:byte(2) ~= nil and str:byte(3) ~= nil
and str:byte(4) ~= nil then -- Not tested
return (str:byte(1) - 0xF0) * 0x40000 return (str:byte(1) - 0xF0) * 0x40000
+ str:byte(2) % 0x40 * 0x1000 + str:byte(2) % 0x40 * 0x1000
+ str:byte(3) % 0x40 * 0x40 + str:byte(3) % 0x40 * 0x40
@ -54,20 +54,6 @@ local function char_to_codepoint(str)
end end
end end
-- Split multiline text into array of lines, with <maxlines> maximum lines.
-- Can not use minetest string.split as it has bug if first line(s) empty
local function split_lines(text, maxlines)
local lines = {}
local pos = 1
repeat
local found = string.find(text, "\n", pos)
found = found or #text + 1
lines[#lines + 1] = string.sub(text, pos, found - 1)
pos = found + 1
until (maxlines and (#lines >= maxlines)) or (pos > (#text + 1))
return lines
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
--- Font class --- Font class
@ -131,6 +117,12 @@ function Font:get_next_char(text)
local codepoint = char_to_codepoint(text) local codepoint = char_to_codepoint(text)
if codepoint == nil then
minetest.log("warning",
"[font_api] Encountered a non UTF char, not displaying text.")
return nil, ''
end
-- Fallback mechanism -- Fallback mechanism
if self.widths[codepoint] == nil then if self.widths[codepoint] == nil then
local char = text:sub(1, bytes) local char = text:sub(1, bytes)
@ -189,94 +181,94 @@ function Font:get_width(line)
while line ~= "" do while line ~= "" do
codepoint, line = self:get_next_char(line) codepoint, line = self:get_next_char(line)
if codepoint == nil then return 0 end -- UTF Error
width = width + self:get_char_width(codepoint) width = width + self:get_char_width(codepoint)
end end
return width return width
end end
--- Builds texture part for a text line --- Legacy make_text_texture method (replaced by "render" - Dec 2018)
-- @param line Text line to be rendered
-- @param texturew Width of the texture (extra text is not rendered)
-- @param x Starting x position in texture
-- @param y Vertical position of the line in texture
-- @return Texture string
function Font:make_line_texture(line, texturew, x, y)
local codepoint
local texture = ""
line = line or ''
while line ~= '' do
codepoint, line = self:get_next_char(line)
-- Add image only if it is visible (at least partly)
if x + self:get_char_width(codepoint) >= 0 and x <= texturew then
texture = texture..
string.format(":%d,%d=font_%s_%04x.png",
x, y, self.name, codepoint)
end
x = x + self:get_char_width(codepoint)
end
return texture
end
--- Builds texture for a multiline colored text
-- @param text Text to be rendered
-- @param texturew Width of the texture (extra text will be truncated)
-- @param textureh Height of the texture
-- @param maxlines Maximum number of lines
-- @param halign Horizontal text align ("left"/"center"/"right") (optional)
-- @param valign Vertical text align ("top"/"center"/"bottom") (optional)
-- @param color Color of the text (optional)
-- @return Texture string
function Font:make_text_texture(text, texturew, textureh, maxlines, function Font:make_text_texture(text, texturew, textureh, maxlines,
halign, valign, color) halign, valign, color)
local texture = "" return self:render(text, texturew, textureh, {
local lines = {} lines = maxlines,
local textheight = 0 valign = valign,
local y halign = halign,
color = color
-- Split text into lines (limited to maxlines fist lines) })
for num, line in pairs(split_lines(text, maxlines)) do
lines[num] = { text = line, width = self:get_width(line) }
end end
textheight = self:get_height(#lines) --- Render text with the font in a view
-- @param text Text to be rendered
-- @param texturew Width (in pixels) of the texture (extra text will be truncated)
-- @param textureh Height (in pixels) of the texture (extra text will be truncated)
-- @param style Style of the rendering:
-- - lines: maximum number of text lines (if text is limited)
-- - halign: horizontal align ("left"/"center"/"right")
-- - valign: vertical align ("top"/"center"/"bottom")
-- - color: color of the text ("#rrggbb")
-- @return Texture string
if #lines then function Font:render(text, texturew, textureh, style)
if valign == "top" then local style = style or {}
-- Split text into lines (and limit to style.lines # of lines)
local lines = {}
local pos = 1
local found, line
repeat
found = string.find(text, "\n", pos) or (#text + 1)
line = string.sub(text, pos, found - 1)
lines[#lines + 1] = { text = line, width = self:get_width(line) }
pos = found + 1
until (style.lines and (#lines >= style.lines)) or (pos > (#text + 1))
if not #lines then
return ""
end
local x, y, codepoint
local texture = ""
local textheight = self:get_height(#lines)
if style.valign == "top" then
y = 0 y = 0
elseif valign == "bottom" then elseif style.valign == "bottom" then
y = textureh - textheight y = textureh - textheight
else else
y = (textureh - textheight) / 2 y = (textureh - textheight) / 2
end end
end
y = y + (self.margintop or 0) y = y + (self.margintop or 0)
for _, line in pairs(lines) do for _, line in pairs(lines) do
if halign == "left" then if style.halign == "left" then
texture = texture.. x = 0
self:make_line_texture(line.text, texturew, elseif style.halign == "right" then
0, y) x = texturew - line.width
elseif halign == "right" then
texture = texture..
self:make_line_texture(line.text, texturew,
texturew - line.width, y)
else else
x = (texturew - line.width) / 2
end
while line.text ~= '' do
codepoint, line.text = self:get_next_char(line.text)
if codepoint == nil then return '' end -- UTF Error
-- Add image only if it is visible (at least partly)
if x + self.widths[codepoint] >= 0 and x <= texturew then
texture = texture.. texture = texture..
self:make_line_texture(line.text, texturew, string.format(":%d,%d=font_%s_%04x.png", x, y, self.name, codepoint)
(texturew - line.width) / 2, y) end
x = x + self.widths[codepoint]
end end
y = y + self:get_height() + (self.linespacing or 0) y = y + self:get_height() + (self.linespacing or 0)
end end
texture = string.format("[combine:%dx%d", texturew, textureh)..texture texture = string.format("[combine:%dx%d", texturew, textureh)..texture
if color then texture = texture.."^[colorize:"..color end if style.color then
texture = texture.."^[colorize:"..style.color
end
return texture return texture
end end

@ -1,6 +1,5 @@
--[[ --[[
font_api mod for Minetest - Library to add font display capability font_api mod for Minetest - Library creating textures with fonts and text
to display_api mod.
(c) Pierre-Yves Rollo (c) Pierre-Yves Rollo
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify

@ -1,6 +1,5 @@
--[[ --[[
font_api mod for Minetest - Library to add font display capability font_api mod for Minetest - Library creating textures with fonts and text
to display_api mod.
(c) Pierre-Yves Rollo (c) Pierre-Yves Rollo
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -30,53 +29,7 @@ font_api.path = minetest.get_modpath(font_api.name)
dofile(font_api.path.."/font.lua") dofile(font_api.path.."/font.lua")
dofile(font_api.path.."/registry.lua") dofile(font_api.path.."/registry.lua")
dofile(font_api.path.."/fontform.lua") dofile(font_api.path.."/fontform.lua")
if minetest.get_modpath("display_api") then
--- Standard on_display_update entity callback. dofile(font_api.path.."/display_api.lua")
-- Node should have a corresponding display_entity with size, resolution and
-- maxlines fields and optionally halign, valign and color fields
-- @param pos Node position
-- @param objref Object reference of entity
function font_api.on_display_update(pos, objref)
local meta = minetest.get_meta(pos)
local text = meta:get_string("display_text")
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
local entity = objref:get_luaentity()
if entity and ndef.display_entities[entity.name] then
local def = ndef.display_entities[entity.name]
local font = font_api.get_font(meta:get_string("font") ~= ""
and meta:get_string("font") or def.font_name)
-- Compute entity resolution accroding to given attributes
local texturew, textureh
textureh = font:get_height(def.lines or def.maxlines or 1)
if def.columns then
if font.fixedwidth then
texturew = def.columns * font.fixedwidth
if def.aspect_ratio then
minetest.log('warning', "[font_api] 'aspect_ratio' ignored because 'columns' is specified")
end end
else dofile(font_api.path.."/deprecation.lua")
minetest.log('warning', "[font_api] 'columns' ignored because '"..font.name.."' is not a fixed width font.")
end
end
if not texturew then
if not def.aspect_ratio then
minetest.log('warning', "[font_api] No 'aspect_ratio' specified, using default 1.")
end
texturew = textureh * def.size.x / def.size.y / (def.aspect_ratio or 1)
end
objref:set_properties({
textures={font:make_text_texture(text, texturew, textureh,
def.maxlines, def.halign, def.valign, def.color)},
visual_size = def.size
})
end
end
-- Compatibility
font_lib = font_api

@ -1,6 +1,5 @@
--[[ --[[
font_api mod for Minetest - Library to add font display capability font_api mod for Minetest - Library creating textures with fonts and text
to display_api mod.
(c) Pierre-Yves Rollo (c) Pierre-Yves Rollo
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -159,4 +158,3 @@ function font_api.register_font(font_name, font_def)
minetest.log("action", "New font registered in font_api: "..font_name..".") minetest.log("action", "New font registered in font_api: "..font_name..".")
end end

@ -33,9 +33,8 @@ local function display_poster(pos, node, player)
node.name, minetest.pos_to_string(pos)) node.name, minetest.pos_to_string(pos))
-- Title texture -- Title texture
local titletexture = font:make_text_texture( local titletexture = font:render(meta:get_string("display_text"),
meta:get_string("display_text"), font:get_height()*8.4, font:get_height()*8.4, font:get_height(), { lines = 1 })
font:get_height(), 1, "center")
fs = string.format([=[ fs = string.format([=[
size[7,9]bgcolor[#0000] size[7,9]bgcolor[#0000]