airutils/text.lua

206 lines
5.7 KiB
Lua
Raw Normal View History

2024-02-12 19:41:23 -03:00
--[[
License for code: LGPL 3.0
see at: https://www.gnu.org/licenses/lgpl-3.0.txt
This code was adapted from signs_lib from VanessaE
the original lib can be found at: https://content.minetest.net/packages/mt-mods/signs_lib/
]]--
-- CONSTANTS
-- Path to the textures.
local TP = signs_lib.path .. "/textures"
-- Font file formatter
local CHAR_FILE = "%s_%02x.png"
-- Fonts path
local CHAR_PATH = TP .. "/" .. CHAR_FILE
-- Initialize character texture cache
local ctexcache = {}
local function fill_line(x, y, w, c, font_size, colorbgw)
c = c or "0"
local tex = { }
for xx = 0, math.max(0, w), colorbgw do
table.insert(tex, (":%d,%d=signs_lib_color_"..font_size.."px_%s.png"):format(x + xx, y, c))
end
return table.concat(tex)
end
-- check if a file does exist
-- to avoid reopening file after checking again
-- pass TRUE as second argument
local function file_exists(name, return_handle, mode)
mode = mode or "r";
local f = io.open(name, mode)
if f ~= nil then
if (return_handle) then
return f
end
io.close(f)
return true
else
return false
end
end
-- make char texture file name
-- if texture file does not exist use fallback texture instead
local function char_tex(font_name, ch)
if ctexcache[font_name..ch] then
return ctexcache[font_name..ch], true
else
local c = ch:byte()
local exists, tex = file_exists(CHAR_PATH:format(font_name, c))
if exists and c ~= 14 then
tex = CHAR_FILE:format(font_name, c)
else
tex = CHAR_FILE:format(font_name, 0x0)
end
ctexcache[font_name..ch] = tex
return tex, exists
end
end
local function make_text_texture(text, default_color, line_width, line_height, cwidth_tab, font_size, colorbgw)
local split = signs_lib.split_lines_and_words
local width = 0
local maxw = 0
local font_name = "signs_lib_font_"..font_size.."px"
local text_ansi = Utf8ToAnsi(text)
local text_splited = split(text_ansi)[1]
local words = { }
default_color = default_color or 0
local cur_color = tonumber(default_color, 16)
-- We check which chars are available here.
for word_i, word in ipairs(text_splited) do
local chars = { }
local ch_offs = 0
word = string.gsub(word, "%^[12345678abcdefgh]", {
["^1"] = string.char(0x81),
["^2"] = string.char(0x82),
["^3"] = string.char(0x83),
["^4"] = string.char(0x84),
["^5"] = string.char(0x85),
["^6"] = string.char(0x86),
["^7"] = string.char(0x87),
["^8"] = string.char(0x88),
["^a"] = string.char(0x8a),
["^b"] = string.char(0x8b),
["^c"] = string.char(0x8c),
["^d"] = string.char(0x8d),
["^e"] = string.char(0x8e),
["^f"] = string.char(0x8f),
["^g"] = string.char(0x90),
["^h"] = string.char(0x91)
})
local word_l = #word
local i = 1
while i <= word_l do
local c = word:sub(i, i)
if c == "#" then
local cc = tonumber(word:sub(i+1, i+1), 16)
if cc then
i = i + 1
cur_color = cc
end
else
local w = cwidth_tab[c]
if w then
width = width + w + 1
if width >= (line_width - cwidth_tab[" "]) then
width = 0
else
maxw = math.max(width, maxw)
end
local max_input_chars = 20
if #chars < max_input_chars then
table.insert(chars, {
off = ch_offs,
tex = char_tex(font_name, c),
col = ("%X"):format(cur_color),
})
end
ch_offs = ch_offs + w
end
end
i = i + 1
end
width = width + cwidth_tab[" "] + 1
maxw = math.max(width, maxw)
table.insert(words, { chars=chars, w=ch_offs })
end
-- Okay, we actually build the "line texture" here.
local texture = { }
local start_xpos = math.floor((line_width - maxw) / 2)
local xpos = start_xpos
local ypos = line_height
cur_color = nil
for word_i, word in ipairs(words) do
local xoffs = (xpos - start_xpos)
if (xoffs > 0) and ((xoffs + word.w) > maxw) then
table.insert(texture, fill_line(xpos, ypos, maxw, "n", font_size, colorbgw))
xpos = start_xpos
ypos = ypos + line_height
table.insert(texture, fill_line(xpos, ypos, maxw, cur_color, font_size, colorbgw))
end
for ch_i, ch in ipairs(word.chars) do
if ch.col ~= cur_color then
cur_color = ch.col
table.insert(texture, fill_line(xpos + ch.off, ypos, maxw, cur_color, font_size, colorbgw))
end
table.insert(texture, (":%d,%d=%s"):format(xpos + ch.off, ypos, ch.tex))
end
table.insert(
texture,
(":%d,%d="):format(xpos + word.w, ypos) .. char_tex(font_name, " ")
)
xpos = xpos + word.w + cwidth_tab[" "]
if xpos >= (line_width + cwidth_tab[" "]) then break end
end
table.insert(texture, fill_line(xpos, ypos, maxw, "n", font_size, colorbgw))
table.insert(texture, fill_line(start_xpos, ypos + line_height, maxw, "n", font_size, colorbgw))
return table.concat(texture)
end
function airutils.convert_text_to_texture(text, default_color, horizontal_aligment)
default_color = default_color or 0
horizontal_aligment = horizontal_aligment or 0.8
local font_size
local line_width
local line_height
local char_width
local colorbgw
local widemult = 1
text = string.sub(text,1,20)
--[[font_size = 31
line_width = math.floor(signs_lib.avgwidth31 * 20) * (1 * widemult)
line_height = signs_lib.lineheight31
char_width = signs_lib.charwidth31
colorbgw = signs_lib.colorbgw31]]--
font_size = 15
line_width = math.floor(signs_lib.avgwidth15 * 40) * (horizontal_aligment * widemult)
line_height = signs_lib.lineheight15
char_width = signs_lib.charwidth15
colorbgw = signs_lib.colorbgw15
local texture = { ("[combine:%dx%d"):format(line_width, line_height) }
local linetex = make_text_texture(text, default_color, line_width, line_height, char_width, font_size, colorbgw)
table.insert(texture, linetex)
table.insert(texture, "^[makealpha:0,0,0")
return table.concat(texture, "")
end