From 9595d86de6344a1600e7874b2eaa5059cf3d87ca Mon Sep 17 00:00:00 2001 From: Flavio de Lima Date: Wed, 30 Sep 2026 12:07:59 -0300 Subject: [PATCH] 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. --- src/battle/BattleState.lua | 6 +++++- src/battle/WideBattle.lua | 5 ++++- tests/engine/ttf_font_mode.lua | 38 ++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/battle/BattleState.lua b/src/battle/BattleState.lua index 0b61ea3c..81a7a1f9 100644 --- a/src/battle/BattleState.lua +++ b/src/battle/BattleState.lua @@ -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 diff --git a/src/battle/WideBattle.lua b/src/battle/WideBattle.lua index 14332147..323fe8e9 100644 --- a/src/battle/WideBattle.lua +++ b/src/battle/WideBattle.lua @@ -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 diff --git a/tests/engine/ttf_font_mode.lua b/tests/engine/ttf_font_mode.lua index 351f9a89..f4c9427c 100644 --- a/tests/engine/ttf_font_mode.lua +++ b/tests/engine/ttf_font_mode.lua @@ -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