Removed display_api, signs_api, and font_api to make them subtrees

This commit is contained in:
Pierre-Yves Rollo 2019-12-31 17:06:15 +01:00
parent de915427ee
commit 135cae7219
42 changed files with 0 additions and 3930 deletions

View File

@ -1,92 +0,0 @@
# Display API
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
### update\_entities
**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.
`pos`: Position of the node
### register\_display\_entity
**display\_api.register\_display\_entity(entity_name)**
This is a helper to register entities used for display.
`entity_name`: Name of the entity to register.
## Provided callback implementations
### on_place
**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_construct
**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_destruct
**display\_api.on_destruct(pos)**
`on_destruct` node callback implementation. Display nodes should have this callback (removes display entities on node destruction).
### on_rotate
**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_activate
**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).
## Howto register a display node
* Register display entities with `register_display_entity`
* Register node with :
- `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).\
- 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
`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 `top`: 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.\
`depth` goes from front (-0.5) to rear (0.5), `top` goes from bottom (-0.5) to top (0.5) and `right` goes from left (-0.5) to right (0.5).\
`yaw`: Entity yaw in radians, regarding to main axis. Default is 0, aligned to node face.
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.
### Example
display_api.register_display_entity("mymod:entity1")
display_api.register_display_entity("mymod:entity2")
function my_display_update1(pos, objref)
objref:set_properties({ textures= {"mytexture1.png"},
visual_size = {x=1, y=1} })
end
function my_display_update2(pos, objref)
objref:set_properties({ textures= {"mytexture2.png"},
                        visual_size = {x=1, y=1} })
end
minetest.register_node("mymod:test_display_node", {
...
paramtype2 = "facedir",
...
groups = { display_api = 1, ... },
...
display_entities = {
["mymod:entity1"] = {
depth = 0.3,
on_display_update = my_display_update1 },
["mymod:entity1"] = {
depth = 0.2, top = 0.1,
on_display_update = my_display_update2 },
},
...
on_place = display_api.on_place,
on_construct = display_api.on_construct,
on_destruct = display_api.on_destruct,
on_rotate = display_api.on_rotate,
...
})

View File

@ -1,166 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -1,34 +0,0 @@
# Display API
This library's purpose is to ease creation of nodes with one or more displays on sides. For example, signs and clocks. Display can be dynamic and/or different for each node instance.
**Limitations**: This lib uses entities to draw display. This means display has to be vertical (and "upside up") on Minetest before version 5.0.
**Dependancies**:default
**License**: LGPLv2
**API**: See [API.md](https://github.com/pyrollo/display_modpack/blob/master/display_api/API.md) document please.
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.
## Change log
### 2019-03-14
- __dispay_api__: Display API now detects automatically whenr rotation restrictions have to be applied.
### 2019-03-09
- __display_api__: Display nodes can be rotated in every directions (if running Minetest 5 or above).
- __display_api__: New setting to restrict rotations to Minetest 0.4 abilities (restriction enabled by default).
### 2018-12-14
- __display_api__: New `yaw` attributes, entities can now have different angles with node.

View File

@ -1,5 +0,0 @@
Code by Pierre-Yves Rollo (pyrollo)
Contributors:
(gpcf): Compatibility with signs lib
(Thomas--S): Fix /clearobjects bug
(12Me21): on_place and on_rotate improvements

View File

@ -1,78 +0,0 @@
--[[
display_api mod for Minetest - Library to add dynamic display
capabilities to nodes
(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_group(deprecated_group, replacement_group)
for name, ndef in pairs(minetest.registered_nodes) do
if ndef.groups and ndef.groups[deprecated_group] then
minetest.log("warning", string.format(
'Node %s belongs to deprecated "%s" group which should be replaced with new "%s" group.',
name, deprecated_group, replacement_group))
end
end
end
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, "deprecated global does not exist.")
if _G[replacement_global_name] == nil then
minetest.log('warning', string.format(
'Replacement global "%s" does not exists.', replacement_global_name))
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(
'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(
'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(1) -- December 2018 - Deprecation of groups display_modpack_node and display_lib_node
-- Group to be removed from display API register_lbm
minetest.after(0, function()
deprecated_group("display_modpack_node", "display_api")
deprecated_group("display_lib_node", "display_api")
end)
-- deprecated(2) -- December 2018 - Deprecation of display_lib
deprecated_global_table('display_lib', 'display_api')

View File

@ -1,318 +0,0 @@
--[[
display_api mod for Minetest - Library to add dynamic display
capabilities to nodes
(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/>.
--]]
-- Prefered gap between node and entity
-- Entity positionment is up to mods but it is a good practice to use this
-- variable as spacing between entity and node
display_api.entity_spacing = 0.002
-- Maximum entity position relative to the node pos
local max_entity_pos = 1.5
local wallmounted_rotations = {
[0]={x=1, y=0, z=0}, [1]={x=3, y=0, z=0},
[2]={x=0, y=3, z=0}, [3]={x=0, y=1, z=0},
[4]={x=0, y=0, z=0}, [5]={x=0, y=2, z=0},
}
local facedir_rotations = {
[ 0]={x=0, y=0, z=0}, [ 1]={x=0, y=3, z=0},
[ 2]={x=0, y=2, z=0}, [ 3]={x=0, y=1, z=0},
[ 4]={x=3, y=0, z=0}, [ 5]={x=0, y=3, z=3},
[ 6]={x=1, y=0, z=2}, [ 7]={x=0, y=1, z=1},
[ 8]={x=1, y=0, z=0}, [ 9]={x=0, y=3, z=1},
[10]={x=3, y=0, z=2}, [11]={x=0, y=1, z=3},
[12]={x=0, y=0, z=1}, [13]={x=3, y=0, z=1},
[14]={x=2, y=0, z=1}, [15]={x=1, y=0, z=1},
[16]={x=0, y=0, z=3}, [17]={x=1, y=0, z=3},
[18]={x=2, y=0, z=3}, [19]={x=3, y=0, z=3},
[20]={x=0, y=0, z=2}, [21]={x=0, y=1, z=2},
[22]={x=0, y=2, z=2}, [23]={x=0, y=3, z=2},
}
-- Compute other useful values depending on wallmounted and facedir param
local wallmounted_values = {}
local facedir_values = {}
local function compute_values(r)
local function rx(v) return { x=v.x, y=v.z, z=-v.y} end
local function ry(v) return { x=-v.z, y=v.y, z=v.x} end
local function rz(v) return { x=v.y, y=-v.x, z=v.z} end
local d = { x = 0, y = 0, z = 1 }
local w = { x = 1, y = 0, z = 0 }
local h = { x = 0, y = 1, z = 0 }
-- Important to keep z rotation first (not same results)
for _ = 1, r.z do d, w, h = rz(d), rz(w), rz(h) end
for _ = 1, r.x do d, w, h = rx(d), rx(w), rx(h) end
for _ = 1, r.y do d, w, h = ry(d), ry(w), ry(h) end
return {
rotation=r, depth=d, width=w, height=h,
restricted=(r.x==0 and r.z==0) }
end
for i, r in pairs(facedir_rotations) do
facedir_values[i] = compute_values(r)
end
for i, r in pairs(wallmounted_rotations) do
wallmounted_values[i] = compute_values(r)
end
-- Detect rotation restriction
local rotation_restricted = nil
minetest.register_entity('display_api:dummy_entity', {
collisionbox = { 0, 0, 0, 0, 0, 0 },
visual = "upright_sprite",
textures = {} })
function display_api.is_rotation_restricted()
if rotation_restricted == nil then
local objref = minetest.add_entity(
{x=0, y=0, z=0}, 'display_api:dummy_entity')
if objref then
rotation_restricted = objref.set_rotation == nil
objref:remove()
end
end
return rotation_restricted
end
-- Clip position property to maximum entity position
local function clip_pos_prop(posprop)
if posprop then
return math.max(-max_entity_pos, math.min(max_entity_pos, posprop))
else
return 0
end
end
-- Get values needed for orientation computation of node
local function get_orientation_values(node)
local ndef = minetest.registered_nodes[node.name]
if ndef then
local paramtype2 = ndef.paramtype2
if paramtype2 == "wallmounted" or paramtype2 == "colorwallmounted" then
return wallmounted_values[node.param2 % 8]
elseif paramtype2 == "facedir" or paramtype2 == "colorfacedir" then
return facedir_values[node.param2 % 32]
else
-- No orientation or unknown orientation type
return facedir_values[0]
end
end
end
-- Gets the display entities attached with a node.
-- Add missing and remove duplicates
local function get_display_objrefs(pos, create)
local objrefs = {}
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
if ndef and ndef.display_entities then
for _, objref in
ipairs(minetest.get_objects_inside_radius(pos, max_entity_pos)) do
local entity = objref:get_luaentity()
if entity and ndef.display_entities[entity.name] and
entity.nodepos and vector.equals(pos, entity.nodepos) then
if objrefs[entity.name] then
objref:remove() -- Remove duplicates
else
objrefs[entity.name] = objref
end
end
end
if create then
-- Add missing
for name, _ in pairs(ndef.display_entities) do
if not objrefs[name] then
objrefs[name] = minetest.add_entity(pos, name,
minetest.serialize({ nodepos = pos }))
end
end
end
end
return objrefs
end
--- Force entity update : position and texture
function display_api.update_entities(pos)
local node = minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
local ov = get_orientation_values(node)
for _, objref in pairs(get_display_objrefs(pos, true)) do
local edef = ndef.display_entities[objref:get_luaentity().name]
local depth = clip_pos_prop(edef.depth)
local right = clip_pos_prop(edef.right)
local top = clip_pos_prop(edef.top)
objref:set_pos({
x = pos.x + ov.depth.x*depth + ov.width.x*right - ov.height.x*top,
y = pos.y + ov.depth.y*depth + ov.width.y*right - ov.height.y*top,
z = pos.z + ov.depth.z*depth + ov.width.z*right - ov.height.z*top,
})
if objref.set_rotation then
objref:set_rotation({
x = ov.rotation.x*math.pi/2,
y = ov.rotation.y*math.pi/2 + (edef.yaw or 0),
z = ov.rotation.z*math.pi/2,
})
else
if ov.rotation.x ~=0 or ov.rotation.y ~= 0 then
minetest.log("warning", string.format(
"[display_api] unable to rotate correctly entity for node at %s without set_rotation method.",
minetest.pos_to_string(pos)))
end
objref:set_yaw(ov.rotation.y*math.pi/2 + (edef.yaw or 0))
end
-- Call on_display_update callback of a node for one of its display entities
if edef.on_display_update then
edef.on_display_update(pos, objref)
end
end
end
--- On_activate callback for display_api entities. Calls on_display_update callbacks
--- of corresponding node for each entity.
function display_api.on_activate(entity, staticdata)
if entity then
if string.sub(staticdata, 1, string.len("return")) == "return" then
local data = minetest.deserialize(staticdata)
if data and type(data) == "table" then
entity.nodepos = data.nodepos
end
entity.object:set_armor_groups({immortal=1})
end
if entity.nodepos then
local node = minetest.get_node(entity.nodepos)
local ndef = minetest.registered_nodes[node.name]
if ndef and ndef.display_entities then
local edef = ndef.display_entities[entity.name]
if edef then
-- Call on_display_update callback of the entity to build texture
if edef.on_display_update then
edef.on_display_update(entity.nodepos, entity.object)
end
return
end
end
end
-- If we got here, this display entity is buggy and should be removed
entity.object:remove()
end
end
--- On_place callback for display_api items.
-- Does nothing more than preventing node from being placed on ceiling or ground
-- TODO:When MT<5 is not in use anymore, simplify this
function display_api.on_place(itemstack, placer, pointed_thing, override_param2)
local ndef = itemstack:get_definition()
local dir = {
x = pointed_thing.under.x - pointed_thing.above.x,
y = pointed_thing.under.y - pointed_thing.above.y,
z = pointed_thing.under.z - pointed_thing.above.z,
}
local rotation_restriction = display_api.is_rotation_restricted()
if rotation_restriction then
-- If item is not placed on a wall, use the player's view direction instead
if dir.x == 0 and dir.z == 0 then
dir = placer:get_look_dir()
end
dir.y = 0
end
local param2 = 0
if ndef then
if ndef.paramtype2 == "wallmounted" or
ndef.paramtype2 == "colorwallmounted" then
param2 = minetest.dir_to_wallmounted(dir)
elseif ndef.paramtype2 == "facedir" or
ndef.paramtype2 == "colorfacedir" then
param2 = minetest.dir_to_facedir(dir, not rotation_restriction)
end
end
return minetest.item_place(itemstack, placer, pointed_thing,
param2 + (override_param2 or 0))
end
--- On_construct callback for display_api items.
-- Creates entities and update them.
function display_api.on_construct(pos)
display_api.update_entities(pos)
end
--- On_destruct callback for display_api items.
-- Removes entities.
function display_api.on_destruct(pos)
for _, objref in pairs(get_display_objrefs(pos)) do
objref:remove()
end
end
-- On_rotate (screwdriver) callback for display_api items. Prevents invalid
-- rotations and reorients entities.
function display_api.on_rotate(pos, node, user, _, new_param2)
node.param2 = new_param2
local ov = get_orientation_values(node)
if ov.restricted or not display_api.is_rotation_restricted() then
minetest.swap_node(pos, node)
display_api.update_entities(pos)
return true
else
return false
end
end
--- Creates display entity with some fields and the on_activate callback
function display_api.register_display_entity(entity_name)
if not minetest.registered_entities[entity_name] then
minetest.register_entity(':'..entity_name, {
collisionbox = { 0, 0, 0, 0, 0, 0 },
visual = "upright_sprite",
textures = {},
on_activate = display_api.on_activate,
get_staticdata = function(self)
return minetest.serialize({ nodepos = self.nodepos })
end,
})
end
end
minetest.register_lbm({
label = "Update display_api entities",
name = "display_api:update_entities",
run_at_every_load = true,
nodenames = {"group:display_api",
"group:display_modpack_node", "group:display_lib_node"}, -- See deprecated(1)
action = function(pos, node) display_api.update_entities(pos) end,
})

View File

@ -1,31 +0,0 @@
--[[
display_api mod for Minetest - Library to add dynamic display
capabilities to nodes
(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/>.
--]]
-- Global variables
-------------------
display_api = {}
display_api.name = minetest.get_current_modname()
display_api.path = minetest.get_modpath(display_api.name)
-- Inclusions
-------------
dofile(display_api.path.."/display.lua")
dofile(display_api.path.."/deprecation.lua")

View File

@ -1,2 +0,0 @@
name=display_api
description=A library for adding dynamic textures on nodes

View File

@ -1,201 +0,0 @@
# Font API
This document describes Font API. Font API creates textures for font display on entities.
## Settings
### default_font
Name of the font to be used when no font is given. The font should be registered.
If no default\_font given or if default\_font given but not registered, the first registered font will be used as default.
## Use font_api with display_api (to display text on nodes)
### Base setup
Font_api offers a direct integration with display_api to display text on nodes.
First of all, create a display node with an entity.
To do this, refer to API.md in display_api mod, in particular "Howto register a display node".
The only requirement then is to connect the `on_display_update` callback of the display entity to `font_api.on_display_update`:
```
minetest.register_node("mymod:test_text_node", {
...
paramtype2 = "facedir",
...
groups = { display_api = 1, ... },
...
display_entities = {
["mymod:text"] = {
depth = -0.5 - display_api.entity_spacing,
on_display_update = font_api.on_display_update },
}
...
on_place = display_api.on_place,
on_construct = display_api.on_construct,
on_destruct = display_api.on_destruct,
on_rotate = display_api.on_rotate,
...
})
```
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.
### Style your text
Font style and size can be chosen by adding some more entries to the display_entities definition table.
#### Font size
Font size can be defined in various ways (maybe more in the future).
Start with a number of lines, and font_api will make it fit to the entity size.
* `maxlines` or `lines`: Number of maximum lines of text to be displayed. The font height will be adjusted accordingly.
Then specify the char width. Two methods available:
* `aspect_ratio`: Defines the aspect ratio of chars. Works with all fonts. Should not be used if `columns` is specified.
* `columns`: Only if using a fixed width font, specifies the number of columns to display.
#### Font style
* `font_name`: name of the font to use. Should correspond to a registered font (from a font mod). If not specified or font not found, default font is used.
* `color`: color to be used (default black).
* `halign`: Horizontal alignment: "left", "center" or "right" (default "center").
* `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
### font_api.get_default_font_name()
Returns de default font name.
### font_api.register_font(font_name, font_def)
Register a new font.
* `font_name`: Name of the font to register. If registering different sizes of the same font, add size in the font name (e.g. times_10, times_12...).
* `font_def`: Font definition table (see **Font definition table** below).
### font_api.on_display_update(pos, objref)
Standard on_display_update entity callback.
* `pos`: Node position
* `objref`: Object reference of entity
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 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) .
* `widths` (required): Array of character widths in pixels, indexed by UTF codepoints.
* `margintop` (optional): Margin (in texture pixels) added on top of each char texture.
* `marginbottom` (optional): Margin (in texture pixels) added at bottom of each char texture.
* `linespacing` (optional): Spacing (in texture pixels) between each lines.
`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.
All textures corresponding to the indexes in widths array should be present in textures directory with a name matching the pattern :
> font\_**{font_name}**_**{utf_code}**.png
**{font\_name}**: Name of the font as given in the first argument
**{utf\_code}**: UTF code of the char in 4 hexadecimal digits
Example : font_courrier_0041.png is for the "A" char in the "courrier" font.
To ease that declaration (specially to build the **widths** array), a shell is provided to build a {font\_name}.lua file from the texture files (see provided tools).
## Provided tools
Still in early stage of development, these tools are helpers to create font mods.
### make_font_texture.sh
This scripts takes a .ttf file as input and create one .png file per char, that can be used as font texture. Launch it from your future font mod directory.
__Advice__
This script works much better with pixels font, providing the correct height. There is no antialiasing at all, vector fonts and bad heights gives very ugly results.
__Syntax__
**make\_font\_texture.sh {fontfile} {fontname} {fontsize}**
**{fontfile}**: A TTF font file to use to create textures.
**{fontname}**: The font name to be used in font_api (should be simple, with no spaces).
**{fontsize}**: Font height to be rendered.
### make_font_lua.sh
This script analyses textures in textures directory and creates a font\_{font\_name}.lua files with a call to register_font with images information. Launch it from your future font mod directory.
Once the font\_{font\_name}.lua created, it can be included by a init.lua file or directly renamed to init.lua if you are creating a simple font mod.
__Syntax__
**make\_font_lua.sh {fontname}**
**{fontname}**: The font name to be used in font_api (same as given to make\_font\_texture.sh)
### An exemple generating a font mod
mkdir font_myfont
cd font_myfont
/<path_to_font_api>/tools/make_font_texture.sh myfont.ttf myfont 12
/<path_to_font_api>/tools/make_font_lua.sh myfont
mv font_myfont.lua init.lua
## Font class
A font usable with font API. This class is supposed to be for internal use but who knows.
### font\_api.Font:new(def)
Create a new font object.
* `def` is a table containing font definition. See **Font definition table** above.
### font:get_char_width(codepoint)
Returns the width of char `codepoint` in texture pixels.
* `codepoint`: Unicode codepoint of char.
### font:get_height(nb_of_lines)
Returns line(s) height. Takes care of top and bottom margins and line spacing.
* `nb_of_lines`: Number of lines in the text.
### font:get_width(line)
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.
### font:renter(text, texturew, textureh, style)
Builds texture for a multiline colored text.
* `text`: Text to be rendered.
* `texturew`: Width of the texture (extra text will be truncated).
* `textureh`: Height of the texture (extra text will be truncated).
* `style`: A table with style indications:
- `lines` or `maxlines`: Maximum number of lines (default none).
- `halign`: Horizontal text align: "left"/"center"/"right" (default "center")
- `valign`: Vertical text align: "top"/"middle"/"bottom" (default "middle")
- `color`: Color of the text (default black)

View File

@ -1,166 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -1,31 +0,0 @@
# Font API
A library for rendernig text on textures (to be used with display_api for sign creation).
**Dependancies**: default
**License**: LGPL
(Default font taken from VanessaE's homedecor/signs_lib, originally under WTFPL)
**API**: See [API.md](https://github.com/pyrollo/display_modpack/blob/master/font_api/API.md) document please.
For more information, see the [forum topic](https://forum.minetest.net/viewtopic.php?t=13563) at the Minetest forums.
## Extra fonts
You can add fonts by installing fonts mod. Be aware that each font comes with numerous textures. This can result in slowing media downloading and/or client display.
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).
* [OldWizard](https://github.com/pyrollo/font_oldwizard): An old style gothic 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.

View File

@ -1,3 +0,0 @@
Code by Pierre-Yves Rollo (pyrollo)
Contributors:
Andrzej Pieńkowski (apienk): Unicode support and tool for creating texturess

View File

@ -1 +0,0 @@
display_api?

View File

@ -1,59 +0,0 @@
--[[
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, "deprecated global does not exist.")
if _G[replacement_global_name] == nil then
minetest.log('warning', string.format(
'Replacement global "%s" does not exists.', replacement_global_name))
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(
'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(
'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')

View File

@ -1,76 +0,0 @@
--[[
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

View File

@ -1,463 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="120mm"
height="110mm"
viewBox="0 0 120 110"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="font.svg">
<defs
id="defs2">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="marker7159"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path7157"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="marker7071"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path7069"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.4,0,0,0.4,4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path886"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path883"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.4,0,0,0.4,4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path880"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path877"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-3"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-6"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-7"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-5"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-2"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-7"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-9-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-1-3"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-2-6"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-7-0"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-1"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-2"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-3"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-94"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-7"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-8"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-4"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-151.37352"
inkscape:cy="445.54867"
inkscape:document-units="mm"
inkscape:current-layer="g8201"
showgrid="true"
inkscape:lockguides="true"
inkscape:window-width="1877"
inkscape:window-height="1052"
inkscape:window-x="1409"
inkscape:window-y="0"
inkscape:window-maximized="1"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid826"
spacingx="1"
units="mm"
spacingy="1" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-187)">
<g
id="g7357"
transform="translate(65,-15)"
style="opacity:0.5">
<rect
y="202"
x="170"
height="70"
width="70"
id="rect828-9"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:0.25098039;fill-rule:nonzero;stroke:#999999;stroke-width:0.30550504;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
d="m 220,252 h 10 v 10 h -10 z m -50,0 h 10 v 10 h -10 z m 5,-10 h 50 v 10 h -50 z m 4.99998,-10 h 10 v 10 h -10 z M 210,232 h 10 v 10 h -10 z m -5,-10 h 10 v 10 h -10 z m -20,0 h 10 v 10 h -10 z m 5,-10.00002 h 20 v 10 H 190 Z M 195,202 h 10 v 10 h -10 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32659864;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect854-2"
inkscape:connector-curvature="0" />
</g>
<g
id="g8201"
transform="translate(0,190)">
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26499998, 1.05999994;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect1594"
width="120"
height="109.99999"
x="0"
y="-3" />
<g
transform="translate(-75,-120)"
id="g7361">
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:0.25098039;fill-rule:nonzero;stroke:#0000ff;stroke-width:0.30550504;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect828"
width="70"
height="70"
x="100"
y="137" />
<path
inkscape:connector-curvature="0"
id="rect854"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32659864;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 150,187 h 10 v 10 h -10 z m -50,0 h 10 v 10 h -10 z m 5,-10 h 50 v 10 h -50 z m 4.99999,-10 h 10 v 10 h -10 z M 140,167 h 10 v 10 h -10 z m -5,-10 h 10 v 10 h -10 z m -20,0 h 10 v 10 h -10 z m 5,-10.00002 h 20 v 10 H 120 Z M 125,137 h 10 v 10 h -10 z" />
</g>
<path
inkscape:connector-curvature="0"
id="path875"
d="M 19.999999,17 V 87"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)" />
<text
inkscape:transform-center-y="5.2916667"
inkscape:transform-center-x="1.889881"
transform="rotate(-90)"
id="text1193"
y="17.496948"
x="-52.43602"
style="font-style:normal;font-weight:normal;font-size:3.96875px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="17.496948"
x="-52.43602"
id="tspan1191"
sodipodi:role="line">Texture Height</tspan></text>
<path
inkscape:connector-curvature="0"
id="path875-3"
d="M 95,97 H 25"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart-3);marker-end:url(#Arrow1Lend-7)" />
<text
inkscape:transform-center-y="-1.8898824"
inkscape:transform-center-x="5.2916602"
id="text1193-5"
y="101.69528"
x="60.176346"
style="font-style:normal;font-weight:normal;font-size:3.96875px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="101.69528"
x="60.176346"
id="tspan1191-6"
sodipodi:role="line">Texture Width</tspan></text>
<rect
y="7"
x="25"
height="85"
width="70"
id="rect828-2"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ff00ff;stroke-width:0.33665016;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path875-0"
d="M 20,7 V 17"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker7071);marker-end:url(#marker7159)" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path875-0-6"
d="m 20,87 v 5"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend)" />
<text
inkscape:transform-center-y="-1.8898824"
inkscape:transform-center-x="5.2916678"
id="text1193-2"
y="10.614426"
x="17.348068"
style="font-style:normal;font-weight:normal;font-size:3.96875px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="text-align:end;text-anchor:end;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="10.614426"
x="17.348068"
id="tspan1191-61"
sodipodi:role="line">Margin</tspan><tspan
id="tspan8103"
style="text-align:end;text-anchor:end;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="15.575363"
x="17.348068"
sodipodi:role="line">Top</tspan></text>
<text
inkscape:transform-center-y="-1.8898824"
inkscape:transform-center-x="5.2916678"
id="text1193-2-8"
y="88.4991"
x="17.240334"
style="font-style:normal;font-weight:normal;font-size:3.96875px;line-height:125%;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="text-align:end;text-anchor:end;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="88.4991"
x="18.503822"
id="tspan1191-61-7"
sodipodi:role="line">Margin </tspan><tspan
id="tspan8105"
style="text-align:end;text-anchor:end;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="93.460037"
x="17.240334"
sodipodi:role="line">Bottom</tspan></text>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path875-1"
d="M 100,7 V 92"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart-1);marker-end:url(#Arrow1Lend-9)" />
<text
inkscape:transform-center-y="5.2916667"
inkscape:transform-center-x="1.889881"
transform="rotate(-90)"
id="text1193-0"
y="104.35954"
x="-49.646301"
style="font-style:normal;font-weight:normal;font-size:3.96875px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="104.35954"
x="-49.646301"
id="tspan1191-3"
sodipodi:role="line">Line Height</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,544 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="120mm"
height="225mm"
viewBox="0 0 120 225"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="lines.svg">
<defs
id="defs2">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="marker7159"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path7157"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="marker7071"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path7069"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.4,0,0,0.4,4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path886"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path883"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.4,0,0,0.4,4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path880"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path877"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-3"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-6"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-7"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-5"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-2"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-7"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-9-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-1-3"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-2-6"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-7-0"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-1"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-2"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-3"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-94"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-7"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-8"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-4"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-1-2"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-2-0"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-9-6"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-3-1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart-1-5"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path877-2-4"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend-9-7"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path880-3-6"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="577.84911"
inkscape:cy="466.83879"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:lockguides="true"
inkscape:window-width="1877"
inkscape:window-height="1052"
inkscape:window-x="1409"
inkscape:window-y="0"
inkscape:window-maximized="1"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid826"
spacingx="1"
units="mm"
spacingy="1" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-72)">
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26499998, 1.05999993999999997;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect890"
width="120"
height="224.99998"
x="0"
y="72" />
<g
id="g10629"
transform="translate(-5,-54.999998)">
<g
id="g8263">
<g
transform="translate(-40,39.999996)"
id="g8268">
<rect
y="102"
x="60"
height="70"
width="70"
id="rect828-9"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:0.25098039;fill-rule:nonzero;stroke:#999999;stroke-width:0.30550504;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
d="m 110,152 h 10 v 10 h -10 z m -50,0 h 10 v 10 H 60 Z m 5,-10 h 50 v 10 H 65 Z m 4.99998,-10 h 10 v 10 h -10 z M 100,132 h 10 v 10 h -10 z m -5,-10 h 10 v 10 H 95 Z m -20,0 h 10 v 10 H 75 Z m 5,-10.00002 h 20 v 10 H 80 Z M 85,102 h 10 v 10 H 85 Z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32659864;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect854-2"
inkscape:connector-curvature="0" />
<rect
y="92"
x="60"
height="85.000008"
width="70"
id="rect828-2-6"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:0.33665016;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
<g
transform="translate(-40,170)"
id="g8268-1">
<rect
y="102"
x="60"
height="70"
width="70"
id="rect828-9-0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:0.25098039;fill-rule:nonzero;stroke:#999999;stroke-width:0.30550504;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
d="m 110,152 h 10 v 10 h -10 z m -50,0 h 10 v 10 H 60 Z m 5,-10 h 50 v 10 H 65 Z m 4.99998,-10 h 10 v 10 h -10 z M 100,132 h 10 v 10 h -10 z m -5,-10 h 10 v 10 H 95 Z m -20,0 h 10 v 10 H 75 Z m 5,-10.00002 h 20 v 10 H 80 Z M 85,102 h 10 v 10 H 85 Z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32659864;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect854-2-6"
inkscape:connector-curvature="0" />
<rect
y="92"
x="60"
height="85.000008"
width="70"
id="rect828-2-6-3"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:0.33665016;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
</g>
<g
transform="translate(-75,70)"
id="g7361">
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:0.25098039;fill-rule:nonzero;stroke:#0000ff;stroke-width:0.30550504;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect828"
width="70"
height="70"
x="100"
y="137" />
<path
inkscape:connector-curvature="0"
id="rect854"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.32659864;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 150,187 h 10 v 10 h -10 z m -50,0 h 10 v 10 h -10 z m 5,-10 h 50 v 10 h -50 z m 4.99999,-10 h 10 v 10 h -10 z M 140,167 h 10 v 10 h -10 z m -5,-10 h 10 v 10 h -10 z m -20,0 h 10 v 10 h -10 z m 5,-10.00002 h 20 v 10 H 120 Z M 125,137 h 10 v 10 h -10 z" />
</g>
<rect
y="197"
x="25"
height="85"
width="70"
id="rect828-2"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ff00ff;stroke-width:0.33665016;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path875-1"
d="m 100,197 v 85"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart-1);marker-end:url(#Arrow1Lend-9)" />
<text
inkscape:transform-center-y="5.2916667"
inkscape:transform-center-x="1.889881"
transform="rotate(-90)"
id="text1193-0"
y="104.35954"
x="-239.6463"
style="font-style:normal;font-weight:normal;font-size:3.96875px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="104.35954"
x="-239.6463"
id="tspan1191-3"
sodipodi:role="line">Line Height</tspan></text>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path875-1-5"
d="m 15,197 v 20"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart-1-2);marker-end:url(#Arrow1Lend-9-6)" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path875-1-56"
d="M 110,132 V 347"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart-1-5);marker-end:url(#Arrow1Lend-9-7)" />
<text
inkscape:transform-center-y="5.2916667"
inkscape:transform-center-x="1.889881"
transform="rotate(-90)"
id="text1193-0-9"
y="115.82679"
x="-239.6463"
style="font-style:normal;font-weight:normal;font-size:3.96875px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="115.82679"
x="-239.6463"
id="tspan1191-3-3"
sodipodi:role="line">Text Height</tspan></text>
<text
inkscape:transform-center-y="5.2916667"
inkscape:transform-center-x="1.889881"
transform="rotate(-90)"
id="text1193-0-7"
y="11.713711"
x="-206.76294"
style="font-style:normal;font-weight:normal;font-size:3.96875px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.26458332px"
y="11.713711"
x="-206.76294"
id="tspan1191-3-4"
sodipodi:role="line">Line Spacing</tspan></text>
<path
inkscape:connector-curvature="0"
id="path10512"
d="M 25,197 H 15 v 0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26499999, 1.05999996;stroke-dashoffset:0;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path10512-5"
d="M 25,217 H 15 v 0"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26499999, 1.05999996;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path10512-2"
d="M 110,132 H 90"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26499999, 1.05999996;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path10512-2-5"
d="M 110,347 H 90"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26499999, 1.05999997;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path10512-2-5-4"
d="M 100,282 H 95"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26499999, 1.05999998;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path10512-2-5-4-7"
d="M 100,197 H 95"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.26499999, 1.05999999;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,175 +0,0 @@
--[[
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/>.
--]]
-- This is the unicode char fallback map. If a char is not present in
-- font, this maps indicates which char to try to use instead next.
return {
-- Lowercase chars
['a'] = 'A', ['b'] = 'B', ['c'] = 'C', ['d'] = 'D',
['e'] = 'E', ['f'] = 'F', ['g'] = 'G', ['h'] = 'H',
['i'] = 'I', ['j'] = 'J', ['k'] = 'K', ['l'] = 'L',
['m'] = 'M', ['n'] = 'N', ['o'] = 'O', ['p'] = 'P',
['q'] = 'Q', ['r'] = 'R', ['s'] = 'S', ['t'] = 'T',
['u'] = 'U', ['v'] = 'V', ['w'] = 'W', ['x'] = 'X',
['y'] = 'Y', ['z'] = 'Z',
-- Special
['¢'] = 'c', ['£'] = 'L', ['¥'] = 'Y', [''] = 'E',
['©'] = '(C)', ['®'] = '(R)', [''] = 'TM',
['ª'] = 'a', ['º'] = 'o',
['«'] = '"', ['»'] = '"', ['´'] = '\'',
['¹'] = '1', ['²'] = '2', ['³'] = '3',
['µ'] = 'u', ['¤'] = 'o',
['¼'] = '1/4', ['½'] = '1/2', ['¾'] = '3/4',
[''] = '1/8', [''] = '3/8', [''] = '5/8', [''] = '7/8',
['¿'] = '?',
-- Upper case accents
['À'] = 'A', ['Á'] = 'A', ['Â'] = 'A', ['Ã'] = 'A',
['Ä'] = 'A', ['Å'] = 'A',
['Æ'] = 'AE', ['Ç'] = 'C',
['È'] = 'E', ['É'] = 'E', ['Ê'] = 'E', ['Ë'] = 'E',
['Ì'] = 'I', ['Í'] = 'I', ['Î'] = 'I', ['Ï'] = 'I',
['Ð'] = 'D', ['Ñ'] = 'N',
['Ò'] = 'O', ['Ó'] = 'O', ['Ô'] = 'O', ['Õ'] = 'O',
['Ö'] = 'O', ['Ø'] = 'O',
['Ú'] = 'U', ['Ù'] = 'U', ['Û'] = 'U', ['Ü'] = 'U',
['×'] = 'x', ['Ý'] = 'Y',
-- Lower case accents
['à'] = 'a', ['à'] = 'a', ['á'] = 'a', ['â'] = 'a',
['ã'] = 'a', ['ä'] = 'a', ['å'] = 'a',
['æ'] = 'ae', ['ç'] = 'c',
['è'] = 'e', ['é'] = 'e', ['ê'] = 'e', ['ë'] = 'e',
['ì'] = 'i', ['í'] = 'i', ['î'] = 'i', ['ï'] = 'i',
['ð'] = 'd', ['ñ'] = 'n',
['ò'] = 'o', ['ó'] = 'o', ['ô'] = 'o', ['õ'] = 'o',
['ö'] = 'o', ['ø'] = 'o',
['ù'] = 'u', ['ú'] = 'u', ['û'] = 'u', ['ü'] = 'u',
['ý'] = 'y', ['ÿ'] = 'y',
-- Extended latin A
['Ā'] = 'A', ['ā'] = 'a', ['Ă'] = 'A', ['ă'] = 'a',
['Ą'] = 'A', ['ą'] = 'a', ['Ć'] = 'C', ['ć'] = 'c',
['Ĉ'] = 'C', ['ĉ'] = 'c', ['Ċ'] = 'C', ['ċ'] = 'c',
['Č'] = 'C', ['č'] = 'c', ['Ď'] = 'D', ['ď'] = 'd',
['Đ'] = 'D', ['đ'] = 'd', ['Ē'] = 'E', ['ē'] = 'e',
['Ĕ'] = 'E', ['ĕ'] = 'e', ['Ė'] = 'E', ['ė'] = 'e',
['Ę'] = 'E', ['ę'] = 'e', ['Ě'] = 'E', ['ě'] = 'e',
['Ĝ'] = 'G', ['Ğ'] = 'G', ['ğ'] = 'g', ['ĝ'] = 'g',
['Ġ'] = 'G', ['ġ'] = 'g', ['Ģ'] = 'G', ['ģ'] = 'g',
['Ĥ'] = 'H', ['ĥ'] = 'h', ['Ħ'] = 'H', ['ħ'] = 'h',
['Ĩ'] = 'I', ['ĩ'] = 'i', ['Ī'] = 'I', ['ī'] = 'i',
['Ĭ'] = 'I', ['ĭ'] = 'i', ['Į'] = 'I', ['į'] = 'i',
['ı'] = 'i', ['İ'] = 'I', ['IJ'] = 'IJ', ['ij'] = 'ij',
['Ĵ'] = 'J', ['ĵ'] = 'j', ['ķ'] = 'k', ['Ķ'] = 'K',
['ĸ'] = 'k',
['Ĺ'] = 'L', ['ĺ'] = 'l', ['Ļ'] = 'L', ['ļ'] = 'l',
['Ľ'] = 'L', ['ľ'] = 'l', ['Ŀ'] = 'L', ['ŀ'] = 'l',
['Ł'] = 'L', ['ł'] = 'l', ['Ń'] = 'N', ['ń'] = 'n',
['Ņ'] = 'N', ['ņ'] = 'n', ['Ň'] = 'N', ['ň'] = 'n',
['ʼn'] = 'n', ['Ŋ'] = 'n', ['ŋ'] = 'n',
['Ō'] = 'O', ['ō'] = 'o', ['Ŏ'] = 'O', ['ŏ'] = 'o',
['ő'] = 'o', ['Ő'] = 'O', ['œ'] = 'oe', ['Œ'] = 'OE',
['Ŕ'] = 'R', ['ŕ'] = 'r', ['Ŗ'] = 'R', ['ŗ'] = 'r',
['Ř'] = 'R', ['ř'] = 'r', ['Ś'] = 'S', ['ś'] = 's',
['Ŝ'] = 'S', ['ŝ'] = 's', ['Ş'] = 'S', ['ş'] = 's',
['Š'] = 'S', ['š'] = 's', ['Ţ'] = 'T', ['ţ'] = 't',
['ť'] = 't', ['Ŧ'] = 'T', ['Ť'] = 'T', ['ŧ'] = 't',
['Ũ'] = 'U', ['ũ'] = 'u', ['Ū'] = 'U', ['ū'] = 'u',
['Ŭ'] = 'U', ['ŭ'] = 'u', ['Ů'] = 'U', ['ů'] = 'u',
['Ű'] = 'U', ['ű'] = 'u', ['Ų'] = 'U', ['ų'] = 'u',
['Ŵ'] = 'W', ['ŵ'] = 'w', ['Ŷ'] = 'Y', ['ŷ'] = 'y',
['Ÿ'] = 'Y',
['Ź'] = 'Z', ['ź'] = 'z', ['Ż'] = 'Z', ['ż'] = 'z',
['Ž'] = 'Z', ['ž'] = 'z', ['ſ'] = 's',
-- Extended latin B
['ƀ'] = 'b', ['Ɓ'] = 'B', ['Ƃ'] = 'B', ['ƃ'] = 'b',
['Ɔ'] = 'O',
['Ƈ'] = 'C', ['ƈ'] = 'c', ['Ɖ'] = 'D', ['Ɗ'] = 'D',
['Ƌ'] = 'D', ['ƌ'] = 'd', ['Ǝ'] = 'E', ['Ə'] = 'e',
['Ɛ'] = 'E',
['Ƒ'] = 'F', ['ƒ'] = 'f', ['Ɠ'] = 'G',
['ƕ'] = 'hv', ['Ɨ'] = 'I', ['Ƙ'] = 'K', ['ƙ'] = 'k',
['ƚ'] = 'l', ['Ɯ'] = 'M', ['Ɲ'] = 'N', ['ƞ'] = 'n',
['Ɵ'] = 'O',
['Ơ'] = 'O', ['ơ'] = 'o', ['Ƣ'] = 'OI', ['ƣ'] = 'oi',
['Ƥ'] = 'P', ['ƥ'] = 'p', ['Ʀ'] = 'YR',
['Ƨ'] = 'S', ['ƨ'] = 's', ['ƫ'] = 't',
['Ƭ'] = 'T', ['ƭ'] = 't', ['Ʈ'] = 'T',
['Ư'] = 'U', ['ư'] = 'u', ['Ʋ'] = 'V',
['Ƴ'] = 'Y', ['ƴ'] = 'y', ['Ƶ'] = 'Z', ['ƶ'] = 'z',
['ƻ'] = '2', ['Ƽ'] = '5', ['ƽ'] = '5',
['DŽ'] = 'DZ', ['Dž'] = 'Dz', ['dž'] = 'dz',
['LJ'] = 'LJ', ['Lj'] = 'Lj', ['lj'] = 'lj',
['NJ'] = 'NJ', ['Nj'] = 'Nj', ['nj'] = 'nj',
['Ǎ'] = 'A', ['ǎ'] = 'a', ['Ǐ'] = 'I', ['ǐ'] = 'i',
['Ǒ'] = 'O', ['ǒ'] = 'o', ['Ǔ'] = 'U', ['ǔ'] = 'u',
['Ǖ'] = 'U', ['ǖ'] = 'u', ['Ǘ'] = 'U', ['ǘ'] = 'u',
['Ǚ'] = 'U', ['ǚ'] = 'u', ['Ǜ'] = 'U', ['ǜ'] = 'u',
['ǝ'] = 'e',
['Ǟ'] = 'A', ['ǟ'] = 'a', ['Ǡ'] = 'A', ['ǡ'] = 'a',
['Ǣ'] = 'Æ', ['ǣ'] = 'æ', ['Ǥ'] = 'G', ['ǥ'] = 'g',
['Ǧ'] = 'G', ['ǧ'] = 'g', ['Ǩ'] = 'K', ['ǩ'] = 'k',
['Ǫ'] = 'Q', ['ǫ'] = 'q', ['Ǭ'] = 'Q', ['ǭ'] = 'q',
['ǰ'] = 'J',
['DZ'] = 'DZ', ['Dz'] = 'Dz', ['dz'] = 'dz',
['Ǵ'] = 'G', ['ǵ'] = 'g', ['Ƕ'] = 'H',
['Ǹ'] = 'N', ['ǹ'] = 'n', ['Ǻ'] = 'A', ['ǻ'] = 'a',
['Ǽ'] = 'Æ', ['ǽ'] = 'æ', ['Ǿ'] = 'Ø', ['ǿ'] = 'ø',
['Ȁ'] = 'A', ['ȁ'] = 'a', ['Ȃ'] = 'A', ['ȃ'] = 'a',
['Ȅ'] = 'E', ['ȅ'] = 'e', ['Ȇ'] = 'E', ['ȇ'] = 'e',
['Ȉ'] = 'I', ['ȉ'] = 'i', ['Ȋ'] = 'I', ['ȋ'] = 'i',
['Ȍ'] = 'O', ['ȍ'] = 'o', ['Ȏ'] = 'O', ['ȏ'] = 'o',
['Ȑ'] = 'R', ['ȑ'] = 'r', ['Ȓ'] = 'R', ['ȓ'] = 'r',
['Ȕ'] = 'U', ['ȕ'] = 'u', ['Ȗ'] = 'U', ['ȗ'] = 'u',
['Ș'] = 'S', ['ș'] = 's', ['Ț'] = 'T', ['ț'] = 't',
['Ȟ'] = 'H', ['ȟ'] = 'h', ['Ƞ'] = 'N',
['ȡ'] = 'd',
['Ȣ'] = 'OU', ['ȣ'] = 'ou', ['Ȥ'] = 'Z', ['ȥ'] = 'z',
['Ȧ'] = 'A', ['ȧ'] = 'a', ['Ȩ'] = 'E', ['ȩ'] = 'e',
['Ȫ'] = 'O', ['ȫ'] = 'o', ['Ȭ'] = 'O', ['ȭ'] = 'o',
['Ȯ'] = 'O', ['ȯ'] = 'o', ['Ȱ'] = 'O', ['ȱ'] = 'o',
['Ȳ'] = 'Y', ['ȳ'] = 'y', ['ȴ'] = 'l',
['ȵ'] = 'n', ['ȶ'] = 't', ['ȷ'] = 'j',
['ȸ'] = 'db', ['ȹ'] = 'qp', ['Ⱥ'] = 'A',
['Ȼ'] = 'C', ['ȼ'] = 'c', ['Ƚ'] = 'L',
['Ⱦ'] = 'T', ['ȿ'] = 's', ['ɀ'] = 'z',
['Ƀ'] = 'B', ['Ʉ'] = 'U', ['Ʌ'] = 'V',
['Ɇ'] = 'E', ['ɇ'] = 'e', ['Ɉ'] = 'J', ['ɉ'] = 'j',
['Ɋ'] = 'Q', ['ɋ'] = 'q', ['Ɍ'] = 'R', ['ɍ'] = 'r',
['Ɏ'] = 'Y', ['ɏ'] = 'y', ['ɐ'] = 'a',
['ɓ'] = 'b', ['ɔ'] = 'o',
['ɕ'] = 'c', ['ɖ'] = 'd', ['ɗ'] = 'd',
['ɘ'] = 'e', ['ə'] = 'e', ['ɚ'] = 'e',
['ɛ'] = 'e', ['ɜ'] = 'e', ['ɝ'] = 'e', ['ɞ'] = 'e',
['ɟ'] = 'j',
['ɠ'] = 'g', ['ɡ'] = 'g', ['ɢ'] = 'G',
['ɥ'] = 'h', ['ɦ'] = 'h', ['ɧ'] = 'h',
['ɨ'] = 'i', ['ɪ'] = 'I',
['ɫ'] = 'l', ['ɬ'] = 'l', ['ɭ'] = 'l',
['ɮ'] = 'lz',
['ɯ'] = 'm', ['ɰ'] = 'm', ['ɱ'] = 'm',
['ɲ'] = 'n', ['ɳ'] = 'n', ['ɴ'] = 'N',
['ɵ'] = 'o', ['ɶ'] = 'Œ',
['ɹ'] = 'r', ['ɺ'] = 'r', ['ɻ'] = 'r',
['ɼ'] = 'r', ['ɽ'] = 'r', ['ɾ'] = 'r', ['ɿ'] = 'r',
}

View File

@ -1,274 +0,0 @@
--[[
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/>.
--]]
-- Fallback table
local fallbacks = dofile(font_api.path.."/fallbacks.lua")
-- Local functions
------------------
-- Returns number of UTF8 bytes of the first char of the string
local function get_char_bytes(str)
local msb = str:byte(1)
if msb ~= nil then
if msb < 0x80 then return 1 end
if msb >= 0xF0 then return 4 end
if msb >= 0xE0 then return 3 end
if msb >= 0xC2 then return 2 end
end
end
-- Returns the unicode codepoint of the first char of the string
local function char_to_codepoint(str)
local bytes = get_char_bytes(str)
if bytes == 1 then
return str:byte(1)
elseif bytes == 2 and str:byte(2) ~= nil then
return (str:byte(1) - 0xC2) * 0x40
+ str:byte(2)
elseif bytes == 3 and str:byte(2) ~= nil and str:byte(3) ~= nil then
return (str:byte(1) - 0xE0) * 0x1000
+ str:byte(2) % 0x40 * 0x40
+ str:byte(3) % 0x40
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
+ str:byte(2) % 0x40 * 0x1000
+ str:byte(3) % 0x40 * 0x40
+ str:byte(4) % 0x40
end
end
--------------------------------------------------------------------------------
--- Font class
local Font = {}
font_api.Font = Font
function Font:new(def)
if type(def) ~= "table" then
minetest.log("error",
"[font_api] Font definition must be a table.")
return nil
end
if def.height == nil or def.height <= 0 then
minetest.log("error",
"[font_api] Font definition must have a positive height.")
return nil
end
if type(def.widths) ~= "table" then
minetest.log("error",
"[font_api] Font definition must have a widths array.")
return nil
end
if def.widths[0] == nil then
minetest.log("error",
"[font_api] Font must have a char with codepoint 0 (=unknown char).")
return nil
end
local font = table.copy(def)
setmetatable(font, self)
self.__index = self
-- Check if fixedwidth
for codepoint, width in pairs(font.widths) do
font.fixedwidth = font.fixedwidth or width
if width ~= font.fixedwidth then
font.fixedwidth = nil
break
end
end
return font
end
--- Gets the next char of a text
-- @return Codepoint of first char,
-- @return Remaining string without this first char
function Font:get_next_char(text)
local bytes = get_char_bytes(text)
if bytes == nil then
minetest.log("warning",
"[font_api] Encountered a non UTF char, not displaying text.")
return nil, ''
end
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
if self.widths[codepoint] == nil then
local char = text:sub(1, bytes)
if fallbacks[char] then
return self:get_next_char(fallbacks[char]..text:sub(bytes+1))
else
return 0, text:sub(bytes+1) -- Ultimate fallback
end
else
return codepoint, text:sub(bytes+1)
end
end
--- Returns the width of a given char
-- @param char : codepoint of the char
-- @return Char width
function Font:get_char_width(codepoint)
if self.fixedwidth then
return self.fixedwidth
elseif self.widths[codepoint] then
return self.widths[codepoint]
else
return self.widths[0]
end
end
--- Text height for multiline text including margins and line spacing
-- @param nb_of_lines : number of text lines (default 1)
-- @return Text height
function Font:get_height(nb_of_lines)
if nb_of_lines == nil then nb_of_lines = 1 end
if nb_of_lines > 0 then
return
(
(self.height or 0) +
(self.margintop or 0) +
(self.marginbottom or 0)
) * nb_of_lines +
(self.linespacing or 0) * (nb_of_lines -1)
else
return nb_of_lines == 0 and 0 or nil
end
end
--- Computes text width for a given text (ignores new lines)
-- @param line Line of text which the width will be computed.
-- @return Text width
function Font:get_width(line)
local codepoint
local width = 0
line = line or ''
while line ~= "" do
codepoint, line = self:get_next_char(line)
if codepoint == nil then return 0 end -- UTF Error
width = width + self:get_char_width(codepoint)
end
return width
end
--- Legacy make_text_texture method (replaced by "render" - Dec 2018)
function Font:make_text_texture(text, texturew, textureh, maxlines,
halign, valign, color)
return self:render(text, texturew, textureh, {
lines = maxlines,
valign = valign,
halign = halign,
color = color
})
end
--- 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
function Font:render(text, texturew, textureh, style)
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
elseif style.valign == "bottom" then
y = textureh - textheight
else
y = (textureh - textheight) / 2
end
y = y + (self.margintop or 0)
for _, line in pairs(lines) do
if style.halign == "left" then
x = 0
elseif style.halign == "right" then
x = texturew - line.width
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..
string.format(":%d,%d=font_%s_%04x.png", x, y, self.name, codepoint)
end
x = x + self.widths[codepoint]
end
y = y + self:get_height() + (self.linespacing or 0)
end
texture = string.format("[combine:%dx%d", texturew, textureh)..texture
if style.color then
texture = texture.."^[colorize:"..style.color
end
return texture
end

View File

@ -1,166 +0,0 @@
--[[
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/>.
--]]
local modname = minetest.get_current_modname()
local contexts = {}
minetest.register_on_leaveplayer(function(player)
if minetest.is_player(player) then
contexts[player:get_player_name()] = nil
end
end)
local function get_context(playername)
if not contexts[playername] then
contexts[playername] = { playername = playername }
end
return contexts[playername]
end
-- Show node formspec functions
local function show_node_formspec(playername, pos)
local meta = minetest.get_meta(pos)
-- Decontextualize formspec
local fs = meta:get_string('formspec')
if not fs then
return
end
-- Change context and currrent_name references to nodemeta references
-- Change context and currrent_name references to nodemeta references
local nodemeta = string.format("nodemeta:%i,%i,%i", pos.x, pos.y ,pos.z)
fs = fs:gsub("current_name", nodemeta)
fs = fs:gsub("context", nodemeta)
-- Change all ${} to their corresponding metadata values
local s, e
repeat
s, e = fs:find('%${.*}')
if s and e then
fs = fs:sub(1, s-1)..
minetest.formspec_escape(meta:get_string(fs:sub(s+2,e-1)))..
fs:sub(e+1)
end
until s == nil
local context = get_context(playername)
context.node_pos = pos
-- Find node on_receive_fields
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
if ndef and ndef.on_receive_fields then
context.on_receive_fields = ndef.on_receive_fields
end
-- Show formspec
minetest.show_formspec(playername, modname..':context_formspec', fs)
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= modname..':context_formspec' then
return
end
if not minetest.is_player(player) then
return true
end
local context = get_context(player:get_player_name())
if context.on_receive_fields then
context.on_receive_fields(context.pos, '', fields, player)
end
return true
end)
-- Specific functions
local function show_font_formspec(playername)
local context = get_context(playername)
local fonts = {}
for name, _ in pairs(font_api.registered_fonts) do
fonts[#fonts+1] = name
end
table.sort(fonts)
local fs = string.format(
"size[4,%s]%s%s%sbutton_exit[0,%s;4,1;cancel;Cancel]",
#fonts + 0.8, default.gui_bg, default.gui_bg_img, default.gui_slots,
#fonts)
for line = 1, #fonts do
local font = font_api.get_font(fonts[line])
local texture = font:make_text_texture(font.name, font:get_height()*5,
font:get_height()*1.2, 1, "center", "top", "#fff")
fs = string.format(
"%simage[0.1,%s;4.5,0.8;%s]button_exit[0,%s;4,1;font_%s;]",
fs, line-0.9, texture, line-1, font.name)
end
minetest.show_formspec(context.playername, modname..':font_list', fs)
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= modname..':font_list' then
return
end
if not minetest.is_player(player) then
return true
end
local playername = player:get_player_name()
local context = get_context(playername)
if not context.pos
or minetest.is_protected(context.pos, playername) then
return true
end
if fields.quit == 'true' then
for name, _ in pairs(font_api.registered_fonts) do
if fields['font_'..name] then
local meta = minetest.get_meta(context.pos)
meta:set_string("font", name)
display_api.update_entities(context.pos)
end
end
if context.callback and type(context.callback) == "function" then
-- Using after to avoid the "double close" bug
minetest.after(0, context.callback, playername, context.pos)
else
-- Using after to avoid the "double close" bug
minetest.after(0, show_node_formspec, playername, context.pos)
end
end
return true
end)
-- @param player Player viewing the form
-- @param pos Node pos
-- @param callback function(playername, pos) to be called on form close
function font_api.show_font_list(player, pos, callback)
if minetest.is_player(player) then
local context = get_context(player:get_player_name())
context.pos = pos
context.callback = callback
show_font_formspec(player:get_player_name())
end
end

View File

@ -1,35 +0,0 @@
--[[
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/>.
--]]
-- Global variables
-------------------
font_api = {}
font_api.name = minetest.get_current_modname()
font_api.path = minetest.get_modpath(font_api.name)
-- Inclusions
-------------
dofile(font_api.path.."/font.lua")
dofile(font_api.path.."/registry.lua")
dofile(font_api.path.."/fontform.lua")
if minetest.get_modpath("display_api") then
dofile(font_api.path.."/display_api.lua")
end
dofile(font_api.path.."/deprecation.lua")

View File

@ -1,3 +0,0 @@
name=font_api
description=A library for rendernig text on textures
optional_depends=display_api

View File

@ -1,160 +0,0 @@
--[[
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/>.
--]]
-- Global variables
-------------------
font_api.registered_fonts = {}
font_api.registered_fonts_number = 0
-- Local variables
------------------
local default_font = false
-- Local functions
------------------
-- Gets a default (settings or fist font)
local function get_default_font()
-- First call
if default_font == false then
default_font = nil
-- First, try with settings
local settings_font = minetest.settings:get("default_font")
if settings_font ~= nil and settings_font ~= "" then
default_font = font_api.registered_fonts[settings_font]
if default_font == nil then
minetest.log("warning", "Default font in settings (\""..
settings_font.."\") is not registered.")
end
end
-- If failed, choose first font without default = false
if default_font == nil then
for _, font in pairs(font_api.registered_fonts) do
if font.default then
default_font = font
break
end
end
end
-- If failed, chose first font
if default_font == nil then
for _, font in pairs(font_api.registered_fonts) do
default_font = font
break
end
end
-- Error, no font registered
if default_font == nil then
minetest.log("error",
"No font registred, unable to choose a default font.")
end
end
return default_font
end
--- Returns font object to be used according to font_name
-- @param font_name: Name of the font
-- @return Font object if font found (or default font)
function font_api.get_font(font_name)
local font = font_api.registered_fonts[font_name]
if font == nil then
local message
if font_name == nil then
message = "No font given"
else
message = "Font \""..font_name.."\" unregistered"
end
font = get_default_font()
if font ~= nil then
minetest.log("info", message..", using font \""..font.name.."\".")
end
end
return font
end
-- API functions
----------------
--- Returns de default font name
-- @return Default font name
function font_api.get_default_font_name()
return get_default_font().name
end
--- Register a new font
-- Textures corresponding to the font should be named after following patern :
-- font_<name>_<code>.png
-- <name> : name of the font
-- <code> : 4 digit hexadecimal unicode of the char
-- @param font_name Name of the font to register
-- If registering different sizes of the same font, add size in the font name
-- (e.g. times_10, times_12...).
-- @param def font definition. A associative array with following keys :
-- @key default True (by default) if this font may be used as default font
-- @key height (mandatory) Height in pixels of all font textures
-- @key widths (mandatory) Array of character widths in pixels, indexed by
-- UTF codepoints
-- @key margintop (optional) Margin (in texture pixels) added on top of each
-- char texture.
-- @key marginbottom (optional) dded at bottom of each char texture.
-- @key linespacing (optional) Spacing (in texture pixels) between each lines.
-- margintop, marginbottom and linespacing can be negative numbers (default 0)
-- and are to be used to adjust various font styles to each other.
-- TODO: Add something to remove common accent if not defined in font
function font_api.register_font(font_name, font_def)
if font_api.registered_fonts[font_name] ~= nil then
minetest.log("error", "Font \""..font_name.."\" already registered.")
return
end
local font = font_api.Font:new(font_def)
if font == nil then
minetest.log("error", "Unable to register font \""..font_name.."\".")
return
end
font.name = font_name
font_api.registered_fonts[font_name] = font
font_api.registered_fonts_number = font_api.registered_fonts_number + 1
-- Force to choose again default font
-- (allows use of fonts registered after start)
default_font = false
minetest.log("action", "New font registered in font_api: "..font_name..".")
end

View File

@ -1 +0,0 @@
default_font(Default font) string

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 B

View File

@ -1,71 +0,0 @@
#!/bin/bash
scriptname=$(basename $0)
identify="identify"
usage() {
echo "Usage: $0 fontname"
echo "fontname: The name of the font. Must correspond to existing texture/font_<fontname>_????.png files"
}
if [ $# -ne 1 ]
then
usage
exit 1
fi
font_name=$1
for f in textures/font_${font_name}_????.png
do
if [[ $f =~ textures/font_${font_name}_([0-9a-fA-F]{4}).png ]]
then
code=$((16#${BASH_REMATCH[1]}))
size=$(identify $f | cut -d " " -f 3)
w=$(echo $size | cut -d "x" -f 1)
h=$(echo $size | cut -d "x" -f 2)
if [ -z "$font_height" ]
then
font_height=$h
else
if [ $font_height -ne $h ]
then
echo "Error : $f as height of $h pixels, previous textures have a height of $font_height pixels. All textures should have the same height."
fi
fi
if [ -z "$font_widths" ]
then
font_widths="[$code]=$w"
else
font_widths="$font_widths, [$code]=$w"
fi
fi
done
echo "--[[
$luafile generated by $scriptname $(LANG=en_US date)
--]]
font_api.register_font(
'$font_name',
{
height = $font_height,
widths = {
$font_widths
},
}
);
" > font_$font_name.lua
if grep -q font_api depends.txt &>/dev/null
then
echo "font_api already in depends.txt."
else
echo "adding font_api to depends.txt."
echo "font_api" >> depends.txt
fi

View File

@ -1,111 +0,0 @@
#!/bin/bash
# This program generates a bitmap font for font_api mod for Minetest game.
# (c) Andrzej Pieńkowski <pienkowski.andrzej@gmail.com>
# (c) Pierre-Yves Rollo <dev@pyrollo.com>
# License: GPL
usage() {
echo "Usage: $0 fontfile fontname fontsize"
echo "fontfile: A TTF font file to use to create textures."
echo "fontname: The font name to be used in font_api (should be simple, with no spaces)."
echo "fontsize: Font height to be rendered."
}
if [ $# -ne 3 ]
then
usage
exit 1
fi
fontfile=$1
fontname=$2
fontsize=$3
if [ ! -r "$fontfile" ]
then
echo "$fontfile not readable."
exit 1
fi
# check imagemagick
hash convert &>/dev/null
if [ $? -eq 1 ]; then
echo -e "Error: This program requires convert from ImageMagick! Please install it by typing 'sudo apt-get install imagemagick' in terminal."
abort=1
fi
# check ttx
hash ttx &>/dev/null
if [ $? -eq 1 ]; then
echo -e "Error: This program requires ttx from FontTools! Please install it by typing 'sudo apt-get install fonttools' in terminal."
abort=1
fi
if [ $abort ]
then
exit 1
fi
generate() {
for i in $(seq $((0x$1)) $((0x$2)))
do
if echo "$codepoints" | grep -qi $(printf "0x%x" $i)
then
hex=$(printf "%04x" $i)
echo -e "Generating textures/font_${fontname}_$hex.png file for \"\\U$hex\" char."
if [[ "$hex" == "005c" ]] # Backslash char
then
convert -background none -fill black -font "$fontfile" -pointsize $fontsize label:"\\\\" -colorspace gray -channel alpha -threshold 50% textures/font_${fontname}_$hex.png
else
convert -background none -fill black -font "$fontfile" -pointsize $fontsize label:"$(echo -en "\\U$hex")" -colorspace gray -channel alpha -threshold 50% textures/font_${fontname}_$hex.png
fi
fi
done
}
mkdir textures
# Reads all available code points in the font.
codepoints=$(ttx -o - "$fontfile" | grep "<map code=" | cut -d \" -f 2)
# Mandatory chars
generate 0020 007f
# generate space and null characters
if [ ! -f "textures/font_${fontname}_0030.png" ]; then
echo "Error: Something wrong happened! Font was not generated!"
exit 1
else
size=$(identify textures/font_${fontname}_0030.png | cut -d " " -f 3)
if ! [[ $fontHeight =~ $re ]] ; then
echo "Error: Something wrong happened! Generated files might be broken!"
exit 1
else
w=$(expr $(echo $size | cut -d x -f 1) - 1)
h=$(expr $(echo $size | cut -d x -f 2) - 1)
# Space char
convert -size $size xc:transparent -colorspace gray textures/font_${fontname}_0020.png
# Null char
convert -size $size xc:transparent -colorspace gray -stroke black -fill transparent -strokewidth 1 -draw "rectangle 0,0 $w,$h" textures/font_${fontname}_0000.png
fi
fi
# Optional Unicode pages (see https://en.wikipedia.org/wiki/Unicode) :
# 00a0-00ff Latin-1 Supplement (full)
generate 00a0 00ff
# 0100-017f Latin Extended-A (full)
generate 0100 017f
# 0370-03ff Greek (full)
generate 0370 03ff
# 0400-04ff Cyrilic (full)
generate 0400 04ff
# 2000-206f General Punctuation (Limited to Dashes)
generate 2010 2015
# 2000-206f General Punctuation (Limited to Quotes)
generate 2018 201F
# 20a0-20cf Currency Symbols (Limited to Euro symbol)
generate 20ac 20ac

View File

@ -1,166 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -1,33 +0,0 @@
# Signs API
This mod provides various helper functions for registereing signs with text display. Text is locked if area is protected.
No actual signs get registered by this mod, the signs are defined in the sign submod.
For more information, see the [forum topic](https://forum.minetest.net/viewtopic.php?t=19365) at the Minetest forums.
**Dependancies**: default, display\_lib, font\_lib
**License**: Code under LGPL, Textures and models under CC-BY-SA
## API Functions
### `signs_api.set_display_text(pos, text)`
Sets the text of a sign. Usually called in `on_receive_fields`.
### `signs_api.set_formspec(pos)`
Usually called in `on_construct` to set the formspec.
### `signs_api.on_receive_fields(pos, formname, fields, player)`
Helper function for `on_receive_fields`. Sets the display text and checks for protection.
### `signs_api.on_place_direction(itemstack, placer, pointed_thing)`
On place callback for direction signs (chooses which sign according to look direction).
### `signs_api.on_rotate(pos, node, player, mode, new_param2)`
Handles screwdriver rotation. Direction is affected for direction signs.
### `signs_api.register_sign(mod, name, model)`
A method to quickly register signs.
## Changelog
### 2019-03-14
- __sign_api__: Screwdriver behavior changed. Now, left click rotates and changes direction.

View File

@ -1,10 +0,0 @@
Code by Pierre-Yves Rollo (pyrollo)
intllib support (i18n) by (fat115)
intllib fallback code and tools by Diego Martínez (kaeza)
Extra contributors:
(gpcf)
(Thomas--S)
Translations:
Muhammad Nur Hidayat Yasuyoshi (MuhdNurHidayat)
(fat115)

View File

@ -1,4 +0,0 @@
default
intllib?
display_api
font_api

View File

@ -1,251 +0,0 @@
--[[
signs mod for Minetest - Various signs with text displayed on
(c) Pierre-Yves Rollo
This file is part of signs.
signs 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.
signs 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 signs. If not, see <http://www.gnu.org/licenses/>.
--]]
signs_api = {}
signs_api.name = minetest.get_current_modname()
signs_api.path = minetest.get_modpath(signs_api.name)
-- Load support for intllib.
local S, NS = dofile(signs_api.path.."/intllib.lua")
signs_api.intllib = S
local F = function(...) return minetest.formspec_escape(S(...)) end
function signs_api.set_display_text(pos, text, font)
local meta = minetest.get_meta(pos)
meta:set_string("display_text", text)
if text and text ~= "" then
meta:set_string("infotext", "\""..text.."\"")
else
meta:set_string("infotext", "")
end
if font then
meta:set_string("font", font)
end
display_api.update_entities(pos)
end
function signs_api.set_formspec(pos)
local meta = minetest.get_meta(pos)
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
if ndef and ndef.display_entities
and ndef.display_entities["signs:display_text"] then
local maxlines = ndef.display_entities["signs:display_text"].maxlines
local fs, y
if maxlines == 1 then
fs = "field[0.5,0.7;5.5,1;display_text;"..F("Text")..
";${display_text}]"
y = 1.2
else
local extralabel = ""
if maxlines then
extralabel = F(" (first %s lines only)"):format(maxlines)
end
fs = "textarea[0.5,0.7;5.5,2;display_text;"..F("Text")..""..
extralabel..";${display_text}]"
y = 2.4
end
fs = fs.."button[1,"..y..";2,1;font;"..F("Font").."]"
fs = fs.."button_exit[3,"..y..";2,1;ok;"..F("Write").."]"
y = y + 0.8
fs = "size[6,"..y.."]"..default.gui_bg..
default.gui_bg_img..default.gui_slots..fs
meta:set_string("formspec", fs)
end
end
function signs_api.on_receive_fields(pos, formname, fields, player)
if not minetest.is_protected(pos, player:get_player_name()) then
if fields and (fields.ok or fields.key_enter) then
signs_api.set_display_text(pos, fields.display_text)
end
if fields and (fields.font) then
signs_api.set_display_text(pos, fields.display_text)
font_api.show_font_list(player, pos)
end
end
end
-- On place callback for direction signs
-- (chooses which sign according to look direction)
function signs_api.on_place_direction(itemstack, placer, pointed_thing)
local name = itemstack:get_name()
local ndef = minetest.registered_nodes[name]
local restriction = display_api.is_rotation_restricted()
local bdir = {
x = pointed_thing.under.x - pointed_thing.above.x,
y = pointed_thing.under.y - pointed_thing.above.y,
z = pointed_thing.under.z - pointed_thing.above.z}
local pdir = placer:get_look_dir()
local ndir, test
if ndef.paramtype2 == "facedir" then
-- If legacy mode, only accept upright nodes
if restriction and bdir.x == 0 and bdir.z == 0 then
-- Ceiling or floor pointed (facedir chosen from player dir)
ndir = minetest.dir_to_facedir({x=pdir.x, y=0, z=pdir.z})
else
-- Wall pointed or no rotation restriction
ndir = minetest.dir_to_facedir(bdir, not restriction)
end
test = { [0]=-pdir.x, pdir.z, pdir.x, -pdir.z, -pdir.x, [8]=pdir.x }
end
if ndef.paramtype2 == "wallmounted" then
ndir = minetest.dir_to_wallmounted(bdir)
-- If legacy mode, only accept upright nodes
if restriction and (ndir == 0 or ndir == 1) then
ndir = minetest.dir_to_wallmounted({x=pdir.x, y=0, z=pdir.z})
end
test = { [0]=-pdir.x, -pdir.x, pdir.z, -pdir.z, -pdir.x, pdir.x}
end
-- Only for direction signs
-- TODO:Maybe improve ground and ceiling placement in every directions
if ndef.signs_other_dir then
if test[ndir] > 0 then
itemstack:set_name(ndef.signs_other_dir)
end
itemstack = minetest.item_place(itemstack, placer, pointed_thing, ndir)
itemstack:set_name(name)
return itemstack
else
return minetest.item_place(itemstack, placer, pointed_thing, ndir)
end
end
-- Handles screwdriver rotation
-- (see "if" block below for rotation restriction mode).
signs_api.on_rotate = function(pos, node, player, mode, new_param2)
-- If rotation mode is 1 and sign is directional, swap direction between
-- each rotation.
if mode == 1 then
local ndef = minetest.registered_nodes[node.name]
if ndef.signs_other_dir then
-- Switch direction
node = {name = ndef.signs_other_dir,
param1 = node.param1, param2 = node.param2}
minetest.swap_node(pos, node)
display_api.update_entities(pos)
-- Rotate only if not "main" sign
-- TODO:Improve detection of "main" direction sign
if ndef.groups and ndef.groups.not_in_creative_inventory then
return display_api.on_rotate(pos, node, player, mode, new_param2)
else
return true
end
end
end
return display_api.on_rotate(pos, node, player, mode, new_param2)
end
-- Legacy mode with rotation restriction
-- TODO:When MT < 5.0 no more in use, to be removed
if display_api.is_rotation_restricted() then
signs_api.on_rotate = function(pos, node, player, mode, new_param2)
-- If rotation mode is 2 and sign is directional, swap direction.
-- Otherwise use display_api's on_rotate function.
if mode == 2 then
local ndef = minetest.registered_nodes[node.name]
if ndef.signs_other_dir then
minetest.swap_node(pos, {name = ndef.signs_other_dir,
param1 = node.param1, param2 = node.param2})
display_api.update_entities(pos)
return true
end
end
return display_api.on_rotate(pos, node, player, mode, new_param2)
end
end
function signs_api.register_sign(mod, name, model)
-- Default fields
local fields = {
sunlight_propagates = true,
paramtype = "light",
paramtype2 = "facedir",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {-model.width/2, -model.height/2, 0.5,
model.width/2, model.height/2, 0.5 - model.depth},
},
groups = {choppy=2, dig_immediate=2, not_blocking_trains=1, display_api=1},
sounds = default.node_sound_defaults(),
display_entities = {
["signs:display_text"] = {
on_display_update = font_api.on_display_update,
depth = 0.5 - display_api.entity_spacing - model.depth,
size = { x = model.width, y = model.height },
aspect_ratio = 1/2,
maxlines = 1,
},
},
on_place = display_api.on_place,
on_construct = function(pos)
local ndef = minetest.registered_nodes[minetest.get_node(pos).name]
local meta = minetest.get_meta(pos)
meta:set_string("font", ndef.display_entities.font_name or
font_api.get_default_font_name())
signs_api.set_formspec(pos)
display_api.on_construct(pos)
end,
on_destruct = display_api.on_destruct,
on_rotate = signs_api.on_rotate,
on_receive_fields = signs_api.on_receive_fields,
on_punch = function(pos, node, player, pointed_thing)
signs_api.set_formspec(pos)
display_api.update_entities(pos)
end,
}
-- Node fields override
for key, value in pairs(model.node_fields) do
if key == "groups" then
for key2, value2 in pairs(value) do
fields[key][key2] = value2
end
else
fields[key] = value
end
end
if not fields.wield_image then fields.wield_image = fields.inventory_image end
-- Entity fields override
for key, value in pairs(model.entity_fields) do
fields.display_entities["signs:display_text"][key] = value
end
minetest.register_node(mod..":"..name, fields)
end
-- Text entity for all signs
display_api.register_display_entity("signs:display_text")

View File

@ -1,45 +0,0 @@
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.
-- Get the latest version of this file at:
-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua
local function format(str, ...)
local args = { ... }
local function repl(escape, open, num, close)
if escape == "" then
local replacement = tostring(args[tonumber(num)])
if open == "" then
replacement = replacement..close
end
return replacement
else
return "@"..open..num..close
end
end
return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end
local gettext, ngettext
if minetest.get_modpath("intllib") then
if intllib.make_gettext_pair then
-- New method using gettext.
gettext, ngettext = intllib.make_gettext_pair()
else
-- Old method using text files.
gettext = intllib.Getter()
end
end
-- Fill in missing functions.
gettext = gettext or function(msgid, ...)
return format(msgid, ...)
end
ngettext = ngettext or function(msgid, msgid_plural, n, ...)
return format(n==1 and msgid or msgid_plural, ...)
end
return gettext, ngettext

View File

@ -1,49 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-01 05:56+0100\n"
"PO-Revision-Date: 2017-05-08 07:08+0200\n"
"Last-Translator: Peppy <peppy@twang-factory.com>\n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.12\n"
#: common.lua
msgid "Text"
msgstr "Texte"
#: common.lua
msgid "Write"
msgstr "Écrire"
#: common.lua
#, lua-format
msgid " (first %s lines only)"
msgstr " (uniquement les %s premières lignes)"
#~ msgid "Title"
#~ msgstr "Titre"
#~ msgid "Close"
#~ msgstr "Fermer"
#~ msgid "(right-click to read more text)"
#~ msgstr "(Clic-droit pour afficher le texte entier)"
#~ msgid "Wooden direction sign"
#~ msgstr "Panneau de direction en bois"
#~ msgid "Poster"
#~ msgstr "Affiche"
#~ msgid "Textd"
#~ msgstr "Texte"

View File

@ -1,46 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Muhammad Nur Hidayat <muhdnurhidayat96@yahoo.com>, 2017.
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-01 05:56+0100\n"
"PO-Revision-Date: 2017-08-27 15:50+0800\n"
"Last-Translator: Muhammad Nur Hidayat <muhdnurhidayat96@yahoo.com>\n"
"Language-Team: Malay <muhdnurhidayat96@yahoo.com>\n"
"Language: ms\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Vé 0.1.4\n"
#: common.lua
msgid "Text"
msgstr "Teks"
#: common.lua
msgid "Write"
msgstr "Tulis"
#: common.lua
#, lua-format
msgid " (first %s lines only)"
msgstr "( %s baris pertama sahaja )"
#~ msgid "Title"
#~ msgstr "Tajuk"
#~ msgid "Close"
#~ msgstr "Tutup"
#~ msgid "(right-click to read more text)"
#~ msgstr "(klik-kanan untuk baca teks penuh)"
#~ msgid "Wooden direction sign"
#~ msgstr "Papan tanda arah kayu"
#~ msgid "Poster"
#~ msgstr "Poster"

View File

@ -1,31 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-01 05:56+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: common.lua
msgid "Text"
msgstr ""
#: common.lua
msgid "Write"
msgstr ""
#: common.lua
#, lua-format
msgid " (first %s lines only)"
msgstr ""

View File

@ -1,4 +0,0 @@
name=signs_api
description=A library providing various helper functions for registereing signs with text display
depends=default,display_api,font_api
optional_depends=intllib

View File

@ -1,25 +0,0 @@
#! /bin/bash
# To create a new translation:
# msginit --locale=ll_CC -o locale/ll_CC.po -i locale/template.pot
cd "$(dirname "${BASH_SOURCE[0]}")/..";
# Extract translatable strings.
xgettext --from-code=UTF-8 \
--language=Lua \
--sort-by-file \
--keyword=S \
--keyword=NS:1,2 \
--keyword=N_ \
--keyword=F \
--add-comments='Translators:' \
--add-location=file \
-o locale/template.pot \
$(find . -name '*.lua')
# Update translations.
find locale -name '*.po' | while read -r file; do
echo $file
msgmerge --update $file locale/template.pot;
done