mirror of
https://github.com/pyrollo/display_modpack.git
synced 2025-10-15 00:35:20 +02:00
wip
This commit is contained in:
@@ -68,37 +68,44 @@ function Font:new(def)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if def.height == nil or def.height <= 0 then
|
local font = table.copy(def)
|
||||||
|
|
||||||
|
if font.height == nil or font.height <= 0 then
|
||||||
minetest.log("error",
|
minetest.log("error",
|
||||||
"[font_api] Font definition must have a positive height.")
|
"[font_api] Font definition must have a positive height.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(def.widths) ~= "table" then
|
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.glyphs) ~= "table" then
|
||||||
minetest.log("error",
|
minetest.log("error",
|
||||||
"[font_api] Font definition must have a widths array.")
|
"[font_api] Font definition must have a `glyphs` array.")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if def.widths[0] == nil then
|
if font.glyphs[0] == nil then
|
||||||
minetest.log("error",
|
minetest.log("error",
|
||||||
"[font_api] Font must have a char with codepoint 0 (=unknown char).")
|
"[font_api] Font must have a char with codepoint 0 (=unknown char).")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local font = table.copy(def)
|
|
||||||
setmetatable(font, self)
|
setmetatable(font, self)
|
||||||
self.__index = 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
|
return font
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -124,7 +131,7 @@ function Font:get_next_char(text)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Fallback mechanism
|
-- Fallback mechanism
|
||||||
if self.widths[codepoint] == nil then
|
if self.glyphs[codepoint] == nil then
|
||||||
local char = text:sub(1, bytes)
|
local char = text:sub(1, bytes)
|
||||||
|
|
||||||
if fallbacks[char] then
|
if fallbacks[char] then
|
||||||
@@ -140,14 +147,32 @@ end
|
|||||||
--- Returns the width of a given char
|
--- Returns the width of a given char
|
||||||
-- @param char : codepoint of the char
|
-- @param char : codepoint of the char
|
||||||
-- @return Char width
|
-- @return Char width
|
||||||
|
|
||||||
function Font:get_char_width(codepoint)
|
function Font:get_char_width(codepoint)
|
||||||
if self.fixedwidth then
|
return (self.glyphs[codepoint] or self.glyphs[0]).w
|
||||||
return self.fixedwidth
|
end
|
||||||
elseif self.widths[codepoint] then
|
|
||||||
return self.widths[codepoint]
|
--- Returns texture for a given glyph
|
||||||
else
|
-- @param glyph: table representing the glyph
|
||||||
return self.widths[0]
|
-- @return Texture
|
||||||
|
|
||||||
|
function Font:get_glyph_texture(glyph)
|
||||||
|
if glyph.c 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 ""
|
||||||
end
|
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)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Text height for multiline text including margins and line spacing
|
--- Text height for multiline text including margins and line spacing
|
||||||
@@ -256,19 +281,23 @@ function Font:render(text, texturew, textureh, style)
|
|||||||
codepoint, l.text = self:get_next_char(l.text)
|
codepoint, l.text = self:get_next_char(l.text)
|
||||||
if codepoint == nil then return '' end -- UTF Error
|
if codepoint == nil then return '' end -- UTF Error
|
||||||
|
|
||||||
|
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 + self.widths[codepoint] >= 0 and x <= texturew then
|
if x + glyph.w >= 0 and x <= texturew then
|
||||||
texture = texture..
|
texture = string.format("%s:%d,%d=%s",
|
||||||
string.format(":%d,%d=font_%s_%04x.png", x, y, self.name, codepoint)
|
texture, x, y, self:get_glyph_texture(glyph):gsub("[\\^:]", "\\%0"))
|
||||||
end
|
end
|
||||||
x = x + self.widths[codepoint]
|
x = x + glyph.w
|
||||||
end
|
end
|
||||||
|
|
||||||
y = y + self:get_height() + (self.linespacing or 0)
|
y = y + self:get_height() + (self.linespacing or 0)
|
||||||
end
|
end
|
||||||
texture = string.format("[combine:%dx%d", texturew, textureh)..texture
|
|
||||||
|
texture = string.format("[combine:%dx%d%s", texturew, textureh, texture)
|
||||||
if style.color then
|
if style.color then
|
||||||
texture = texture.."^[colorize:"..style.color
|
texture = texture.."^[colorize:"..style.color
|
||||||
end
|
end
|
||||||
|
print(texture)
|
||||||
return texture
|
return texture
|
||||||
end
|
end
|
||||||
|
@@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
-- This files generates only code and textures - should not be translated
|
-- This files generates only code and textures - should not be translated
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO : detect and manage fixed width fonts
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Argument management
|
-- Argument management
|
||||||
--
|
--
|
||||||
@@ -52,7 +55,7 @@ end
|
|||||||
--
|
--
|
||||||
|
|
||||||
-- TODO: we should be able to choose basedir
|
-- TODO: we should be able to choose basedir
|
||||||
local moddir = fontname
|
local moddir = "font_" .. fontname
|
||||||
|
|
||||||
if os.execute("[ -d " .. moddir .. " ]") then
|
if os.execute("[ -d " .. moddir .. " ]") then
|
||||||
print ("Directory " .. moddir .. " already exists!")
|
print ("Directory " .. moddir .. " already exists!")
|
||||||
@@ -61,10 +64,44 @@ end
|
|||||||
|
|
||||||
os.execute("mkdir -p " .. moddir .. "/textures")
|
os.execute("mkdir -p " .. moddir .. "/textures")
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
--
|
-- Compute available tile sizes
|
||||||
--
|
--
|
||||||
|
|
||||||
|
local function compute_tile_sizes(texture_size)
|
||||||
|
results = {}
|
||||||
|
for size = 1, texture_size do
|
||||||
|
if texture_size % size == 0 then
|
||||||
|
table.insert(results, size)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This will give enough combinations (720 is 2 * 2 * 2 * 2 * 3 * 3 * 5)
|
||||||
|
tile_widths = compute_tile_sizes(720)
|
||||||
|
|
||||||
|
-- Table width has to be sorted
|
||||||
|
table.sort(tile_widths)
|
||||||
|
texture_width = tile_widths[#tile_widths]
|
||||||
|
|
||||||
|
-- Rounds glyph width up to available tile width (first width larger than given one)
|
||||||
|
local function tile_width(width)
|
||||||
|
for _, w in ipairs(tile_widths) do
|
||||||
|
if width < w then
|
||||||
|
return w
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return texture_width
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Things start here
|
||||||
|
--
|
||||||
|
|
||||||
|
-- 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'))
|
||||||
@@ -72,6 +109,8 @@ local function command(cmd)
|
|||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 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
|
||||||
@@ -108,75 +147,82 @@ while codepoint do
|
|||||||
end
|
end
|
||||||
cmd:close()
|
cmd:close()
|
||||||
|
|
||||||
local bywidth = {} -- Codepoints by glyph width
|
local by_width = {} -- Codepoints by tile width
|
||||||
local widths = {} -- Existing widths
|
local tile_widths = {} -- Existing tile width
|
||||||
local fontheight = 0 -- Max height of all glyphs
|
local glyph_widths = {} -- Exact width of reach glyph
|
||||||
|
local font_height = 0 -- Max height of all glyphs
|
||||||
|
|
||||||
local function add_codepoints(from, to)
|
local function add_codepoints(from, to)
|
||||||
for codepoint = from, to do
|
for codepoint = from, to do
|
||||||
if codepoints[codepoint] then
|
if codepoints[codepoint] then
|
||||||
|
-- Glyph size
|
||||||
local w, h = measure(codepoint)
|
local w, h = measure(codepoint)
|
||||||
if h > fontheight then fontheight = h end
|
if h > font_height then font_height = h end
|
||||||
|
glyph_widths[codepoint] = w
|
||||||
|
|
||||||
if bywidth[w] == nil then
|
-- Tile width
|
||||||
bywidth[w] = {}
|
local tile_w = tile_width(w)
|
||||||
table.insert(widths, w)
|
if by_width[tile_w] == nil then
|
||||||
|
by_width[tile_w] = {}
|
||||||
|
table.insert(tile_widths, tile_w)
|
||||||
end
|
end
|
||||||
|
table.insert(by_width[tile_w], codepoint)
|
||||||
table.insert(bywidth[w], codepoint)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.sort(widths)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local glyphxs = {} -- x (in grid) for each glyph
|
-- Characteristics of [sheet:NxM:x,y
|
||||||
local glyphys = {} -- y (in grid) for each glyph
|
-- M is always the same and depends on font and texture height.
|
||||||
local glyphws = {} -- widths (in pixel) of each glyph
|
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 function make_final_texture(imagewidth, filename)
|
local function make_final_texture(filename)
|
||||||
|
|
||||||
local imageheight = fontheight
|
local texture_height = font_height
|
||||||
|
|
||||||
local x = 0 -- cursor x
|
local x = 0 -- cursor x
|
||||||
local glyphy = 0
|
local glyph_y = 0
|
||||||
|
|
||||||
|
table.sort(tile_widths)
|
||||||
|
|
||||||
-- Compute positions
|
-- Compute positions
|
||||||
for _, width in ipairs(widths) do
|
for _, tile_width in ipairs(tile_widths) do
|
||||||
for _, codepoint in ipairs(bywidth[width]) do
|
for _, codepoint in ipairs(by_width[tile_width]) do
|
||||||
local glyphx = math.ceil(x / width)
|
local glyph_x = x // tile_width
|
||||||
x = glyphx * width
|
x = glyph_x * tile_width
|
||||||
if x + width > imagewidth then -- no space left on current line
|
if x + tile_width > texture_width then -- no space left on current line
|
||||||
x = 0
|
x = 0
|
||||||
glyphx = 0
|
glyph_x = 0
|
||||||
glyphy = glyphy + 1
|
glyph_y = glyph_y + 1
|
||||||
imageheight = imageheight + fontheight
|
texture_height = texture_height + font_height
|
||||||
end
|
end
|
||||||
glyphxs[codepoint] = glyphx
|
glyph_xs[codepoint] = glyph_x
|
||||||
glyphys[codepoint] = glyphy
|
glyph_ys[codepoint] = glyph_y
|
||||||
glyphws[codepoint] = width
|
glyph_ns[codepoint] = texture_width // tile_width
|
||||||
x = x + width
|
x = x + tile_width
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Compose texture
|
-- Compose texture
|
||||||
command(string.format(
|
command(string.format(
|
||||||
"convert -channel alpha -colorspace gray -size %dx%d xc:transparent %s",
|
"convert -channel alpha -colorspace gray -size %dx%d xc:transparent %s",
|
||||||
imagewidth, imageheight, filename
|
texture_width, texture_height, filename
|
||||||
))
|
))
|
||||||
|
print(texture_width, texture_height)
|
||||||
|
|
||||||
for codepoint, w in pairs(glyphws) do
|
for codepoint, n in pairs(glyph_ns) do
|
||||||
local x = w * glyphxs[codepoint]
|
local w = texture_width // n
|
||||||
local y = fontheight * glyphys[codepoint]
|
local x = w * glyph_xs[codepoint]
|
||||||
|
local y = font_height * glyph_ys[codepoint]
|
||||||
|
|
||||||
local cmd
|
local cmd
|
||||||
|
|
||||||
-- Subtexture subcommand
|
-- Subtexture subcommand
|
||||||
if codepoint == 0 then
|
if codepoint == 0 then
|
||||||
-- The "unknown" char
|
-- The "unknown" char
|
||||||
cmd = string.format("-size %dx%d xc:transparent -colorspace gray -stroke black -fill transparent -strokewidth 1 -draw \"rectangle 0,0 %d,%d\"",
|
cmd = string.format("xc:transparent[%dx%d] -background none -colorspace gray -stroke black -fill transparent -strokewidth 1 -draw \"rectangle 0,0 %d,%d\"",
|
||||||
w, fontheight, w-1, fontheight-1
|
w, font_height, w - 1, font_height - 1
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
-- Other glyhp chars
|
-- Other glyhp chars
|
||||||
@@ -186,6 +232,7 @@ local function make_final_texture(imagewidth, 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
|
||||||
|
|
||||||
@@ -200,10 +247,11 @@ print("Compute glyphs properties")
|
|||||||
--
|
--
|
||||||
|
|
||||||
-- Special char: unknown char
|
-- Special char: unknown char
|
||||||
-- We use size of glyph "0" but it would be better to get size from ttx
|
-- We use size of glyph "0" (rounded) but it would be better to get size from ttx
|
||||||
local w, _ = measure(0x0030)
|
local w = tile_width(measure(0x0030))
|
||||||
bywidth[w] = { 0 }
|
glyph_widths[0] = w
|
||||||
widths = { w }
|
by_width[w] = { 0 }
|
||||||
|
tile_widths = { w }
|
||||||
|
|
||||||
-- Mandatory chars
|
-- Mandatory chars
|
||||||
add_codepoints(0x0021, 0x007f)
|
add_codepoints(0x0021, 0x007f)
|
||||||
@@ -213,7 +261,7 @@ add_codepoints(0x0021, 0x007f)
|
|||||||
-- Optional Unicode pages (see https://en.wikipedia.org/wiki/Unicode) :
|
-- Optional Unicode pages (see https://en.wikipedia.org/wiki/Unicode) :
|
||||||
|
|
||||||
-- 00a0-00ff Latin-1 Supplement (full)
|
-- 00a0-00ff Latin-1 Supplement (full)
|
||||||
--add_codepoints(0x00a0, 0x00ff)
|
add_codepoints(0x00a0, 0x00ff)
|
||||||
|
|
||||||
-- 0100-017f Latin Extended-A (full)
|
-- 0100-017f Latin Extended-A (full)
|
||||||
--add_codepoints(0x0100, 0x017f)
|
--add_codepoints(0x0100, 0x017f)
|
||||||
@@ -233,14 +281,16 @@ add_codepoints(0x0021, 0x007f)
|
|||||||
-- 20a0-20cf Currency Symbols (Limited to Euro symbol)
|
-- 20a0-20cf Currency Symbols (Limited to Euro symbol)
|
||||||
--add_codepoints(0x20ac, 0x20ac)
|
--add_codepoints(0x20ac, 0x20ac)
|
||||||
|
|
||||||
|
|
||||||
print("Prepare final texture")
|
print("Prepare final texture")
|
||||||
|
|
||||||
make_final_texture(200, moddir .. "/textures/" .. modname .. "_" .. fontname .. ".png")
|
make_final_texture(moddir .. "/textures/font_" .. modname .. ".png")
|
||||||
|
|
||||||
-- Invisible chars : Spaces
|
-- Invisible chars : Spaces -- Should be computed from ttx
|
||||||
glyphws[0x0020] = glyphws[0]
|
glyph_widths[0x0020] = glyph_widths[0x0030]
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Write init.lua
|
||||||
|
--
|
||||||
|
|
||||||
file = io.open(moddir .. "/init.lua", "w")
|
file = io.open(moddir .. "/init.lua", "w")
|
||||||
file:write(string.format([[
|
file:write(string.format([[
|
||||||
@@ -263,13 +313,14 @@ font_api.register_font(
|
|||||||
height = %d,
|
height = %d,
|
||||||
glyphs = {
|
glyphs = {
|
||||||
]],
|
]],
|
||||||
fontname, fontheight)
|
fontname, font_height)
|
||||||
)
|
)
|
||||||
for codepoint, w in pairs(glyphws) do
|
for codepoint, w in pairs(glyph_widths) do
|
||||||
x = glyphxs[codepoint]
|
local x = glyph_xs[codepoint]
|
||||||
y = glyphys[codepoint]
|
local y = glyph_ys[codepoint]
|
||||||
if x ~= nil and y ~=nil then
|
local n = glyph_ns[codepoint]
|
||||||
file:write(string.format(" [%d] = { w = %d, x = %d, y = %d },\n", codepoint, w, x, y))
|
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))
|
||||||
else
|
else
|
||||||
file:write(string.format(" [%d] = { w = %d },\n", codepoint, w))
|
file:write(string.format(" [%d] = { w = %d },\n", codepoint, w))
|
||||||
end
|
end
|
||||||
@@ -280,3 +331,20 @@ file:write([[
|
|||||||
);
|
);
|
||||||
]])
|
]])
|
||||||
file:close()
|
file:close()
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Write mod.conf
|
||||||
|
--
|
||||||
|
|
||||||
|
local fontlabel = fontname:gsub("^%l", string.upper)
|
||||||
|
|
||||||
|
file = io.open(moddir .. "/mod.conf", "w")
|
||||||
|
file:write(string.format([[
|
||||||
|
name = font_%s
|
||||||
|
title = %s Font
|
||||||
|
description = %s font for font_api
|
||||||
|
depends = font_api
|
||||||
|
]], fontname, fontlabel, fontlabel))
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user