diff --git a/src/Spectre.Console.Tests/Unit/CanvasTests.cs b/src/Spectre.Console.Tests/Unit/CanvasTests.cs new file mode 100644 index 0000000..6ed48ec --- /dev/null +++ b/src/Spectre.Console.Tests/Unit/CanvasTests.cs @@ -0,0 +1,108 @@ +using System; +using System.Linq; +using System.Text; +using Shouldly; +using Spectre.Console.Rendering; +using Spectre.Console.Testing; +using Xunit; + +namespace Spectre.Console.Tests.Unit +{ + public class CanvasTests + { + [Fact] + public void Canvas_Must_Have_Proper_Size() + { + Should.Throw(() => new Canvas(1, 0)); + + Should.Throw(() => new Canvas(0, 1)); + } + + [Fact] + public void Simple_Render() + { + // Given + var console = new FakeAnsiConsole(ColorSystem.Standard); + var canvas = new Canvas(width: 2, height: 2); + canvas.SetPixel(0, 0, Color.Aqua); + canvas.SetPixel(1, 1, Color.Grey); + + // When + console.Render(canvas); + + // Then + console.Output.ShouldBe($"\u001b[106m \u001b[0m {Environment.NewLine} \u001b[100m \u001b[0m{Environment.NewLine}"); + } + + [Fact] + public void Render_Wider_Than_Terminal_Cannot_Be_Reduced_Further() + { + // Given + var console = new FakeAnsiConsole(ColorSystem.Standard, width: 10); + var canvas = new Canvas(width: 20, height: 2); + canvas.SetPixel(0, 0, Color.Aqua); + canvas.SetPixel(19, 1, Color.Grey); + + // When + console.Render(canvas); + + // Then + console.Output.ShouldBe(string.Empty); + } + + [Fact] + public void Render_Wider_Than_Terminal() + { + // Given + var console = new FakeAnsiConsole(ColorSystem.Standard, width: 10); + var canvas = new Canvas(width: 20, height: 10); + canvas.SetPixel(0, 0, Color.Aqua); + canvas.SetPixel(19, 9, Color.Grey); + + // When + console.Render(canvas); + + // Then + var numNewlines = console.Output.Count(x => x == '\n'); + + // Small terminal shrinks the canvas + numNewlines.ShouldBe(expected: 2); + } + + [Fact] + public void Render_Wider_Configured_With_Max_Width() + { + // Given + var console = new FakeAnsiConsole(ColorSystem.Standard, width: 80); + var canvas = new Canvas(width: 20, height: 10) { MaxWidth = 10 }; + canvas.SetPixel(0, 0, Color.Aqua); + canvas.SetPixel(19, 9, Color.Grey); + + // When + console.Render(canvas); + + // Then + var numNewlines = console.Output.Count(x => x == '\n'); + + // MaxWidth truncates the canvas + numNewlines.ShouldBe(expected: 5); + } + + [Fact] + public void Simple_Measure() + { + // Given + var console = new FakeAnsiConsole(ColorSystem.Standard); + var canvas = new Canvas(width: 2, height: 2); + canvas.SetPixel(0, 0, Color.Aqua); + canvas.SetPixel(1, 1, Color.Grey); + + // When + var measurement = ((IRenderable)canvas).Measure(new RenderContext(Encoding.Unicode, false), 80); + + // Then + measurement.Max.ShouldBe(expected: 4); + measurement.Min.ShouldBe(expected: 4); + } + } +} \ No newline at end of file diff --git a/src/Spectre.Console/Widgets/Canvas.cs b/src/Spectre.Console/Widgets/Canvas.cs index acad4ce..422845b 100644 --- a/src/Spectre.Console/Widgets/Canvas.cs +++ b/src/Spectre.Console/Widgets/Canvas.cs @@ -44,6 +44,16 @@ namespace Spectre.Console /// The canvas height. public Canvas(int width, int height) { + if (width < 1) + { + throw new ArgumentException("Must be > 1", nameof(width)); + } + + if (height < 1) + { + throw new ArgumentException("Must be > 1", nameof(height)); + } + Width = width; Height = height; @@ -104,6 +114,12 @@ namespace Spectre.Console { height = (int)(height * (maxWidth / (float)(width * PixelWidth))); width = maxWidth / PixelWidth; + + // If it's not possible to scale the canvas sufficiently, it's too small to render. + if (height == 0) + { + yield break; + } } // Need to rescale the pixel buffer?