1
0
mirror of https://github.com/pyrollo/display_modpack.git synced 2025-10-15 08:35:35 +02:00
This commit is contained in:
Pierre-Yves Rollo
2025-10-07 11:08:09 +02:00
parent cbc594343c
commit e592b52b18
4 changed files with 99 additions and 65 deletions

View File

@@ -58,6 +58,7 @@ end
--- Font class
local Font = {}
Font.__index = Font
font_api.Font = Font
function Font:new(def)
@@ -70,31 +71,53 @@ function Font:new(def)
local font = table.copy(def)
if font.height == nil or font.height <= 0 then
minetest.log("error",
"[font_api] Font definition must have a positive height.")
return nil
end
if type(font.widths) == "table" then
if type(font.glyphs) == "table" then
minetest.log("warning",
"[font_api] Ingonring `widths` array in font definition as there is also a `glyphs` array.")
else
minetest.log("warning",
"[font_api] Use of `widths` array in font definition is deprecated, please upgrade to `glyphs`.")
font.glyphs = {}
for codepoint, width in pairs(font.widths) do
font.glyphs[codepoint] = { w = width, c = codepoint }
end
font.widths = nil
-- Version 1 is with one texture per glyph
if font.version == nil or font.version == 1 then
if font.height == nil or font.height <= 0 then
minetest.log("error",
"[font_api] Font definition must have a positive height.")
return nil
end
if type(font.widths) ~= "table" then
minetest.log("error",
"[font_api] Font definition must have a `widths` array.")
return nil
end
-- Kind of convert to version 2
font.glyphs = {}
for codepoint, width in pairs(font.widths) do
font.glyphs[codepoint] = { width, codepoint }
end
font.widths = nil
font.glyphs_height = font.height
font.height = nil
end
if type(font.glyphs) ~= "table" then
minetest.log("error",
"[font_api] Font definition must have a `glyphs` array.")
return nil
-- Version 2 is with one only texture for all glyphs, using `[sheet` textures
if font.version == 2 then
if type(font.glyphs) ~= "table" then
minetest.log("error",
"[font_api] Font definition must have a `glyphs` array.")
return nil
end
if font.texture_height == nil or font.texture_height <= 0 then
minetest.log("error",
"[font_api] Font definition must have a positive `texture_height`.")
return nil
end
if font.glyphs_height == nil or font.glyphs_height <= 0 then
minetest.log("error",
"[font_api] Font definition must have a positive `glyphs_height`.")
return nil
end
font.vertical_number_of_tiles = math.floor(font.texture_height / font.glyphs_height)
end
if font.glyphs[0] == nil then
@@ -103,8 +126,7 @@ function Font:new(def)
return nil
end
setmetatable(font, self)
self.__index = self
setmetatable(font, self)
return font
end
@@ -149,7 +171,8 @@ end
-- @return Char width
function Font:get_char_width(codepoint)
return (self.glyphs[codepoint] or self.glyphs[0]).w
-- [1] is char width
return (self.glyphs[codepoint] or self.glyphs[0])[1]
end
--- Returns texture for a given glyph
@@ -157,22 +180,18 @@ end
-- @return Texture
function Font:get_glyph_texture(glyph)
if glyph.c then
if #glyph == 4 then
-- Actual version with one texture for all glyphs
return string.format("font_%s.png^[sheet:%dx%d:%d,%d",
self.name, glyph[2], self.vertical_number_of_tiles, glyph[3], glyph[4])
end
if #glyph == 2 then
-- Former version with one texture per glyph
return string.format("font_%s_%04x.png",
self.name, glyph.c)
end
if glyph.x == nil or glyph.y == nil then
-- Case of invisible chars like space (no need to add any texture)
return ""
self.name, glyph[2])
end
--le 5x15 est le nombre de tuiles, pas la taille des tuiles.
return string.format("font_%s.png^[sheet:40x5:%d,%d",
self.name, glyph.x, glyph.y)
-- return string.format("font_%s.png^[sheet:%dx%d:%d,%d",
-- self.name, glyph.w, self.height, glyph.x, glyph.y)
-- Case of invisible chars like space (no need to add any texture)
return ""
end
--- Text height for multiline text including margins and line spacing
@@ -185,7 +204,7 @@ function Font:get_height(nb_of_lines)
if nb_of_lines > 0 then
return
(
(self.height or 0) +
self.glyphs_height +
(self.margintop or 0) +
(self.marginbottom or 0)
) * nb_of_lines +
@@ -227,8 +246,8 @@ 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 width Width (in pixels) of the texture (extra text will be truncated)
-- @param height 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")
@@ -236,7 +255,7 @@ end
-- - color: color of the text ("#rrggbb")
-- @return Texture string
function Font:render(text, texturew, textureh, style)
function Font:render(text, width, height, style)
style = style or {}
-- Split text into lines (and limit to style.lines # of lines)
@@ -256,14 +275,14 @@ function Font:render(text, texturew, textureh, style)
local x, y, codepoint
local texture = ""
local textheight = self:get_height(#lines)
local text_height = self:get_height(#lines)
if style.valign == "top" then
y = 0
elseif style.valign == "bottom" then
y = textureh - textheight
y = height - text_height
else
y = (textureh - textheight) / 2
y = (height - text_height) / 2
end
y = y + (self.margintop or 0)
@@ -272,9 +291,9 @@ function Font:render(text, texturew, textureh, style)
if style.halign == "left" then
x = 0
elseif style.halign == "right" then
x = texturew - l.width
x = width - l.width
else
x = (texturew - l.width) / 2
x = (width - l.width) / 2
end
while l.text ~= '' do
@@ -284,17 +303,19 @@ function Font:render(text, texturew, textureh, style)
local glyph = self.glyphs[codepoint]
-- Add image only if it is visible (at least partly)
if x + glyph.w >= 0 and x <= texturew then
texture = string.format("%s:%d,%d=%s",
texture, x, y, self:get_glyph_texture(glyph):gsub("[\\^:]", "\\%0"))
if x + glyph[1] >= 0 and x <= width then
local glyph_texture = self:get_glyph_texture(glyph):gsub("[\\^:]", "\\%0")
if glyph_texture ~= '' then
texture = string.format("%s:%d,%d=%s", texture, x, y, glyph_texture)
end
end
x = x + glyph.w
x = x + glyph[1]
end
y = y + self:get_height() + (self.linespacing or 0)
end
texture = string.format("[combine:%dx%d%s", texturew, textureh, texture)
texture = string.format("[combine:%dx%d%s", width, height, texture)
if style.color then
texture = texture.."^[colorize:"..style.color
end

View File

@@ -103,11 +103,17 @@ local function show_font_formspec(playername)
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")
local texture = font:render(font.name,
font:get_height()*5, font:get_height()*1.2, {
lines = 1,
valign = "middle",
halign = "center",
color = "#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)
fs, line - 0.9, texture, line - 1, font.name)
end
minetest.show_formspec(context.playername, modname..':font_list', fs)
end

5
font_api/tools/README.md Normal file
View File

@@ -0,0 +1,5 @@
# Debian installation
```shell
apt install lua5.4 imagemagick fonttools
```

View File

@@ -79,8 +79,8 @@ local function compute_tile_sizes(texture_size)
return results
end
-- This will give enough combinations (720 is 2 * 2 * 2 * 2 * 3 * 3 * 5)
tile_widths = compute_tile_sizes(720)
-- This will give enough combinations (360 is 2 * 2 * 2 * 3 * 3 * 5)
tile_widths = compute_tile_sizes(360)
-- Table width has to be sorted
table.sort(tile_widths)
@@ -177,9 +177,11 @@ local glyph_xs = {} -- x for each glyph
local glyph_ys = {} -- y for each glyph
local glyph_ns = {} -- n of tiles in sheet for each glyph (=texturewidth / tilewidth)
local texture_height
local function make_final_texture(filename)
local texture_height = font_height
texture_height = font_height
local x = 0 -- cursor x
local glyph_y = 0
@@ -209,7 +211,6 @@ local function make_final_texture(filename)
"convert -channel alpha -colorspace gray -size %dx%d xc:transparent %s",
texture_width, texture_height, filename
))
print(texture_width, texture_height)
for codepoint, n in pairs(glyph_ns) do
local w = texture_width // n
@@ -232,11 +233,10 @@ local function make_final_texture(filename)
end
-- Place subtexure in texture
cmd = string.format("convert %s \\( %s -repage +%d+%d \\) -flatten %s", filename, cmd, x, y, filename)
print (cmd)
command(cmd)
end
command(string.format("convert %s -threshold 50%% %s", filename, filename))
command(string.format("convert %s -channel alpha -threshold 50%% %s", filename, filename))
end
@@ -307,22 +307,24 @@ file:write(string.format([[
font_api.register_font(
'%s',
{
version = 2,
default = true,
margintop = 3,
linespacing = -2,
height = %d,
texture_height = %d,
glyphs_height = %d,
glyphs = {
]],
fontname, font_height)
fontname, texture_height, font_height)
)
for codepoint, w in pairs(glyph_widths) do
local x = glyph_xs[codepoint]
local y = glyph_ys[codepoint]
local n = glyph_ns[codepoint]
if x ~= nil and y ~=nil and n ~= nil then
file:write(string.format(" [%d] = { w = %d, n = %f, x = %d, y = %d },\n", codepoint, w, n, x, y))
file:write(string.format(" [%d] = { %d, %d, %d, %d },\n", codepoint, w, n, x, y))
else
file:write(string.format(" [%d] = { w = %d },\n", codepoint, w))
file:write(string.format(" [%d] = { %d },\n", codepoint, w))
end
end
file:write([[