1
0
mirror of https://github.com/pyrollo/display_modpack.git synced 2025-10-15 16:45:35 +02:00

WIP params

This commit is contained in:
Pierre-Yves Rollo
2025-10-10 11:42:58 +02:00
parent 4a278539b2
commit 4b0245dc8b
7 changed files with 357 additions and 166 deletions

View File

@@ -0,0 +1,68 @@
-- This is an example parameter file for make_font.lua
-- Copy this file as params.lua.
-- Replace values between brakets <> to your choices.
-- Launch make_font.lua params.lua
params = {
-- Resulting mod name (required)
-- As this name will be use as texture prefix and so repeated many times,
-- please avoid long names but keep explicit anyway.
mod_name = "fonts_extra",
-- If only one font, have font in title, like "xxx font"
mod_title = "Extra fonts",
-- A good description would be "... fonts for font_api"
mod_descriptiion = "Extra fonts for font_api: botic",
-- List of fons to include to the mod.
fonts = {
{
-- Registered font name (required)
-- As this name will be use as texture prefix and so repeated many times,
-- avoid long names. A good name would be a single world all lowercase.
name = "botic",
-- Registered font label (optional, default capitalized name)
-- This is the display name for this font. No need to be concise.
label = "Botic",
-- True type font file to get glyphs from (required)
file = "sources/pixeldroidBoticRegular.ttf",
-- Render pointsize (integer, required)
-- Try to find a proper value for a good rendering
pointsize = 16,
-- Shoud chars be trimmed? (boolean, required)
-- Set it to true to reduce texture size
-- and increase `char_spacing` accordingly.
-- If results are weird, you may try to set it to false.
trim = true,
-- Margin added on top of text textures with this font (integer, optional, default 0)
margin_top = 3,
-- Space between consecutive lines (integer, optional, default 0)
-- Space may be negative to make lines closer.
line_spacing = -2,
-- Space between consecutive chars (integer, optional, default 0)
char_spacing = 2,
-- Extra codepoints to include to font mod (optional, default none)
-- Codepoints from 0x0020 to 0x007f (ASCII) are always included.
-- Codepoint 0x0020 is always considered as a space.
-- Codepoints not existing in font file will be ignored.
-- Refer to https://en.wikipedia.org/wiki/Unicode
codepoints = {
-- 00a0-00ff Latin-1 Supplement (full)
{ from=0x00a0, to=0x00ff },
-- 20a0-20cf Currency Symbols (Limited to Euro symbol)
{ from=0x20ac, 0x20ac },
},
}
}
}

Binary file not shown.

View File

@@ -6,11 +6,6 @@
-- TODO : detect and manage fixed width fonts -- TODO : detect and manage fixed width fonts
-- TODO: HAVE A PARAM FILE FOR EACH FONT WITH WANTED SETTINGS
-- Par exemple:
-- activation du trim
-- valeur de linespacing / charspacing ..
-- enabled codepoints
-- --
-- Dependancies check -- Dependancies check
@@ -35,44 +30,32 @@ end
-- --
-- Argument management -- Argument & parameters management
-- --
local function usage() local function usage()
print (arg[0] .. " takes tree arguments:") print (arg[0] .. " takes two arguments:")
print (" - font file name") print (" - parameter file")
print (" - wanted font name") print (" - destination path")
print (" - wanted font height")
end end
if #arg ~= 3 then if #arg ~= 2 then
usage() usage()
os.exit(1) os.exit(1)
end end
local fontfile = arg[1] print("Reading paramaters.")
local fontname = arg[2] dofile(arg[1])
local fontsize = arg[3]
local modname = fontname local mod_dir = arg[2]
if os.execute("[ -d " .. mod_dir .. " ]") then
-- print ("Directory " .. mod_dir .. " already exists!")
-- Prepare output directory
--
-- TODO: we should be able to choose basedir
local moddir = "font_" .. fontname
if os.execute("[ -d " .. moddir .. " ]") then
print ("Directory " .. moddir .. " already exists!")
-- os.exit(1) -- os.exit(1)
end end
os.execute("mkdir -p " .. mod_dir .. "/textures")
os.execute("mkdir -p " .. moddir .. "/textures")
-- --
-- Compute available tile sizes -- Available tile sizes management
-- --
local function compute_tile_sizes(texture_size) local function compute_tile_sizes(texture_size)
@@ -86,11 +69,11 @@ local function compute_tile_sizes(texture_size)
end end
-- This will give enough tile width combinations (360 is 2 * 2 * 2 * 3 * 3 * 5) -- This will give enough tile width combinations (360 is 2 * 2 * 2 * 3 * 3 * 5)
tile_widths = compute_tile_sizes(360) local 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)
texture_width = tile_widths[#tile_widths] local texture_width = tile_widths[#tile_widths]
-- Rounds glyph width up to available tile width (first width larger than given one) -- Rounds glyph width up to available tile width (first width larger than given one)
local function tile_width(width) local function tile_width(width)
@@ -103,11 +86,10 @@ local function tile_width(width)
end end
-- --
-- Things start here -- Helper functions
-- --
-- Issue an OS command and get its result -- Issue an OS command and get its result
local function command(cmd) local function command(cmd)
local f = assert(io.popen(cmd, 'r')) local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a')) local s = assert(f:read('*a'))
@@ -116,7 +98,6 @@ local function command(cmd)
end end
-- Escape chars that could harm commands -- Escape chars that could harm commands
local function escape(char) local function escape(char)
if char == "\\" then return "\\\\\\\\" end if char == "\\" then return "\\\\\\\\" end
if char == "\"" then return "\\\"" end if char == "\"" then return "\\\"" end
@@ -124,14 +105,17 @@ local function escape(char)
return char return char
end end
-- Measures a glyph, returs its height and width in pixels --
-- Things start here
--
local function measure(codepoint) -- Measures a glyph, returs its height and width in pixels
local function measure(font, codepoint)
local char = utf8.char(codepoint) local char = utf8.char(codepoint)
local cmd = string.format( local cmd = string.format(
"convert -font \"%s\" -pointsize %d label:\"%s\" -define trim:edges=east,west -trim info:", "convert -font \"%s\" -pointsize %d label:\"%s\" -define trim:edges=east,west -trim info:",
fontfile, fontsize, escape(char) font.file, font.height, escape(char)
) )
local _, _, w, h = string.find(command(cmd), "([0-9]+)x([0-9]+)" ) local _, _, w, h = string.find(command(cmd), "([0-9]+)x([0-9]+)" )
@@ -139,76 +123,82 @@ local function measure(codepoint)
return tonumber(w), tonumber(h) return tonumber(w), tonumber(h)
end end
-- Read all available codepoints -- Read all available codepoints from ttf file
local cmd, errmsg, status = io.popen("ttx -o - \"" .. fontfile .. "\" 2>/dev/null | grep \"<map code=\" | cut -d \\\" -f 2", 'r') local function read_available_codepoints(file)
if cmd == nil then local cmd, errmsg, status = io.popen(string.format(
print("Could not open font file " .. fontfile .. ":\n" .. errmsg) "ttx -o - \"%s\" 2>/dev/null | grep \"<map code=\" | cut -d \\\" -f 2",
os.exit(status) file), 'r')
if cmd == nil then
print(string.format(
"Could not open font file %s:\n%s", file, errmsg))
os.exit(status)
end
local codepoints = {}
local codepoint = cmd:read("*line")
while codepoint do
codepoints[tonumber(codepoint)] = true
codepoint = cmd:read("*line")
end
cmd:close()
return codepoints
end end
local codepoints = {} -- Add codepoints to a font
local codepoint = cmd:read("*line") local function add_codepoints(font, from, to)
while codepoint do
codepoints[tonumber(codepoint)] = true
codepoint = cmd:read("*line")
end
cmd:close()
local by_width = {} -- Codepoints by tile width
local tile_widths = {} -- Existing tile width
local glyph_widths = {} -- Exact width of reach glyph
local font_height = 0 -- Max height of all glyphs
local function add_codepoints(from, to)
for codepoint = from, to do for codepoint = from, to do
if codepoints[codepoint] then if font.cp[codepoint] then
-- Glyph size -- Glyph size
local w, h = measure(codepoint) local w, h = measure(font, codepoint)
if h > font_height then font_height = h end if h > font.glyphs_height then font.glyphs_height = h end
glyph_widths[codepoint] = w font.glyph_widths[codepoint] = w
-- Tile width -- Tile width
local tile_w = tile_width(w) local tile_w = tile_width(w)
if by_width[tile_w] == nil then if font.by_width[tile_w] == nil then
by_width[tile_w] = {} font.by_width[tile_w] = {}
table.insert(tile_widths, tile_w) table.insert(font.tile_widths, tile_w)
end end
table.insert(by_width[tile_w], codepoint) table.insert(font.by_width[tile_w], codepoint)
end end
end end
end end
-- Characteristics of [sheet:NxM:x,y -- Make font texture
-- M is always the same and depends on font and texture height. -- Font must have all its codepoints added
local glyph_xs = {} -- x for each glyph local function make_final_texture(font)
local glyph_ys = {} -- y for each glyph local texture_file = string.format("%/textures/font_%s.png",
local glyph_ns = {} -- n of tiles in sheet for each glyph (=texturewidth / tilewidth) mod_dir, font.name)
local texture_height -- We start with a single line
font.texture_height = font.glyphs_height
local function make_final_texture(filename) -- Characteristics of [sheet:NxM:x,y
-- M is always the same and depends on font and texture height.
font.glyph_xs = {} -- x for each glyph
font.glyph_ys = {} -- y for each glyph
font.glyph_ns = {} -- n of tiles in sheet for each glyph (=texturewidth / tilewidth)
texture_height = font_height
local x = 0 -- cursor x local x = 0 -- cursor x
local glyph_y = 0 local glyph_y = 0
table.sort(tile_widths) table.sort(font.tile_widths)
-- Compute positions -- Compute positions
for _, tile_width in ipairs(tile_widths) do for _, tile_width in ipairs(font.tile_widths) do
for _, codepoint in ipairs(by_width[tile_width]) do for _, codepoint in ipairs(font.by_width[tile_width]) do
local glyph_x = math.ceil(x / tile_width) local glyph_x = math.ceil(x / tile_width)
x = glyph_x * tile_width x = glyph_x * tile_width
if x + tile_width > texture_width then -- no space left on current line if x + tile_width > font.texture_width then -- no space left on current line
x = 0 x = 0
glyph_x = 0 glyph_x = 0
glyph_y = glyph_y + 1 glyph_y = glyph_y + 1
texture_height = texture_height + font_height font.texture_height = font.texture_height + font.glyphs_height
end end
glyph_xs[codepoint] = glyph_x font.glyph_xs[codepoint] = glyph_x
glyph_ys[codepoint] = glyph_y font.glyph_ys[codepoint] = glyph_y
glyph_ns[codepoint] = math.floor(texture_width / tile_width) font.glyph_ns[codepoint] = math.floor(texture_width / tile_width)
x = x + tile_width x = x + tile_width
end end
end end
@@ -216,13 +206,13 @@ local function make_final_texture(filename)
-- Compose texture -- Compose texture
command(string.format( command(string.format(
"convert -size %dx%d xc:transparent %s", "convert -size %dx%d xc:transparent %s",
texture_width, texture_height, filename texture_width, texture_height, texture_file
)) ))
for codepoint, n in pairs(glyph_ns) do for codepoint, n in pairs(glyph_ns) do
local w = math.floor(texture_width / n) local w = math.floor(texture_width / n)
local x = w * glyph_xs[codepoint] local x = w * glyph_xs[codepoint]
local y = font_height * glyph_ys[codepoint] local y = font.glyphs_height * glyph_ys[codepoint]
local cmd local cmd
-- Subtexture subcommand -- Subtexture subcommand
@@ -232,7 +222,7 @@ local function make_final_texture(filename)
"convert %s" .. "convert %s" ..
" -stroke black -fill transparent -strokewidth 1 " .. " -stroke black -fill transparent -strokewidth 1 " ..
" -draw \"rectangle %d,%d %d,%d\" %s", " -draw \"rectangle %d,%d %d,%d\" %s",
filename, x, y, x + w, y + font_height, filename texture_file, x, y, x + w, y + font.glyphs_height, texture_file
) )
else else
-- Other glyhp chars -- Other glyhp chars
@@ -241,82 +231,91 @@ local function make_final_texture(filename)
" -background none -font \"%s\" -pointsize %d label:\"%s\"" .. " -background none -font \"%s\" -pointsize %d label:\"%s\"" ..
" -define trim:edges=east,west -trim" .. " -define trim:edges=east,west -trim" ..
" -repage +%d+%d \\) -flatten %s", " -repage +%d+%d \\) -flatten %s",
filename, fontfile, fontsize, escape(utf8.char(codepoint)), texture_file, font.file, font.pointsize, escape(utf8.char(codepoint)),
x, y, filename x, y, texture_file
) )
end end
command(cmd) command(cmd)
end end
command(string.format("convert %s -channel alpha -threshold 50%% %s", filename, filename)) command(string.format("convert %s -channel alpha -threshold 50%% %s", texture_file, texture_file))
end
local function process_font(font)
print(string.format("Processing font \"%s\" (%s)", font.label, font.name)
font.by_width = {} -- Codepoints by tile width
font.tile_widths = {} -- Used tile widths
font.glyph_widths = {} -- Exact width of reach glyph
font.glyphs_height = 0 -- Max height of all glyphs
print("Read available glyphs")
-- Available codepoints from file
font.cp = read_available_codepoints(font.file)
print("Compute glyphs properties")
-- Special char: unknown char
-- We use size of glyph "0" (rounded) but it would be better to get size from ttx
-- TODO: We could get information from ttx:
-- <mtx> gives a width always divisible by 125 for metro font (check if its somehow proportional to what magick gives)
local w = tile_width(measure(font, 0x0030))
font.glyph_widths[0] = w
font.by_width[w] = { 0 }
font.tile_widths = { w }
-- Mandatory codepoints (ASCII)
add_codepoints(font, 0x0021, 0x007f)
-- Extra codepoints
if font.codepoints then
for _, range in ipairs(font.codepoints) do
add_codepoints(font, range.from, range.to)
end
end
print("Create final texture")
make_final_texture(font)
-- Add invisible chars : Spaces
-- TODO: Should be computed from ttx
-- TODO: manage half/quater spaces
glyph_widths[0x0020] = glyph_widths[0x0030]
end end
print("Compute glyphs properties") local function get_font_registration_lua(font)
-- TODO: We could get information from ttx: local glyphs = ""
-- <mtx> gives a width always divisible by 125 for metro font (check if its somehow proportional to what magick gives) local curlinesize = 1000
--
-- Special char: unknown char for codepoint, w in pairs(glyph_widths) do
-- We use size of glyph "0" (rounded) but it would be better to get size from ttx local glyph
local w = tile_width(measure(0x0030)) local x = glyph_xs[codepoint]
glyph_widths[0] = w local y = glyph_ys[codepoint]
by_width[w] = { 0 } local n = glyph_ns[codepoint]
tile_widths = { w } if x ~= nil and y ~=nil and n ~= nil then
glyph = string.format("[%d] = { %d, %d, %d, %d },", codepoint, w, n, x, y)
else
glyph = string.format("[%d] = { %d },", codepoint, w)
end
-- Mandatory chars curlinesize = curlinesize + glyph:len() + 1
add_codepoints(0x0021, 0x007f) if curlinesize > 80 then
glyphs = glyphs + "\n\t\t\t" + glyph
curlinesize = 12 + glyph:len()
else
glyphs = glyphs + " " + glyph
end
end
-- TODO: manage Space without texture! + half/quater spaces return string.format([[
-- Font generated from file %s with pointsize %d
-- Optional Unicode pages (see https://en.wikipedia.org/wiki/Unicode) :
-- 00a0-00ff Latin-1 Supplement (full)
add_codepoints(0x00a0, 0x00ff)
-- 0100-017f Latin Extended-A (full)
--add_codepoints(0x0100, 0x017f)
-- 0370-03ff Greek (full)
--add_codepoints(0x0370, 0x03ff)
-- 0400-04ff Cyrilic (full)
--add_codepoints(0x0400, 0x04ff)
-- 2000-206f General Punctuation (Limited to Dashes)
--add_codepoints(0x2010, 0x2015)
-- 2000-206f General Punctuation (Limited to Quotes)
--add_codepoints(0x2018, 0x201F)
-- 20a0-20cf Currency Symbols (Limited to Euro symbol)
--add_codepoints(0x20ac, 0x20ac)
print("Prepare final texture")
make_final_texture(moddir .. "/textures/font_" .. modname .. ".png")
-- Invisible chars : Spaces -- Should be computed from ttx
glyph_widths[0x0020] = glyph_widths[0x0030]
--
-- Write init.lua
--
file = io.open(moddir .. "/init.lua", "w")
file:write(string.format([[
--
-- %s: A '%s' font mod for font_api
--
-- This file was generated by `%s` on %s from file `%s` with size %d.
--
]], modname, fontname, arg[0], os.date("%Y-%m-%d at %H:%M"), fontfile, fontsize
))
file:write(string.format([[
-- luacheck: ignore
font_api.register_font( font_api.register_font(
'%s', '%s',
{ {
@@ -328,19 +327,41 @@ font_api.register_font(
texture_height = %d, texture_height = %d,
glyphs_height = %d, glyphs_height = %d,
glyphs = { glyphs = {
]], %s
fontname, texture_height, font_height) }
) ]], font.file, font.pointsize, font.texture_height, font.glyphd_height, glyphs)
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] = { %d, %d, %d, %d },\n", codepoint, w, n, x, y))
else
file:write(string.format(" [%d] = { %d },\n", codepoint, w))
end
end end
--
-- Main code
--
-- Defaults (TODO)
if not font.label then
font.label = font.name:gsub("^%l", string.upper)
end
for _, font in ipairs(font.fonts) do
process_font(font)
end
-- Write init.lua
file = io.open(mod_dir .. "/init.lua", "w")
file:write(string.format([[
--
-- %s: A font mod for font_api
--
-- This file was generated by `%s` on %s.
--
]], params.mod_name, arg[0], os.date("%Y-%m-%d at %H:%M")
))
for _, font in ipairs(font.fonts) do
file:write(get_font_registration_lua(font))
end
file:write([[ file:write([[
} }
} }
@@ -348,19 +369,17 @@ file:write([[
]]) ]])
file:close() file:close()
-- --
-- Write mod.conf -- Write mod.conf
-- --
local fontlabel = fontname:gsub("^%l", string.upper)
file = io.open(moddir .. "/mod.conf", "w") file = io.open(mod_dir .. "/mod.conf", "w")
file:write(string.format([[ file:write(string.format([[
name = font_%s name = %s
title = %s Font title = %s
description = %s font for font_api description = %s
depends = font_api depends = font_api
]], fontname, fontlabel, fontlabel)) ]], params.mod_name, params.mod_title, params.mod_description))

View File

@@ -0,0 +1,83 @@
-- This is an example parameter file for make_font.lua
-- Copy this file as params.lua.
-- Replace values between brakets <> to your choices.
-- Launch make_font.lua params.lua
params = {
-- Resulting mod name (required)
-- As this name will be use as texture prefix and so repeated many times,
-- please avoid long names but keep explicit anyway.
mod_name = "<your mod name>",
-- If only one font, have font in title, like "xxx font"
mod_title = "<your mod title>",
-- A good description would be "... fonts for font_api"
mod_descriptiion = "<your mod description>",
-- List of fons to include to the mod.
fonts = {
{
-- Registered font name (required)
-- As this name will be use as texture prefix and so repeated many times,
-- avoid long names. A good name would be a single world all lowercase.
name = "<your font technical name>",
-- Registered font label (optional, default capitalized name)
-- This is the display name for this font. No need to be concise.
label = "<your font display label>",
-- True type font file to get glyphs from (required)
file = "<your font true type font>",
-- Render pointsize (integer, required)
-- Try to find a proper value for a good rendering
pointsize = <proper rendering height>,
-- Shoud chars be trimmed? (boolean, required)
-- Set it to true to reduce texture size
-- and increase `char_spacing` accordingly.
-- If results are weird, you may try to set it to false.
trim = true,
-- Margin added on top of text textures with this font (integer, optional, default 0)
margin_top = 3,
-- Space between consecutive lines (integer, optional, default 0)
-- Space may be negative to make lines closer.
line_spacing = -2,
-- Space between consecutive chars (integer, optional, default 0)
char_spacing = 2,
-- Extra codepoints to include to font mod (optional, default none)
-- Codepoints from 0x0020 to 0x007f (ASCII) are always included.
-- Codepoint 0x0020 is always considered as a space.
-- Codepoints not existing in font file will be ignored.
-- Refer to https://en.wikipedia.org/wiki/Unicode
codepoints = {
-- 00a0-00ff Latin-1 Supplement (full)
{ from=0x00a0, to=0x00ff },
-- 0100-017f Latin Extended-A (full)
{ from=0x0100, 0x017f },
-- 0370-03ff Greek (full)
{ from=0x0370, 0x03ff },
-- 0400-04ff Cyrilic (full)
{ from=0x0400, 0x04ff },
-- 2000-206f General Punctuation (Limited to Dashes)
{ from=0x2010, 0x2015 },
-- 2000-206f General Punctuation (Limited to Quotes)
{ from=0x2018, 0x201F },
-- 20a0-20cf Currency Symbols (Limited to Euro symbol)
{ from=0x20ac, 0x20ac },
},
}
}
}

View File

@@ -0,0 +1,5 @@
The FontStruction “Metro Sans”
(https://fontstruct.com/fontstructions/show/723864) by Christian Munk is
licensed under a Creative Commons Attribution Share Alike license
(http://creativecommons.org/licenses/by-sa/3.0/).
[ancestry]

Binary file not shown.

View File

@@ -0,0 +1,16 @@
The font file in this archive was created using Fontstruct the free, online
font-building tool.
This font was created by Christian Munk.
This font has a homepage where this archive and other versions may be found:
https://fontstruct.com/fontstructions/show/723864
[ancestry]
Try Fontstruct at https://fontstruct.com
Its easy and its fun.
Fontstruct is copyright ©2012-2025 Rob Meek
LEGAL NOTICE:
In using this font you must comply with the licensing terms described in the
file “license.txt” included with this archive.
If you redistribute the font file in this archive, it must be accompanied by all
the other files from this archive, including this one.