using System.Collections.Generic; using System.Linq; using System.Reflection; using Azimuth; using Glass.UnitTests.Materials; using UnitTestSharp; using Prism; namespace Glass.UnitTests { public class TextMaterialStyleTests : TestFixture { /// /// Lines 4 high. /// public static TextMaterialStyle WithFont() => new TextMaterialStyle { Font = TextMaterialTests.SharedMonospaceFont }; public class MultilineTests : TestFixture { public void DefaultsToUnlimited() { var style = new TextMaterialStyle(); CheckTrue(style.Multiline); CheckNull(style.MaxLines); } public void False_SetsMaxLinesToOne() { CheckEqual(1, new TextMaterialStyle { Multiline = false }.MaxLines); } public void True_ClearsMaxLines() { CheckNull(new TextMaterialStyle { MaxLines = 5, Multiline = true }.MaxLines); } public void MaxLinesOfOne_ReadsAsNotMultiline() { CheckFalse(new TextMaterialStyle { MaxLines = 1 }.Multiline); } public void MaxLinesGreaterThanOne_ReadsAsMultiline() { CheckTrue(new TextMaterialStyle { MaxLines = 3 }.Multiline); } public void SettingBoth_TheOneWrittenLastWins() { var multilineThenMaxLines = new TextMaterialStyle { Multiline = false, MaxLines = 5 }; CheckEqual(5, multilineThenMaxLines.MaxLines); CheckTrue(multilineThenMaxLines.Multiline); var maxLinesThenMultiline = new TextMaterialStyle { MaxLines = 5, Multiline = false }; CheckEqual(1, maxLinesThenMultiline.MaxLines); CheckFalse(maxLinesThenMultiline.Multiline); } } public class VerticalMarginTests : TestFixture { public void Unset_IsAQuarterOfTheFontsLineHeight() { CheckEqual((Scalar)1, WithFont().VerticalMargin); } public void UnsetWithoutAFont_IsZero() { CheckEqual((Scalar)0, new TextMaterialStyle().VerticalMargin); } public void Set_IsWhatWasSet() { CheckEqual((Scalar)7, (WithFont() with { VerticalMargin = 7 }).VerticalMargin); } } public class HorizontalMarginTests : TestFixture { public void Unset_IsHalfTheFontsLineHeight() { CheckEqual((Scalar)2, WithFont().HorizontalMargin); } public void UnsetWithoutAFont_IsZero() { CheckEqual((Scalar)0, new TextMaterialStyle().HorizontalMargin); } public void Set_IsWhatWasSet() { CheckEqual((Scalar)7, (WithFont() with { HorizontalMargin = 7 }).HorizontalMargin); } } public class ScaleTests : TestFixture { public void DefaultsToOne() { CheckEqual((Scalar)1, new TextMaterialStyle().Scale); } public void Set_IsWhatWasSet() { CheckEqual((Scalar)3, new TextMaterialStyle { Scale = 3 }.Scale); } public void SetToOne_EqualsOneThatWasNeverSet() { CheckEqual(new TextMaterialStyle(), new TextMaterialStyle { Scale = 1 }); } } public class LookTests : TestFixture { public void DefaultsToNothingSet() { CheckEqual(default(TextStyle), new TextMaterialStyle().Look); } public void IndividualProperties_AreWrittenIntoIt() { SpriteFontDefinition font = TextMaterialTests.SharedMonospaceFont; var texture = new FakeTexture(); var style = new TextMaterialStyle { Font = font, TintColor = Colors.Red, TintTexture = texture, CoverageGamma = 2, Scale = 3, }; CheckEqual( new TextStyle { Font = font, TintColor = Colors.Red, TintTexture = texture, CoverageGamma = 2, Scale = 3, }, style.Look); } public void WrittenWhole_IsReadBackThroughTheIndividualProperties() { SpriteFontDefinition font = TextMaterialTests.SharedMonospaceFont; var texture = new FakeTexture(); var style = new TextMaterialStyle { Look = new TextStyle { Font = font, TintColor = Colors.Red, TintTexture = texture, CoverageGamma = 2, Scale = 3, }, }; CheckTrue(ReferenceEquals(font, style.Font)); CheckEqual((Color?)Colors.Red, style.TintColor); CheckTrue(ReferenceEquals(texture, style.TintTexture)); CheckEqual((Scalar?)2, style.CoverageGamma); CheckEqual((Scalar)3, style.Scale); } public void TintTransformAndSpace_ReadAndWriteTheLook() { var transform = AffineMatrix.BuildFromTranslation(new Vector(3, 4)); TextMaterialStyle style = WithFont() with { TintTransform = transform, TintSpace = TintSpace.Model }; CheckEqual((AffineMatrix?)transform, style.TintTransform); CheckEqual((TintSpace?)TintSpace.Model, style.TintSpace); CheckEqual(new TextStyle { Font = style.Font, TintTransform = transform, TintSpace = TintSpace.Model }, style.Look); } public void SettingOneIndividualProperty_LeavesTheRestOfTheLook() { TextMaterialStyle style = WithFont() with { Scale = 3 }; CheckTrue(ReferenceEquals(TextMaterialTests.SharedMonospaceFont, style.Font)); } public void SettingTheLookOnACopy_ReplacesTheWholeLook() { TextMaterialStyle style = WithFont() with { Look = new TextStyle { Scale = 3 } }; CheckNull(style.Font); CheckEqual((Scalar)3, style.Scale); } public void SettingTheLookOnACopy_LeavesTheLayoutAlone() { TextMaterialStyle style = WithFont() with { MaxLines = 2 }; CheckEqual(2, (style with { Look = default }).MaxLines); } } public class SingleLineHeightTests : TestFixture { public void WithAFont_IsTheLineHeightPlusBothVerticalMargins() { CheckEqual((Scalar)6, WithFont().SingleLineHeight); } public void ASetMargin_ReplacesTheDefaultOne() { CheckEqual((Scalar)18, (WithFont() with { VerticalMargin = 7 }).SingleLineHeight); } public void Scaled_ScalesTheMarginsToo() { CheckEqual((Scalar)12, (WithFont() with { Scale = 2 }).SingleLineHeight); } public void WithoutAFont_IsJustTheMargins() { CheckEqual((Scalar)10, new TextMaterialStyle { VerticalMargin = 5 }.SingleLineHeight); } public void WithoutAFontOrMargin_IsZero() { CheckEqual((Scalar)0, new TextMaterialStyle().SingleLineHeight); } } public class VerticalAlignmentTests : TestFixture { public void DefaultsToTop() { CheckEqual(Alignment.Vertical.Top, new TextMaterialStyle().VerticalAlignment); } } public class HorizontalAlignmentTests : TestFixture { public void DefaultsToLeft() { CheckEqual(Alignment.Horizontal.Left, new TextMaterialStyle().HorizontalAlignment); } } public class OverflowBehaviorTests : TestFixture { public void DefaultsToClip() { CheckEqual(TextOverflow.Clip, new TextMaterialStyle().OverflowBehavior); } } public class TrailingSpacesTests : TestFixture { public void DefaultsToHang() { CheckEqual(Glass.Typesetting.TrailingSpaceMode.Hang, new TextMaterialStyle().TrailingSpaces); } } public class EqualityTests : TestFixture { public void SeparatelyBuiltWithTheSameSettings_AreEqual() { SpriteFontDefinition font = TextMaterialTests.SharedMonospaceFont; CheckEqual(new TextMaterialStyle { Font = font, Scale = 2 }, new TextMaterialStyle { Font = font, Scale = 2 }); } public void DifferingInAnySetting_AreNotEqual() { SpriteFontDefinition font = TextMaterialTests.SharedMonospaceFont; CheckNotEqual(new TextMaterialStyle { Font = font, Scale = 2 }, new TextMaterialStyle { Font = font, Scale = 3 }); } } public class LaysOutLikeTests : TestFixture { public void DifferingOnlyInColorTextureGammaAndStrikethrough_IsTrue() { TextMaterialStyle style = WithFont(); TextMaterialStyle recolored = style with { TintColor = Colors.Red, TintTexture = new FakeTexture(), TintTransform = AffineMatrix.BuildFromTranslation(new Vector(3, 4)), TintSpace = TintSpace.Model, CoverageGamma = 2, Strikethrough = true, }; CheckTrue(recolored.LaysOutLike(style)); } public void DifferingInAnyLayoutSetting_IsFalse() { TextMaterialStyle style = WithFont(); var variants = new Dictionary { [nameof(TextMaterialStyle.Font)] = style with { Font = TextMaterialTests.CreateMonospaceTestFont(3, 4) }, [nameof(TextMaterialStyle.VerticalAlignment)] = style with { VerticalAlignment = Alignment.Vertical.Center }, [nameof(TextMaterialStyle.HorizontalAlignment)] = style with { HorizontalAlignment = Alignment.Horizontal.Right }, [nameof(TextMaterialStyle.VerticalMargin)] = style with { VerticalMargin = 7 }, [nameof(TextMaterialStyle.HorizontalMargin)] = style with { HorizontalMargin = 7 }, [nameof(TextMaterialStyle.MaxLines)] = style with { MaxLines = 2 }, [nameof(TextMaterialStyle.OverflowBehavior)] = style with { OverflowBehavior = TextOverflow.Ellipsis }, [nameof(TextMaterialStyle.TrailingSpaces)] = style with { TrailingSpaces = Glass.Typesetting.TrailingSpaceMode.Wrap }, [nameof(TextMaterialStyle.Scale)] = style with { Scale = 2 }, }; CheckEqual(new string[0], variants.Where(variant => variant.Value.LaysOutLike(style)).Select(variant => variant.Key)); } public void AMarginSetToTheFontsDefault_IsTrue() { TextMaterialStyle style = WithFont(); CheckTrue((style with { VerticalMargin = style.VerticalMargin }).LaysOutLike(style)); } /// /// LaysOutLike lists its fields by hand, so a property added to TextMaterialStyle has to be sorted into one /// list or the other here before this passes. /// public void EveryProperty_IsEitherLayoutOrAppearance() { string[] layout = { "Font", "VerticalAlignment", "HorizontalAlignment", "VerticalMargin", "HorizontalMargin", "MaxLines", "OverflowBehavior", "TrailingSpaces", "Scale", }; string[] appearanceOrDerived = { "TintColor", "TintTexture", "TintTransform", "TintSpace", "CoverageGamma", "Strikethrough", "Multiline", "SingleLineHeight", "Look", }; IEnumerable properties = typeof(TextMaterialStyle) .GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(property => property.Name); CheckEqual(layout.Concat(appearanceOrDerived).OrderBy(name => name), properties.OrderBy(name => name)); } public static readonly TextMaterialStyle AllocationStyle = WithFont(); public static readonly TextMaterialStyle AllocationRecolored = AllocationStyle with { TintColor = Colors.Red }; [AllocationTest] public void AllocatesNothing() { bool laysOutLike = AllocationRecolored.LaysOutLike(AllocationStyle); CheckNoAllocations(); CheckTrue(laysOutLike); } } public class FakeTexture : ITexture { public Point Size => default; } public class MaxLayoutHeightTests : TestFixture { public void MultilineClipping_ClampsToWhatWasOffered() { CheckEqual((Scalar)100, WithFont().MaxLayoutHeight(100)); } public void MultilineEllipsis_ClampsToTheSameHeightAsClipping() { TextMaterialStyle style = WithFont() with { OverflowBehavior = TextOverflow.Ellipsis }; CheckEqual((Scalar)100, style.MaxLayoutHeight(100)); } public void SingleLine_ClampsToOneLineOfTheFontEvenWhenClipping() { CheckEqual((Scalar)4, (WithFont() with { Multiline = false }).MaxLayoutHeight(100)); } public void SingleLineWithoutAFont_FallsBackToWhatWasOffered() { CheckEqual((Scalar)100, new TextMaterialStyle { Multiline = false }.MaxLayoutHeight(100)); } } } }