1
0
mirror of https://github.com/pyrollo/display_modpack.git synced 2025-10-15 16:45: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 --- Font class
local Font = {} local Font = {}
Font.__index = Font
font_api.Font = Font font_api.Font = Font
function Font:new(def) function Font:new(def)
@@ -70,31 +71,53 @@ function Font:new(def)
local font = table.copy(def) local font = table.copy(def)
if font.height == nil or font.height <= 0 then -- Version 1 is with one texture per glyph
minetest.log("error", if font.version == nil or font.version == 1 then
"[font_api] Font definition must have a positive height.") if font.height == nil or font.height <= 0 then
return nil minetest.log("error",
end "[font_api] Font definition must have a positive height.")
return nil
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
end 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 end
if type(font.glyphs) ~= "table" then -- Version 2 is with one only texture for all glyphs, using `[sheet` textures
minetest.log("error", if font.version == 2 then
"[font_api] Font definition must have a `glyphs` array.") if type(font.glyphs) ~= "table" then
return nil 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 end
if font.glyphs[0] == nil then if font.glyphs[0] == nil then
@@ -103,8 +126,7 @@ function Font:new(def)
return nil return nil
end end
setmetatable(font, self) setmetatable(font, self)
self.__index = self
return font return font
end end
@@ -149,7 +171,8 @@ end
-- @return Char width -- @return Char width
function Font:get_char_width(codepoint) 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 end
--- Returns texture for a given glyph --- Returns texture for a given glyph
@@ -157,22 +180,18 @@ end
-- @return Texture -- @return Texture
function Font:get_glyph_texture(glyph) 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 -- Former version with one texture per glyph
return string.format("font_%s_%04x.png", return string.format("font_%s_%04x.png",
self.name, glyph.c) self.name, glyph[2])
end
if glyph.x == nil or glyph.y == nil then
-- Case of invisible chars like space (no need to add any texture)
return ""
end end
-- Case of invisible chars like space (no need to add any texture)
--le 5x15 est le nombre de tuiles, pas la taille des tuiles. return ""
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)
end end
--- Text height for multiline text including margins and line spacing --- 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 if nb_of_lines > 0 then
return return
( (
(self.height or 0) + self.glyphs_height +
(self.margintop or 0) + (self.margintop or 0) +
(self.marginbottom or 0) (self.marginbottom or 0)
) * nb_of_lines + ) * nb_of_lines +
@@ -227,8 +246,8 @@ end
--- Render text with the font in a view --- Render text with the font in a view
-- @param text Text to be rendered -- @param text Text to be rendered
-- @param texturew Width (in pixels) of the texture (extra text will be truncated) -- @param width 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 height Height (in pixels) of the texture (extra text will be truncated)
-- @param style Style of the rendering: -- @param style Style of the rendering:
-- - lines: maximum number of text lines (if text is limited) -- - lines: maximum number of text lines (if text is limited)
-- - halign: horizontal align ("left"/"center"/"right") -- - halign: horizontal align ("left"/"center"/"right")
@@ -236,7 +255,7 @@ end
-- - color: color of the text ("#rrggbb") -- - color: color of the text ("#rrggbb")
-- @return Texture string -- @return Texture string
function Font:render(text, texturew, textureh, style) function Font:render(text, width, height, style)
style = style or {} style = style or {}
-- Split text into lines (and limit to style.lines # of lines) -- 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 x, y, codepoint
local texture = "" local texture = ""
local textheight = self:get_height(#lines) local text_height = self:get_height(#lines)
if style.valign == "top" then if style.valign == "top" then
y = 0 y = 0
elseif style.valign == "bottom" then elseif style.valign == "bottom" then
y = textureh - textheight y = height - text_height
else else
y = (textureh - textheight) / 2 y = (height - text_height) / 2
end end
y = y + (self.margintop or 0) y = y + (self.margintop or 0)
@@ -272,9 +291,9 @@ function Font:render(text, texturew, textureh, style)
if style.halign == "left" then if style.halign == "left" then
x = 0 x = 0
elseif style.halign == "right" then elseif style.halign == "right" then
x = texturew - l.width x = width - l.width
else else
x = (texturew - l.width) / 2 x = (width - l.width) / 2
end end
while l.text ~= '' do while l.text ~= '' do
@@ -284,17 +303,19 @@ function Font:render(text, texturew, textureh, style)
local glyph = self.glyphs[codepoint] local glyph = self.glyphs[codepoint]
-- Add image only if it is visible (at least partly) -- Add image only if it is visible (at least partly)
if x + glyph.w >= 0 and x <= texturew then if x + glyph[1] >= 0 and x <= width then
texture = string.format("%s:%d,%d=%s", local glyph_texture = self:get_glyph_texture(glyph):gsub("[\\^:]", "\\%0")
texture, x, y, 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 end
x = x + glyph.w x = x + glyph[1]
end end
y = y + self:get_height() + (self.linespacing or 0) y = y + self:get_height() + (self.linespacing or 0)
end end
texture = string.format("[combine:%dx%d%s", texturew, textureh, texture) texture = string.format("[combine:%dx%d%s", width, height, texture)
if style.color then if style.color then
texture = texture.."^[colorize:"..style.color texture = texture.."^[colorize:"..style.color
end end

View File

@@ -103,11 +103,17 @@ local function show_font_formspec(playername)
for line = 1, #fonts do for line = 1, #fonts do
local font = font_api.get_font(fonts[line]) local font = font_api.get_font(fonts[line])
local texture = font:make_text_texture(font.name, font:get_height()*5, local texture = font:render(font.name,
font:get_height()*1.2, 1, "center", "top", "#fff") font:get_height()*5, font:get_height()*1.2, {
lines = 1,
valign = "middle",
halign = "center",
color = "#fff"
}
)
fs = string.format( fs = string.format(
"%simage[0.1,%s;4.5,0.8;%s]button_exit[0,%s;4,1;font_%s;]", "%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 end
minetest.show_formspec(context.playername, modname..':font_list', fs) minetest.show_formspec(context.playername, modname..':font_list', fs)
end 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 return results
end end
-- This will give enough combinations (720 is 2 * 2 * 2 * 2 * 3 * 3 * 5) -- This will give enough combinations (360 is 2 * 2 * 2 * 3 * 3 * 5)
tile_widths = compute_tile_sizes(720) tile_widths = compute_tile_sizes(360)
-- Table width has to be sorted -- Table width has to be sorted
table.sort(tile_widths) table.sort(tile_widths)
@@ -177,9 +177,11 @@ local glyph_xs = {} -- x for each glyph
local glyph_ys = {} -- y for each glyph local glyph_ys = {} -- y for each glyph
local glyph_ns = {} -- n of tiles in sheet for each glyph (=texturewidth / tilewidth) local glyph_ns = {} -- n of tiles in sheet for each glyph (=texturewidth / tilewidth)
local texture_height
local function make_final_texture(filename) local function make_final_texture(filename)
local texture_height = font_height texture_height = font_height
local x = 0 -- cursor x local x = 0 -- cursor x
local glyph_y = 0 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", "convert -channel alpha -colorspace gray -size %dx%d xc:transparent %s",
texture_width, texture_height, filename texture_width, texture_height, filename
)) ))
print(texture_width, texture_height)
for codepoint, n in pairs(glyph_ns) do for codepoint, n in pairs(glyph_ns) do
local w = texture_width // n local w = texture_width // n
@@ -232,11 +233,10 @@ local function make_final_texture(filename)
end end
-- Place subtexure in texture -- Place subtexure in texture
cmd = string.format("convert %s \\( %s -repage +%d+%d \\) -flatten %s", filename, cmd, x, y, filename) cmd = string.format("convert %s \\( %s -repage +%d+%d \\) -flatten %s", filename, cmd, x, y, filename)
print (cmd)
command(cmd) command(cmd)
end end
command(string.format("convert %s -threshold 50%% %s", filename, filename)) command(string.format("convert %s -channel alpha -threshold 50%% %s", filename, filename))
end end
@@ -307,22 +307,24 @@ file:write(string.format([[
font_api.register_font( font_api.register_font(
'%s', '%s',
{ {
version = 2,
default = true, default = true,
margintop = 3, margintop = 3,
linespacing = -2, linespacing = -2,
height = %d, texture_height = %d,
glyphs_height = %d,
glyphs = { glyphs = {
]], ]],
fontname, font_height) fontname, texture_height, font_height)
) )
for codepoint, w in pairs(glyph_widths) do for codepoint, w in pairs(glyph_widths) do
local x = glyph_xs[codepoint] local x = glyph_xs[codepoint]
local y = glyph_ys[codepoint] local y = glyph_ys[codepoint]
local n = glyph_ns[codepoint] local n = glyph_ns[codepoint]
if x ~= nil and y ~=nil and n ~= nil then 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 else
file:write(string.format(" [%d] = { w = %d },\n", codepoint, w)) file:write(string.format(" [%d] = { %d },\n", codepoint, w))
end end
end end
file:write([[ file:write([[