using Annulus; using Azimuth; using System; using UnitTestSharp; namespace Glass.UnitTests { public class TextureMaterialTests : TestFixture { public class SizedTexture : ITexture { public SizedTexture(int width, int height) { Size = new Point(width, height); } public Point Size { get; } } public class PreferredSizeTests : TestFixture { public void UnboundedOffer_IsTheTexturesSize() { var material = new TextureMaterial { Texture = new SizedTexture(40, 20) }; CheckEqual(new Vector(40, 20), material.PreferredSize(Constraints.Unbounded)); } public void NoTexture_IsZero() { CheckEqual(Vector.Zero, new TextureMaterial().PreferredSize(Constraints.Unbounded)); } public void TightWidthWithLockedRatio_HeightFollows() { var material = new TextureMaterial { Texture = new SizedTexture(40, 20), LockAspectRatio = true }; CheckEqual(new Vector(10, 5), material.PreferredSize(Constraints.TightWidth(10, 100))); } public void TightWidthWithoutLockedRatio_KeepsTheTexturesHeight() { var material = new TextureMaterial { Texture = new SizedTexture(40, 20) }; CheckEqual(new Vector(10, 20), material.PreferredSize(Constraints.TightWidth(10, 100))); } } public class PlaceWithinTests : TestFixture { public static readonly Rect Wide = Rect.FromPositionAndSize(new Vector(10, 20), new Vector(100, 40)); public static readonly Rect Tall = Rect.FromPositionAndSize(new Vector(0, 0), new Vector(20, 100)); public static TextureMaterial Square( bool locked = false, Tiling across = Tiling.Stretch, Tiling down = Tiling.Stretch, Alignment.Horizontal horizontal = Alignment.Horizontal.Center, Alignment.Vertical vertical = Alignment.Vertical.Center, int width = 10, int height = 10) { return new TextureMaterial { Texture = new SizedTexture(width, height), LockAspectRatio = locked, TilingX = across, TilingY = down, HorizontalAlignment = horizontal, VerticalAlignment = vertical, }; } public static Rect Box(Scalar left, Scalar top, Scalar width, Scalar height) { return Rect.FromPositionAndSize(new Vector(left, top), new Vector(width, height)); } public class DefaultsTests : TestFixture { public void AlignsCenteredBothWays() { var material = new TextureMaterial(); CheckEqual(Alignment.Horizontal.Center, material.HorizontalAlignment); CheckEqual(Alignment.Vertical.Center, material.VerticalAlignment); } public void StretchesAndFillsTheRect() { TextureMaterial.Placement placement = Square().PlaceWithin(Wide); CheckEqual(Wide, placement.Bounds); CheckEqual(1, placement.Scale); CheckEqual(Tiling.Stretch, placement.TilingX); CheckEqual(Tiling.Stretch, placement.TilingY); CheckFalse(placement.Overflows); } } public class DegenerateTests : TestFixture { public void NoTexture_FillsTheRectStretched() { var material = new TextureMaterial { LockAspectRatio = true, TilingX = Tiling.None }; TextureMaterial.Placement placement = material.PlaceWithin(Wide); CheckEqual(Wide, placement.Bounds); CheckEqual(Tiling.Stretch, placement.TilingX); } public void TextureWithNoWidth_FillsTheRectStretched() { TextureMaterial.Placement placement = Square(locked: true, width: 0).PlaceWithin(Wide); CheckEqual(Wide, placement.Bounds); CheckEqual(1, placement.Scale); } public void TextureWithNoHeight_FillsTheRectStretched() { CheckEqual(Wide, Square(locked: true, height: 0).PlaceWithin(Wide).Bounds); } public void RectWithNoWidth_IsReturnedAsIs() { Rect empty = Box(5, 6, 0, 8); CheckEqual(empty, Square(locked: true).PlaceWithin(empty).Bounds); } public void RectWithNoHeight_IsReturnedAsIs() { Rect empty = Box(5, 6, 8, 0); CheckEqual(empty, Square(locked: true).PlaceWithin(empty).Bounds); } public void UnknownTilingAcross_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); Square(across: Tiling.Count).PlaceWithin(Wide); } public void UnknownTilingDown_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); Square(down: (Tiling)99).PlaceWithin(Wide); } } public class UnlockedTests : TestFixture { public void TileBothWays_FillsTheRectWithTiles() { TextureMaterial.Placement placement = Square(across: Tiling.Tile, down: Tiling.Tile).PlaceWithin(Wide); CheckEqual(Wide, placement.Bounds); CheckEqual(1, placement.Scale); CheckEqual(Tiling.Tile, placement.TilingX); CheckEqual(Tiling.Tile, placement.TilingY); } public void StretchAndTileBothWays_FillsTheRectWithStretchedTiles() { TextureMaterial.Placement placement = Square(across: Tiling.StretchAndTile, down: Tiling.StretchAndTile).PlaceWithin(Wide); CheckEqual(Wide, placement.Bounds); CheckEqual(Tiling.StretchAndTile, placement.TilingX); CheckEqual(Tiling.StretchAndTile, placement.TilingY); } public void EachAxisKeepsItsOwnMode() { TextureMaterial.Placement placement = Square(across: Tiling.Tile, down: Tiling.Stretch).PlaceWithin(Wide); CheckEqual(Wide, placement.Bounds); CheckEqual(Tiling.Tile, placement.TilingX); CheckEqual(Tiling.Stretch, placement.TilingY); } public void FillingAxes_IgnoreAlignment() { TextureMaterial material = Square( across: Tiling.Tile, horizontal: Alignment.Horizontal.Right, vertical: Alignment.Vertical.Bottom); CheckEqual(Wide, material.PlaceWithin(Wide).Bounds); } public void NoneAcross_DrawsOneNativeWidthCopyCentered() { TextureMaterial.Placement placement = Square(across: Tiling.None).PlaceWithin(Wide); CheckEqual(Box(55, 20, 10, 40), placement.Bounds); CheckEqual(Tiling.Stretch, placement.TilingX); CheckEqual(Tiling.Stretch, placement.TilingY); } public void NoneAcross_SitsAtTheLeftEdgeWhenAlignedLeft() { TextureMaterial material = Square(across: Tiling.None, horizontal: Alignment.Horizontal.Left); CheckEqual(Box(10, 20, 10, 40), material.PlaceWithin(Wide).Bounds); } public void NoneAcross_SitsAtTheRightEdgeWhenAlignedRight() { TextureMaterial material = Square(across: Tiling.None, horizontal: Alignment.Horizontal.Right); CheckEqual(Box(100, 20, 10, 40), material.PlaceWithin(Wide).Bounds); } public void NoneDown_SitsAtTheTopEdgeWhenAlignedTop() { TextureMaterial material = Square(down: Tiling.None, vertical: Alignment.Vertical.Top); CheckEqual(Box(0, 0, 20, 10), material.PlaceWithin(Tall).Bounds); } public void NoneDown_SitsInTheMiddleWhenAlignedCenter() { CheckEqual(Box(0, 45, 20, 10), Square(down: Tiling.None).PlaceWithin(Tall).Bounds); } public void NoneDown_SitsAtTheBottomEdgeWhenAlignedBottom() { TextureMaterial material = Square(down: Tiling.None, vertical: Alignment.Vertical.Bottom); CheckEqual(Box(0, 90, 20, 10), material.PlaceWithin(Tall).Bounds); } public void NoneBothWays_DrawsOneNativeSizeCopy() { TextureMaterial.Placement placement = Square(across: Tiling.None, down: Tiling.None).PlaceWithin(Wide); CheckEqual(Box(55, 35, 10, 10), placement.Bounds); CheckEqual(1, placement.Scale); CheckFalse(placement.Overflows); } public void NoneFillingTheAxisExactly_DoesNotOverflow() { TextureMaterial.Placement placement = Square(across: Tiling.None, width: 100).PlaceWithin(Wide); CheckEqual(Box(10, 20, 100, 40), placement.Bounds); CheckFalse(placement.Overflows); } public void NoneLargerThanTheRect_OverflowsEvenlyOnBothSides() { TextureMaterial.Placement placement = Square(across: Tiling.None, width: 200).PlaceWithin(Wide); CheckEqual(Box(-40, 20, 200, 40), placement.Bounds); CheckTrue(placement.Overflows); } public void NoneLargerThanTheRect_OverflowsPastTheEdgeAlignedAgainst() { TextureMaterial material = Square( down: Tiling.None, vertical: Alignment.Vertical.Top, height: 300); TextureMaterial.Placement placement = material.PlaceWithin(Tall); CheckEqual(Box(0, 0, 20, 300), placement.Bounds); CheckTrue(placement.Overflows); } } public class LockedBothStretchingTests : TestFixture { public void SquareInWideRect_IsCenteredAtFullHeight() { TextureMaterial.Placement placement = Square(locked: true).PlaceWithin(Wide); CheckEqual(Box(40, 20, 40, 40), placement.Bounds); CheckEqual(4, placement.Scale); CheckEqual(Tiling.Stretch, placement.TilingX); CheckEqual(Tiling.Stretch, placement.TilingY); CheckFalse(placement.Overflows); } public void SquareInTallRect_IsCenteredAtFullWidth() { TextureMaterial.Placement placement = Square(locked: true).PlaceWithin(Tall); CheckEqual(Box(0, 40, 20, 20), placement.Bounds); CheckEqual(2, placement.Scale); } public void MatchingShape_FillsTheRect() { CheckEqual(Wide, Square(locked: true, width: 5, height: 2).PlaceWithin(Wide).Bounds); } public void SmallTexture_IsScaledUpToFit() { TextureMaterial.Placement placement = Square(locked: true, width: 1, height: 1).PlaceWithin(Wide); CheckEqual(40, placement.Bounds.Height); CheckEqual(40, placement.Scale); } public void LargeTexture_IsScaledDownToFit() { TextureMaterial.Placement placement = Square(locked: true, width: 80, height: 80).PlaceWithin(Wide); CheckEqual(40, placement.Bounds.Height); CheckEqual(0.5, placement.Scale); } public void AlignedLeft_SitsAtTheLeftEdge() { TextureMaterial material = Square(locked: true, horizontal: Alignment.Horizontal.Left); CheckEqual(Box(10, 20, 40, 40), material.PlaceWithin(Wide).Bounds); } public void AlignedRight_SitsAtTheRightEdge() { TextureMaterial material = Square(locked: true, horizontal: Alignment.Horizontal.Right); CheckEqual(Box(70, 20, 40, 40), material.PlaceWithin(Wide).Bounds); } public void AlignedTop_SitsAtTheTopEdge() { TextureMaterial material = Square(locked: true, vertical: Alignment.Vertical.Top); CheckEqual(Box(0, 0, 20, 20), material.PlaceWithin(Tall).Bounds); } public void AlignedBottom_SitsAtTheBottomEdge() { TextureMaterial material = Square(locked: true, vertical: Alignment.Vertical.Bottom); CheckEqual(Box(0, 80, 20, 20), material.PlaceWithin(Tall).Bounds); } public void AlignmentOnTheAxisWithNoSlack_ChangesNothing() { TextureMaterial material = Square( locked: true, horizontal: Alignment.Horizontal.Right, vertical: Alignment.Vertical.Bottom); CheckEqual(Box(70, 20, 40, 40), material.PlaceWithin(Wide).Bounds); } } public class LockedOneStretchingTests : TestFixture { public void StretchAcrossTileDown_SizesTilesToTheWidth() { TextureMaterial.Placement placement = Square(locked: true, across: Tiling.Stretch, down: Tiling.Tile).PlaceWithin(Wide); CheckEqual(10, placement.Scale); CheckEqual(Wide, placement.Bounds); CheckEqual(Tiling.Stretch, placement.TilingX); CheckEqual(Tiling.Tile, placement.TilingY); CheckFalse(placement.Overflows); } public void StretchAcrossTileDown_InATallRect_SizesTilesToTheWidth() { TextureMaterial.Placement placement = Square(locked: true, across: Tiling.Stretch, down: Tiling.Tile).PlaceWithin(Tall); CheckEqual(2, placement.Scale); CheckEqual(Tall, placement.Bounds); } public void TileAcrossStretchDown_SizesTilesToTheHeight() { TextureMaterial.Placement placement = Square(locked: true, across: Tiling.Tile, down: Tiling.Stretch).PlaceWithin(Wide); CheckEqual(4, placement.Scale); CheckEqual(Wide, placement.Bounds); CheckEqual(Tiling.Tile, placement.TilingX); CheckEqual(Tiling.Stretch, placement.TilingY); } public void StretchAcrossNoneDown_DrawsOneCopyThatFitsTheWidth() { TextureMaterial.Placement placement = Square(locked: true, across: Tiling.Stretch, down: Tiling.None).PlaceWithin(Tall); CheckEqual(2, placement.Scale); CheckEqual(Box(0, 40, 20, 20), placement.Bounds); CheckFalse(placement.Overflows); } public void StretchAcrossNoneDown_CopyTallerThanTheRect_OverflowsAtTheAlignment() { TextureMaterial centered = Square(locked: true, across: Tiling.Stretch, down: Tiling.None); TextureMaterial top = centered with { VerticalAlignment = Alignment.Vertical.Top }; TextureMaterial bottom = centered with { VerticalAlignment = Alignment.Vertical.Bottom }; CheckEqual(Box(10, -10, 100, 100), centered.PlaceWithin(Wide).Bounds); CheckEqual(Box(10, 20, 100, 100), top.PlaceWithin(Wide).Bounds); CheckEqual(Box(10, -40, 100, 100), bottom.PlaceWithin(Wide).Bounds); CheckTrue(centered.PlaceWithin(Wide).Overflows); } public void StretchAcrossStretchAndTileDown_TilesDownAtTheWidthsScale() { TextureMaterial.Placement placement = Square( locked: true, across: Tiling.Stretch, down: Tiling.StretchAndTile).PlaceWithin(Wide); CheckEqual(10, placement.Scale); CheckEqual(Tiling.Stretch, placement.TilingX); CheckEqual(Tiling.Tile, placement.TilingY); } public void StretchAndTileAcrossStretchDown_TilesAcrossAtTheHeightsScale() { TextureMaterial.Placement placement = Square( locked: true, across: Tiling.StretchAndTile, down: Tiling.Stretch).PlaceWithin(Wide); CheckEqual(4, placement.Scale); CheckEqual(Tiling.Tile, placement.TilingX); CheckEqual(Tiling.Stretch, placement.TilingY); } } public class LockedNeitherStretchingTests : TestFixture { public void TileBothWays_KeepsTheNativeSize() { TextureMaterial.Placement placement = Square(locked: true, across: Tiling.Tile, down: Tiling.Tile).PlaceWithin(Wide); CheckEqual(1, placement.Scale); CheckEqual(Wide, placement.Bounds); CheckEqual(Tiling.Tile, placement.TilingX); CheckEqual(Tiling.Tile, placement.TilingY); } public void NoneBothWays_DrawsOneNativeSizeCopy() { TextureMaterial.Placement placement = Square(locked: true, across: Tiling.None, down: Tiling.None).PlaceWithin(Wide); CheckEqual(1, placement.Scale); CheckEqual(Box(55, 35, 10, 10), placement.Bounds); } public void NoneAcrossTileDown_TilesAColumn() { TextureMaterial.Placement placement = Square(locked: true, across: Tiling.None, down: Tiling.Tile).PlaceWithin(Wide); CheckEqual(Box(55, 20, 10, 40), placement.Bounds); CheckEqual(Tiling.Stretch, placement.TilingX); CheckEqual(Tiling.Tile, placement.TilingY); } public void StretchAndTileAcross_ScalesTilesToFitAWholeNumberAcross() { Rect rect = Box(0, 0, 90, 50); TextureMaterial.Placement placement = Square( locked: true, across: Tiling.StretchAndTile, down: Tiling.Tile, width: 40, height: 40).PlaceWithin(rect); CheckEqual(1.125, placement.Scale); CheckEqual(rect, placement.Bounds); CheckEqual(Tiling.Tile, placement.TilingX); CheckEqual(Tiling.Tile, placement.TilingY); } public void StretchAndTileAcross_NarrowerThanOneTile_ShrinksTheTileToFit() { Rect rect = Box(0, 0, 10, 50); TextureMaterial.Placement placement = Square( locked: true, across: Tiling.StretchAndTile, down: Tiling.Tile, width: 40, height: 40).PlaceWithin(rect); CheckEqual(0.25, placement.Scale); } public void StretchAndTileDown_ScalesTilesToFitAWholeNumberDown() { Rect rect = Box(0, 0, 50, 90); TextureMaterial.Placement placement = Square( locked: true, across: Tiling.Tile, down: Tiling.StretchAndTile, width: 40, height: 40).PlaceWithin(rect); CheckEqual(1.125, placement.Scale); CheckEqual(rect, placement.Bounds); CheckEqual(Tiling.Tile, placement.TilingX); CheckEqual(Tiling.Tile, placement.TilingY); } public void StretchAndTileBothWays_FitsAcrossAndLetsDownTruncate() { Rect rect = Box(0, 0, 90, 70); TextureMaterial.Placement placement = Square( locked: true, across: Tiling.StretchAndTile, down: Tiling.StretchAndTile, width: 40, height: 40).PlaceWithin(rect); CheckEqual(1.125, placement.Scale); CheckEqual(Tiling.Tile, placement.TilingX); CheckEqual(Tiling.Tile, placement.TilingY); } public void StretchAndTileAcrossNoneDown_DrawsOneCopyDownAtTheFittedScale() { Rect rect = Box(0, 0, 90, 200); TextureMaterial.Placement placement = Square( locked: true, across: Tiling.StretchAndTile, down: Tiling.None, width: 40, height: 40).PlaceWithin(rect); CheckEqual(1.125, placement.Scale); CheckEqual(Box(0, 77.5, 90, 45), placement.Bounds); } } public class LockedProportionsTests : TestFixture { private static readonly Tiling[] DrawnOnce = { Tiling.None, Tiling.Stretch }; public void BothAxesDrawnOnce_KeepTheTexturesProportions() { foreach (Rect rect in new[] { Wide, Tall, Box(0, 0, 33, 71), Box(-5, 9, 400, 3) }) { foreach (Tiling across in DrawnOnce) { foreach (Tiling down in DrawnOnce) { TextureMaterial material = Square( locked: true, across: across, down: down, width: 20, height: 10); Rect bounds = material.PlaceWithin(rect).Bounds; CheckEqual(2, bounds.Width / bounds.Height); } } } } } } public class MinimumSizeTests : TestFixture { public void MatchesThePreferredSize() { var material = new TextureMaterial { Texture = new SizedTexture(40, 20), LockAspectRatio = true }; Constraints constraints = Constraints.TightWidth(10, 100); CheckEqual(material.PreferredSize(constraints), material.MinimumSize(constraints)); } } } }