Sfoglia il codice sorgente

LineCanvas code cleanup and API docs

Tig 8 mesi fa
parent
commit
95f21c383e

+ 132 - 95
Terminal.Gui/Drawing/LineCanvas.cs

@@ -1,62 +1,9 @@
 #nullable enable
 namespace Terminal.Gui;
 
-/// <summary>Facilitates box drawing and line intersection detection and rendering.  Does not support diagonal lines.</summary>
+/// <summary>Facilitates box drawing and line intersection detection and rendering. Does not support diagonal lines.</summary>
 public class LineCanvas : IDisposable
 {
-    /// <summary>
-    ///     Optional <see cref="FillPair"/> which when present overrides the <see cref="StraightLine.Attribute"/>
-    ///     (colors) of lines in the canvas. This can be used e.g. to apply a global <see cref="GradientFill"/>
-    ///     across all lines.
-    /// </summary>
-    public FillPair? Fill { get; set; }
-
-    private readonly List<StraightLine> _lines = [];
-
-    private readonly Dictionary<IntersectionRuneType, IntersectionRuneResolver> _runeResolvers = new ()
-    {
-        {
-            IntersectionRuneType.ULCorner,
-            new ULIntersectionRuneResolver ()
-        },
-        {
-            IntersectionRuneType.URCorner,
-            new URIntersectionRuneResolver ()
-        },
-        {
-            IntersectionRuneType.LLCorner,
-            new LLIntersectionRuneResolver ()
-        },
-        {
-            IntersectionRuneType.LRCorner,
-            new LRIntersectionRuneResolver ()
-        },
-        {
-            IntersectionRuneType.TopTee,
-            new TopTeeIntersectionRuneResolver ()
-        },
-        {
-            IntersectionRuneType.LeftTee,
-            new LeftTeeIntersectionRuneResolver ()
-        },
-        {
-            IntersectionRuneType.RightTee,
-            new RightTeeIntersectionRuneResolver ()
-        },
-        {
-            IntersectionRuneType.BottomTee,
-            new BottomTeeIntersectionRuneResolver ()
-        },
-        {
-            IntersectionRuneType.Cross,
-            new CrossIntersectionRuneResolver ()
-        }
-
-        // TODO: Add other resolvers
-    };
-
-    private Rectangle _cachedViewport;
-
     /// <summary>Creates a new instance.</summary>
     public LineCanvas ()
     {
@@ -66,54 +13,62 @@ public class LineCanvas : IDisposable
         Applied += ConfigurationManager_Applied;
     }
 
+    private readonly List<StraightLine> _lines = [];
+
     /// <summary>Creates a new instance with the given <paramref name="lines"/>.</summary>
     /// <param name="lines">Initial lines for the canvas.</param>
     public LineCanvas (IEnumerable<StraightLine> lines) : this () { _lines = lines.ToList (); }
 
+    /// <summary>
+    ///     Optional <see cref="FillPair"/> which when present overrides the <see cref="StraightLine.Attribute"/>
+    ///     (colors) of lines in the canvas. This can be used e.g. to apply a global <see cref="GradientFill"/>
+    ///     across all lines.
+    /// </summary>
+    public FillPair? Fill { get; set; }
+
+    private Rectangle _cachedBounds;
+
     /// <summary>
     ///     Gets the rectangle that describes the bounds of the canvas. Location is the coordinates of the line that is
-    ///     furthest left/top and Size is defined by the line that extends the furthest right/bottom.
+    ///     the furthest left/top and Size is defined by the line that extends the furthest right/bottom.
     /// </summary>
-    public Rectangle Viewport
+    public Rectangle Bounds
     {
         get
         {
-            if (_cachedViewport.IsEmpty)
+            if (_cachedBounds.IsEmpty)
             {
                 if (_lines.Count == 0)
                 {
-                    return _cachedViewport;
+                    return _cachedBounds;
                 }
 
-                Rectangle viewport = _lines [0].Viewport;
+                Rectangle bounds = _lines [0].Bounds;
 
                 for (var i = 1; i < _lines.Count; i++)
                 {
-                    viewport = Rectangle.Union (viewport, _lines [i].Viewport);
+                    bounds = Rectangle.Union (bounds, _lines [i].Bounds);
                 }
 
-                if (viewport is { Width: 0 } or { Height: 0 })
+                if (bounds is { Width: 0 } or { Height: 0 })
                 {
-                    viewport = viewport with
+                    bounds = bounds with
                     {
-                        Width = Math.Clamp (viewport.Width, 1, short.MaxValue),
-                        Height = Math.Clamp (viewport.Height, 1, short.MaxValue)
+                        Width = Math.Clamp (bounds.Width, 1, short.MaxValue),
+                        Height = Math.Clamp (bounds.Height, 1, short.MaxValue)
                     };
                 }
 
-                _cachedViewport = viewport;
+                _cachedBounds = bounds;
             }
 
-            return _cachedViewport;
+            return _cachedBounds;
         }
     }
 
     /// <summary>Gets the lines in the canvas.</summary>
     public IReadOnlyCollection<StraightLine> Lines => _lines.AsReadOnly ();
 
-    /// <inheritdoc/>
-    public void Dispose () { Applied -= ConfigurationManager_Applied; }
-
     /// <summary>
     ///     <para>Adds a new <paramref name="length"/> long line to the canvas starting at <paramref name="start"/>.</para>
     ///     <para>
@@ -141,7 +96,7 @@ public class LineCanvas : IDisposable
         Attribute? attribute = null
     )
     {
-        _cachedViewport = Rectangle.Empty;
+        _cachedBounds = Rectangle.Empty;
         _lines.Add (new (start, length, orientation, style, attribute));
     }
 
@@ -149,49 +104,67 @@ public class LineCanvas : IDisposable
     /// <param name="line"></param>
     public void AddLine (StraightLine line)
     {
-        _cachedViewport = Rectangle.Empty;
+        _cachedBounds = Rectangle.Empty;
         _lines.Add (line);
     }
 
-    /// <summary>Clears all lines from the LineCanvas.</summary>
-    public void Clear ()
-    {
-        _cachedViewport = Rectangle.Empty;
-        _lines.Clear ();
-        _exclusionRegion = null;
-    }
-
     private Region? _exclusionRegion;
 
     /// <summary>
-    ///     Gets the list of locations that will be excluded from <see cref="GetCellMap"/> and <see cref="GetMap()"/>.
+    ///     Causes the provided region to be excluded from <see cref="GetCellMap"/> and <see cref="GetMap()"/>.
     /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Each call to this method will add to the exclusion region. To clear the exclusion region, call
+    ///         <see cref="ClearCache"/>.
+    ///     </para>
+    /// </remarks>
     public void Exclude (Region region)
     {
-        _exclusionRegion ??= new Region ();
+        _exclusionRegion ??= new ();
         _exclusionRegion.Union (region);
     }
 
     /// <summary>
-    ///     Clears any cached states from the canvas Call this method if you make changes to lines that have already been
+    ///     Clears the exclusion region. After calling this method, <see cref="GetCellMap"/> and <see cref="GetMap()"/> will
+    ///     return all points in the canvas.
+    /// </summary>
+    public void ClearExclusions () { _exclusionRegion = null; }
+
+    /// <summary>Clears all lines from the LineCanvas.</summary>
+    public void Clear ()
+    {
+        _cachedBounds = Rectangle.Empty;
+        _lines.Clear ();
+        ClearExclusions ();
+    }
+
+    /// <summary>
+    ///     Clears any cached states from the canvas. Call this method if you make changes to lines that have already been
     ///     added.
     /// </summary>
-    public void ClearCache () { _cachedViewport = Rectangle.Empty; }
+    public void ClearCache () { _cachedBounds = Rectangle.Empty; }
 
     /// <summary>
     ///     Evaluates the lines that have been added to the canvas and returns a map containing the glyphs and their
     ///     locations. The glyphs are the characters that should be rendered so that all lines connect up with the appropriate
     ///     intersection symbols.
     /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Only the points within the <see cref="Bounds"/> of the canvas that are not in the exclusion region will be
+    ///         returned. To exclude points from the map, use <see cref="Exclude"/>.
+    ///     </para>
+    /// </remarks>
     /// <returns>A map of all the points within the canvas.</returns>
     public Dictionary<Point, Cell?> GetCellMap ()
     {
         Dictionary<Point, Cell?> map = new ();
 
         // walk through each pixel of the bitmap
-        for (int y = Viewport.Y; y < Viewport.Y + Viewport.Height; y++)
+        for (int y = Bounds.Y; y < Bounds.Y + Bounds.Height; y++)
         {
-            for (int x = Viewport.X; x < Viewport.X + Viewport.Width; x++)
+            for (int x = Bounds.X; x < Bounds.X + Bounds.Width; x++)
             {
                 IntersectionDefinition? [] intersects = _lines
                                                         .Select (l => l.Intersects (x, y))
@@ -217,6 +190,12 @@ public class LineCanvas : IDisposable
     ///     locations. The glyphs are the characters that should be rendered so that all lines connect up with the appropriate
     ///     intersection symbols.
     /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Only the points within the <paramref name="inArea"/> of the canvas that are not in the exclusion region will be
+    ///         returned. To exclude points from the map, use <see cref="Exclude"/>.
+    ///     </para>
+    /// </remarks>
     /// <param name="inArea">A rectangle to constrain the search by.</param>
     /// <returns>A map of the points within the canvas that intersect with <paramref name="inArea"/>.</returns>
     public Dictionary<Point, Rune> GetMap (Rectangle inArea)
@@ -250,8 +229,14 @@ public class LineCanvas : IDisposable
     ///     locations. The glyphs are the characters that should be rendered so that all lines connect up with the appropriate
     ///     intersection symbols.
     /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Only the points within the <see cref="Bounds"/> of the canvas that are not in the exclusion region will be
+    ///         returned. To exclude points from the map, use <see cref="Exclude"/>.
+    ///     </para>
+    /// </remarks>
     /// <returns>A map of all the points within the canvas.</returns>
-    public Dictionary<Point, Rune> GetMap () { return GetMap (Viewport); }
+    public Dictionary<Point, Rune> GetMap () { return GetMap (Bounds); }
 
     /// <summary>Merges one line canvas into this one.</summary>
     /// <param name="lineCanvas"></param>
@@ -285,13 +270,13 @@ public class LineCanvas : IDisposable
 
     /// <summary>
     ///     Returns the contents of the line canvas rendered to a string. The string will include all columns and rows,
-    ///     even if <see cref="Viewport"/> has negative coordinates. For example, if the canvas contains a single line that
+    ///     even if <see cref="Bounds"/> has negative coordinates. For example, if the canvas contains a single line that
     ///     starts at (-1,-1) with a length of 2, the rendered string will have a length of 2.
     /// </summary>
     /// <returns>The canvas rendered to a string.</returns>
     public override string ToString ()
     {
-        if (Viewport.IsEmpty)
+        if (Bounds.IsEmpty)
         {
             return string.Empty;
         }
@@ -300,13 +285,13 @@ public class LineCanvas : IDisposable
         Dictionary<Point, Rune> runeMap = GetMap ();
 
         // Create the rune canvas
-        Rune [,] canvas = new Rune [Viewport.Height, Viewport.Width];
+        Rune [,] canvas = new Rune [Bounds.Height, Bounds.Width];
 
         // Copy the rune map to the canvas, adjusting for any negative coordinates
         foreach (KeyValuePair<Point, Rune> kvp in runeMap)
         {
-            int x = kvp.Key.X - Viewport.X;
-            int y = kvp.Key.Y - Viewport.Y;
+            int x = kvp.Key.X - Bounds.X;
+            int y = kvp.Key.Y - Bounds.Y;
             canvas [y, x] = kvp.Value;
         }
 
@@ -330,7 +315,10 @@ public class LineCanvas : IDisposable
         return sb.ToString ();
     }
 
-    private bool All (IntersectionDefinition? [] intersects, Orientation orientation) { return intersects.All (i => i!.Line.Orientation == orientation); }
+    private static bool All (IntersectionDefinition? [] intersects, Orientation orientation)
+    {
+        return intersects.All (i => i!.Line.Orientation == orientation);
+    }
 
     private void ConfigurationManager_Applied (object? sender, ConfigurationManagerEventArgs e)
     {
@@ -347,13 +335,55 @@ public class LineCanvas : IDisposable
     /// <param name="intersects"></param>
     /// <param name="types"></param>
     /// <returns></returns>
-    private bool Exactly (HashSet<IntersectionType> intersects, params IntersectionType [] types) { return intersects.SetEquals (types); }
+    private static bool Exactly (HashSet<IntersectionType> intersects, params IntersectionType [] types) { return intersects.SetEquals (types); }
 
     private Attribute? GetAttributeForIntersects (IntersectionDefinition? [] intersects)
     {
-        return Fill != null ? Fill.GetAttribute (intersects [0]!.Point) : intersects [0]!.Line.Attribute;
+        return Fill?.GetAttribute (intersects [0]!.Point) ?? intersects [0]!.Line.Attribute;
     }
 
+    private readonly Dictionary<IntersectionRuneType, IntersectionRuneResolver> _runeResolvers = new ()
+    {
+        {
+            IntersectionRuneType.ULCorner,
+            new ULIntersectionRuneResolver ()
+        },
+        {
+            IntersectionRuneType.URCorner,
+            new URIntersectionRuneResolver ()
+        },
+        {
+            IntersectionRuneType.LLCorner,
+            new LLIntersectionRuneResolver ()
+        },
+        {
+            IntersectionRuneType.LRCorner,
+            new LRIntersectionRuneResolver ()
+        },
+        {
+            IntersectionRuneType.TopTee,
+            new TopTeeIntersectionRuneResolver ()
+        },
+        {
+            IntersectionRuneType.LeftTee,
+            new LeftTeeIntersectionRuneResolver ()
+        },
+        {
+            IntersectionRuneType.RightTee,
+            new RightTeeIntersectionRuneResolver ()
+        },
+        {
+            IntersectionRuneType.BottomTee,
+            new BottomTeeIntersectionRuneResolver ()
+        },
+        {
+            IntersectionRuneType.Cross,
+            new CrossIntersectionRuneResolver ()
+        }
+
+        // TODO: Add other resolvers
+    };
+
     private Cell? GetCellForIntersects (ConsoleDriver? driver, IntersectionDefinition? [] intersects)
     {
         if (!intersects.Any ())
@@ -695,7 +725,7 @@ public class LineCanvas : IDisposable
         internal Rune _thickBoth;
         internal Rune _thickH;
         internal Rune _thickV;
-        public IntersectionRuneResolver () { SetGlyphs (); }
+        protected IntersectionRuneResolver () { SetGlyphs (); }
 
         public Rune? GetRuneForIntersects (ConsoleDriver? driver, IntersectionDefinition? [] intersects)
         {
@@ -871,4 +901,11 @@ public class LineCanvas : IDisposable
             _normal = Glyphs.URCorner;
         }
     }
+
+    /// <inheritdoc/>
+    public void Dispose ()
+    {
+        Applied -= ConfigurationManager_Applied;
+        GC.SuppressFinalize (this);
+    }
 }

+ 8 - 8
Terminal.Gui/Drawing/StraightLine.cs

@@ -6,11 +6,11 @@
 public class StraightLine
 {
     /// <summary>Creates a new instance of the <see cref="StraightLine"/> class.</summary>
-    /// <param name="start"></param>
-    /// <param name="length"></param>
-    /// <param name="orientation"></param>
-    /// <param name="style"></param>
-    /// <param name="attribute"></param>
+    /// <param name="start">The start location.</param>
+    /// <param name="length">The length of the line.</param>
+    /// <param name="orientation">The orientation of the line.</param>
+    /// <param name="style">The line style.</param>
+    /// <param name="attribute">The attribute to be used for rendering the line.</param>
     public StraightLine (
         Point start,
         int length,
@@ -43,11 +43,11 @@ public class StraightLine
 
     /// <summary>
     ///     Gets the rectangle that describes the bounds of the canvas. Location is the coordinates of the line that is
-    ///     furthest left/top and Size is defined by the line that extends the furthest right/bottom.
+    ///     the furthest left/top and Size is defined by the line that extends the furthest right/bottom.
     /// </summary>
 
-    // PERF: Probably better to store the rectangle rather than make a new one on every single access to Viewport.
-    internal Rectangle Viewport
+    // PERF: Probably better to store the rectangle rather than make a new one on every single access to Bounds.
+    internal Rectangle Bounds
     {
         get
         {

+ 1 - 1
Terminal.Gui/View/View.Drawing.cs

@@ -543,7 +543,7 @@ public partial class View // Drawing APIs
             return;
         }
 
-        if (!SuperViewRendersLineCanvas && LineCanvas.Viewport != Rectangle.Empty)
+        if (!SuperViewRendersLineCanvas && LineCanvas.Bounds != Rectangle.Empty)
         {
             foreach (KeyValuePair<Point, Cell?> p in LineCanvas.GetCellMap ())
             {

+ 4 - 0
Terminal.sln.DotSettings

@@ -381,6 +381,10 @@
 	<s:Boolean x:Key="/Default/CodeStyle/EditorConfig/EnableEditorConfigSupport/@EntryValue">False</s:Boolean>
 	<s:Boolean x:Key="/Default/CodeStyle/EditorConfig/ShowEditorConfigStatusBarIndicator/@EntryValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/CodeStyle/EditorConfig/SyncToVisualStudio/@EntryValue">True</s:Boolean>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LL/@EntryIndexedValue">LL</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LR/@EntryIndexedValue">LR</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UL/@EntryIndexedValue">UL</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UR/@EntryIndexedValue">UR</s:String>
 	<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">False</s:Boolean>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PublicFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>

+ 18 - 18
UnitTests/Drawing/LineCanvasTests.cs

@@ -377,7 +377,7 @@ public class LineCanvasTests (ITestOutputHelper _output)
         canvas.AddLine (new (x, y), length, Orientation.Horizontal, LineStyle.Single);
         canvas.AddLine (new (x, y), length, Orientation.Vertical, LineStyle.Single);
 
-        Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Viewport);
+        Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Bounds);
     }
 
     [InlineData (
@@ -458,7 +458,7 @@ public class LineCanvasTests (ITestOutputHelper _output)
         var canvas = new LineCanvas ();
         canvas.AddLine (new (x, y), length, Orientation.Horizontal, LineStyle.Single);
 
-        Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Viewport);
+        Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Bounds);
     }
 
     [Fact]
@@ -480,27 +480,27 @@ public class LineCanvasTests (ITestOutputHelper _output)
 
         // Add a short horiz line for ╔╡
         lc.AddLine (new (x, y), 2, Orientation.Horizontal, LineStyle.Double);
-        Assert.Equal (new (x, y, 2, 1), lc.Viewport);
+        Assert.Equal (new (x, y, 2, 1), lc.Bounds);
 
         //LHS line down
         lc.AddLine (new (x, y), height, Orientation.Vertical, LineStyle.Double);
-        Assert.Equal (new (x, y, 2, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 2, 2), lc.Bounds);
 
         //Vertical line before Title, results in a ╡
         lc.AddLine (new (x + 1, y), 0, Orientation.Vertical, LineStyle.Single);
-        Assert.Equal (new (x, y, 2, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 2, 2), lc.Bounds);
 
         //Vertical line after Title, results in a ╞
         lc.AddLine (new (x + 2, y), 0, Orientation.Vertical, LineStyle.Single);
-        Assert.Equal (new (x, y, 3, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 3, 2), lc.Bounds);
 
         // remainder of top line
         lc.AddLine (new (x + 2, y), width - 1, Orientation.Horizontal, LineStyle.Double);
-        Assert.Equal (new (x, y, 4, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 4, 2), lc.Bounds);
 
         //RHS line down
         lc.AddLine (new (x + width, y), height, Orientation.Vertical, LineStyle.Double);
-        Assert.Equal (new (x, y, 4, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 4, 2), lc.Bounds);
 
         TestHelpers.AssertEqual (
                                  _output,
@@ -530,27 +530,27 @@ public class LineCanvasTests (ITestOutputHelper _output)
 
         // Add a short horiz line for ╔╡
         lc.AddLine (new (x, y), 2, Orientation.Horizontal, LineStyle.Double);
-        Assert.Equal (new (x, y, 2, 1), lc.Viewport);
+        Assert.Equal (new (x, y, 2, 1), lc.Bounds);
 
         //LHS line down
         lc.AddLine (new (x, y), height, Orientation.Vertical, LineStyle.Double);
-        Assert.Equal (new (x, y, 2, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 2, 2), lc.Bounds);
 
         //Vertical line before Title, results in a ╡
         lc.AddLine (new (x + 1, y), 0, Orientation.Vertical, LineStyle.Single);
-        Assert.Equal (new (x, y, 2, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 2, 2), lc.Bounds);
 
         //Vertical line after Title, results in a ╞
         lc.AddLine (new (x + 2, y), 0, Orientation.Vertical, LineStyle.Single);
-        Assert.Equal (new (x, y, 3, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 3, 2), lc.Bounds);
 
         // remainder of top line
         lc.AddLine (new (x + 2, y), width - 1, Orientation.Horizontal, LineStyle.Double);
-        Assert.Equal (new (x, y, 4, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 4, 2), lc.Bounds);
 
         //RHS line down
         lc.AddLine (new (x + width, y), height, Orientation.Vertical, LineStyle.Double);
-        Assert.Equal (new (x, y, 4, 2), lc.Viewport);
+        Assert.Equal (new (x, y, 4, 2), lc.Bounds);
 
         TestHelpers.AssertEqual (
                                  _output,
@@ -567,13 +567,13 @@ public class LineCanvasTests (ITestOutputHelper _output)
     {
         var lc = new LineCanvas ();
 
-        Assert.Equal (Rectangle.Empty, lc.Viewport);
+        Assert.Equal (Rectangle.Empty, lc.Bounds);
 
         lc.AddLine (Point.Empty, 2, Orientation.Horizontal, LineStyle.Double);
-        Assert.NotEqual (Rectangle.Empty, lc.Viewport);
+        Assert.NotEqual (Rectangle.Empty, lc.Bounds);
 
         lc.Clear ();
-        Assert.Equal (Rectangle.Empty, lc.Viewport);
+        Assert.Equal (Rectangle.Empty, lc.Bounds);
     }
 
     [InlineData (0, 0, Orientation.Horizontal, "─")]
@@ -872,7 +872,7 @@ public class LineCanvasTests (ITestOutputHelper _output)
         //// Left Up
         //canvas.AddLine (new Point (0, 3), -3, Orientation.Vertical, LineStyle.Single);
 
-        Assert.Equal (new (0, 0, 2, 2), canvas.Viewport);
+        Assert.Equal (new (0, 0, 2, 2), canvas.Bounds);
 
         Dictionary<Point, Rune> map = canvas.GetMap ();
         Assert.Equal (2, map.Count);

+ 1 - 1
UnitTests/Drawing/StraightLineTests.cs

@@ -321,6 +321,6 @@ public class StraightLineTests (ITestOutputHelper output)
     {
         var sl = new StraightLine (new (x, y), length, orientation, LineStyle.Single);
 
-        Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), sl.Viewport);
+        Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), sl.Bounds);
     }
 }