fix(battle): advance the message box pen by glyph width for TTF fonts

The battle message box laid its glyphs on a fixed 8px grid, in both the
classic layout (BattleState:drawTextArea) and the wide one (WideBattle's
drawMessageBox). With a mod's TTF font registered, glyphs have their own
advance, so Latin text was spread out and clipped at the box edge and
wider CJK glyphs overlapped. Move the pen by Font.advanceOf, as TextBox
and the text() helper in drawTextArea already do.

Tile pages advance 8px, so nothing changes without a TTF.
This commit is contained in:
Flavio de Lima
2026-09-30 12:07:59 -03:00
parent 370aaf4e1f
commit 9595d86de6
3 changed files with 47 additions and 2 deletions
+5 -1
View File
@@ -6964,8 +6964,12 @@ function BattleState:drawTextArea()
local ys = { 112, 128 }
for li, line in ipairs(self.shown or {}) do
local y = (ys[li] or 128) + off
-- pen by each glyph's own advance, like TextBox: a TTF font is not on
-- the 8px tile grid
local pen = 8
for i = 1, #line do
drawGlyph(line[i], 8 + (i - 1) * 8, y)
drawGlyph(line[i], pen, y)
pen = pen + Font.advanceOf(line[i])
end
end
-- the blinking down arrow ('▼', glyph $EE) while a \v CONT wait
+4 -1
View File
@@ -189,8 +189,11 @@ local function drawMessageBox(battle)
local ys = { 112, 128 }
for li, line in ipairs(battle.shown or {}) do
local y = (ys[li] or 128) + off
-- same pen as BattleState:drawTextArea: per-glyph advance, not 8px cells
local pen = 8
for i = 1, #line do
Font.drawCode(line[i], 8 + (i - 1) * 8, y)
Font.drawCode(line[i], pen, y)
pen = pen + Font.advanceOf(line[i])
end
end
if (battle.msgWaiting or battle.msgPrompt) and battle.frame % 60 < 30 then
+38
View File
@@ -208,6 +208,44 @@ do
T.eq(pens[3].x, 8 + latin * 2, "the ligature tile sits after the TTF pair")
end
-- ------------------------------------------------- so does the battle box
-- the battle message box keeps its own draw loop (classic and wide layout);
-- both have to move the pen the way TextBox does, or a TTF line is spread
-- over the 8px grid and clipped at the box edge
do
local BattleState = require("src.battle.BattleState")
local WideBattle = require("src.battle.WideBattle")
local function battle()
return setmetatable({
phase = "messages", current = {}, frame = 0, fieldCleared = true,
shown = { Font.encode("AB'd") },
bottomUIVisible = function() return true end,
extendedHUD = function() return false end,
drawPicsLayer = function() end,
}, BattleState)
end
local function pensOf(draw)
local pens = {}
local oldDraw = Font.drawCode
Font.drawCode = function(code, x)
if code >= BASE or code == 0xD0 then pens[#pens + 1] = x end
end
local ok, err = pcall(draw)
Font.drawCode = oldDraw
if not ok then error(err, 0) end
return pens
end
local classic = pensOf(function() battle():drawTextArea() end)
T.eq(#classic, 3, "the battle box draws three glyphs for AB'd")
T.eq(classic[2], 8 + latin, "its pen moves by the TTF advance, not 8px")
T.eq(classic[3], 8 + latin * 2, "and the ligature tile follows the pair")
local wide = pensOf(function() WideBattle.draw(battle()) end)
T.eq(#wide, 3, "the wide battle box draws the same three glyphs")
T.eq(wide[2], 8 + latin, "with the same per-glyph pen")
T.eq(wide[3], 8 + latin * 2, "up to the ligature tile")
end
-- ------------------------------------------------- the registry entry
do