using System.Collections.Generic; using AcDream.App.UI; using DatReaderWriter.Types; namespace AcDream.App.Tests.UI; /// /// Pure pen-advance / MeasureWidth math for the retail dat font (no GL, no dat). /// The advance per glyph is the retail /// HorizontalOffsetBefore + Width + HorizontalOffsetAfter /// (SurfaceWindow::DrawCharacter, acclient 0x00442c3a), accumulated across the /// string the way the retail string loop does (0x00467ed4 edi_3 += var_98). /// public class UiDatFontTests { private static FontCharDesc Glyph( ushort unicode, byte width, sbyte before = 0, sbyte after = 0, ushort offsetX = 0, ushort offsetY = 0, byte height = 16, sbyte vBefore = 0) => new() { Unicode = unicode, Width = width, Height = height, OffsetX = offsetX, OffsetY = offsetY, HorizontalOffsetBefore = before, HorizontalOffsetAfter = after, VerticalOffsetBefore = vBefore, }; [Fact] public void GlyphAdvance_SumsBeforeWidthAfter() { var g = Glyph('A', width: 8, before: 1, after: 2); Assert.Equal(11f, UiDatFont.GlyphAdvance(g)); } [Fact] public void GlyphAdvance_HandlesNegativeBearings() { // Kerned glyph: a negative left-bearing pulls it leftward; the advance // still nets out to before + width + after. var g = Glyph('j', width: 4, before: -1, after: 0); Assert.Equal(3f, UiDatFont.GlyphAdvance(g)); } [Fact] public void MeasureWidth_SumsEachGlyphAdvance() { var table = new Dictionary { ['2'] = Glyph('2', width: 7, before: 1, after: 1), // advance 9 ['9'] = Glyph('9', width: 7, before: 1, after: 1), // advance 9 ['1'] = Glyph('1', width: 3, before: 2, after: 1), // advance 6 ['/'] = Glyph('/', width: 4, before: 0, after: 1), // advance 5 }; FontCharDesc? Lookup(char c) => table.TryGetValue(c, out var g) ? g : null; // "291/291" = 9 + 9 + 6 + 5 + 9 + 9 + 6 = 53 Assert.Equal(53f, UiDatFont.MeasureWidth("291/291", Lookup)); } [Fact] public void MeasureWidth_SkipsCharactersNotInFont() { var table = new Dictionary { ['5'] = Glyph('5', width: 6, before: 1, after: 1), // advance 8 }; FontCharDesc? Lookup(char c) => table.TryGetValue(c, out var g) ? g : null; // 'X' has no glyph → contributes nothing; only the two '5's count. Assert.Equal(16f, UiDatFont.MeasureWidth("5X5", Lookup)); } [Fact] public void MeasureWidth_EmptyOrNullIsZero() { FontCharDesc? Lookup(char c) => null; Assert.Equal(0f, UiDatFont.MeasureWidth("", Lookup)); Assert.Equal(0f, UiDatFont.MeasureWidth(null, Lookup)); } }