engine: pin retained glyph text contract

This commit is contained in:
gamer147
2026-07-30 18:05:43 -04:00
parent 74d6509e3d
commit 41001f6f77
9 changed files with 227 additions and 35 deletions

View File

@@ -0,0 +1,55 @@
using Age.Engine.Model;
public class AdvRetainedTextContractTests
{
[Fact]
public void GlyphRecordUsesNativeEdgesAndExactChainFlag()
{
var chained = new AdvRetainedGlyphRecord(1, 10, 20, 34, 51);
var nonChained = chained with { PublicationChainFlag = 2 };
Assert.Equal((24, 31), (chained.Width, chained.Height));
Assert.True(chained.PublishesNextInSameTick);
Assert.False(nonChained.PublishesNextInSameTick);
}
[Fact]
public void OverflowComparisonsAreStrictAndIndependentPerAxis()
{
Assert.Equal(
AdvTextOverflowFlags.None,
AdvRetainedTextContract.CheckOverflow(100, 50, 100, 50));
Assert.Equal(
AdvTextOverflowFlags.Horizontal,
AdvRetainedTextContract.CheckOverflow(100, 50, 101, 50));
Assert.Equal(
AdvTextOverflowFlags.Vertical,
AdvRetainedTextContract.CheckOverflow(100, 50, 100, 51));
Assert.Equal(
AdvTextOverflowFlags.Horizontal | AdvTextOverflowFlags.Vertical,
AdvRetainedTextContract.CheckOverflow(100, 50, 101, 51));
}
[Theory]
[InlineData(0x8141)] // 、
[InlineData(0x8142)] // 。
[InlineData(0x8176)] // 」
public void NativeClosingPunctuationPreventsHorizontalWrapBefore(int cp932)
=> Assert.True(AdvRetainedTextContract.PreventsHorizontalWrapBefore((ushort)cp932));
[Fact]
public void OtherCp932GlyphsMayWrapNormally()
{
Assert.False(AdvRetainedTextContract.PreventsHorizontalWrapBefore(0x8140)); // full-width space
Assert.False(AdvRetainedTextContract.PreventsHorizontalWrapBefore(0x82a0)); // あ
}
[Fact]
public void TimedPublicationStopsAtConfiguredObjectCapacity()
{
Assert.True(AdvRetainedTextContract.TimedPublicationHandleExists(0, 500));
Assert.True(AdvRetainedTextContract.TimedPublicationHandleExists(499, 500));
Assert.False(AdvRetainedTextContract.TimedPublicationHandleExists(500, 500));
Assert.False(AdvRetainedTextContract.TimedPublicationHandleExists(-1, 500));
}
}

View File

@@ -289,6 +289,12 @@ public class AdvTextOpsTests
Assert.Equal((10, 10, 250, 368), CursorAndBounds(history.GetLayoutSnapshot(9)));
Assert.Equal(new[] { 1 }, history.LayoutsCoveredByTextObjectErase(0xd6d8, 0x1f4));
Assert.Equal(new[] { 7 }, history.LayoutsCoveredByTextObjectErase(0x7d0, 0x1f4));
Assert.All(Enumerable.Range(1, 9), slot =>
{
AdvTextLayoutPresentationBinding binding = history.GetPresentationBinding(slot);
Assert.Equal(slot + 0x14, binding.SourceSurfaceSlot);
Assert.Equal(0x1f4, binding.ObjectCapacity);
});
static (int X, int Y, int Right, int Bottom) CursorAndBounds(AdvTextLayoutSnapshot layout)
=> (layout.CursorX, layout.CursorY, layout.Right, layout.Bottom);

View File

@@ -92,6 +92,34 @@ public class NativeNumberedSaveCodecTests
Assert.Equal(AdvTextHistoryRecordKind.Metadata, restored.Records[1].Kind);
}
[Fact]
public void HistoryTailRestorePreservesInitializedLiveLayoutBindings()
{
var savedHistory = new AdvTextHistory();
savedHistory.DefineLayout(1, 400, 120, 75, 340);
savedHistory.AppendText(1, 0x123, "保存履歴", AdvTextStyle.Default);
var liveHistory = new AdvTextHistory();
liveHistory.DefineLayout(3, 320, 90, 20, 400);
liveHistory.SetResetCursor(3, 45, 42);
liveHistory.SetBounds(3, 300, 80);
liveHistory.SetWaitIndicatorObjectHandle(3, 0x1234);
liveHistory.SetTextObjectRange(3, 0x2000, 500);
NativeTextHistoryCodec.DecodeInto(NativeTextHistoryCodec.Encode(savedHistory), liveHistory);
Assert.Equal(savedHistory.Entries, liveHistory.Entries);
Assert.Equal(savedHistory.Records.Select(record => record.Text),
liveHistory.Records.Select(record => record.Text));
Assert.Equal(3, liveHistory.CurrentLayoutSlot);
Assert.Equal(
new AdvTextLayoutSnapshot(3, 320, 90, 20, 400, 0, 0, 300, 80),
liveHistory.GetLayoutSnapshot(3));
Assert.Equal(
new AdvTextLayoutPresentationBinding(3, 0x17, 0x2000, 500, 0x1234),
liveHistory.GetPresentationBinding(3));
}
[Fact]
public void DirectoryStorePreservesHistoryTailAfterNativeContainer()
{