Browse Source

Merge branch 'master' into reworkedFontManager

Benedikt Stebner 6 years ago
parent
commit
69e78c4682

+ 7 - 13
src/Avalonia.Controls/Utils/BorderRenderHelper.cs

@@ -90,23 +90,17 @@ namespace Avalonia.Controls.Utils
             {
                 var borderThickness = borders.Top;
                 var top = borderThickness * 0.5;
-                var cornerRadius = (float)Math.Max(0, radii.TopLeft - borderThickness - top);
 
-                if (background != null)
-                {
-                    var topLeft = new Point(borders.Left, borders.Top);
-                    var bottomRight = new Point(size.Width - borders.Right, size.Height - borders.Bottom);
-                    var innerRect = new Rect(topLeft, bottomRight);
-                    context.FillRectangle(background, innerRect, cornerRadius);
-                }
+                IPen pen = null;
 
-                if (borderBrush != null && borderThickness > 0)
+                if (borderThickness > 0)
                 {
-                    var topLeft = new Point(top, top);
-                    var bottomRight = new Point(size.Width - top, size.Height - top);
-                    var outerRect = new Rect(topLeft, bottomRight);
-                    context.DrawRectangle(new Pen(borderBrush, borderThickness), outerRect, (float)radii.TopLeft);
+                    pen = new Pen(borderBrush, borderThickness);
                 }
+
+                var rect = new Rect(top, top, size.Width - borderThickness, size.Height - borderThickness);
+
+                context.DrawRectangle(background, pen, rect, radii.TopLeft, radii.TopLeft);
             }
         }    
 

+ 38 - 8
src/Avalonia.Visuals/Media/DrawingContext.cs

@@ -118,6 +118,42 @@ namespace Avalonia.Media
             }
         }
 
+        /// <summary>
+        /// Draws a rectangle with the specified Brush and Pen.
+        /// </summary>
+        /// <param name="brush">The brush used to fill the rectangle, or <c>null</c> for no fill.</param>
+        /// <param name="pen">The pen used to stroke the rectangle, or <c>null</c> for no stroke.</param>
+        /// <param name="rect">The rectangle bounds.</param>
+        /// <param name="radiusX">The radius in the X dimension of the rounded corners.
+        ///     This value will be clamped to the range of 0 to Width/2
+        /// </param>
+        /// <param name="radiusY">The radius in the Y dimension of the rounded corners.
+        ///     This value will be clamped to the range of 0 to Height/2
+        /// </param>
+        /// <remarks>
+        /// The brush and the pen can both be null. If the brush is null, then no fill is performed.
+        /// If the pen is null, then no stoke is performed. If both the pen and the brush are null, then the drawing is not visible.
+        /// </remarks>
+        public void DrawRectangle(IBrush brush, IPen pen, Rect rect, double radiusX = 0, double radiusY = 0)
+        {
+            if (brush == null && !PenIsVisible(pen))
+            {
+                return;
+            }
+
+            if (Math.Abs(radiusX) > double.Epsilon)
+            {
+                radiusX = Math.Min(radiusX, rect.Width / 2);
+            }
+
+            if (Math.Abs(radiusY) > double.Epsilon)
+            {
+                radiusY = Math.Min(radiusY, rect.Height / 2);
+            }
+
+            PlatformImpl.DrawRectangle(brush, pen, rect, radiusX, radiusY);
+        }
+
         /// <summary>
         /// Draws the outline of a rectangle.
         /// </summary>
@@ -126,10 +162,7 @@ namespace Avalonia.Media
         /// <param name="cornerRadius">The corner radius.</param>
         public void DrawRectangle(IPen pen, Rect rect, float cornerRadius = 0.0f)
         {
-            if (PenIsVisible(pen))
-            {
-                PlatformImpl.DrawRectangle(pen, rect, cornerRadius);
-            }
+            DrawRectangle(null, pen, rect, cornerRadius, cornerRadius);
         }
 
         /// <summary>
@@ -162,10 +195,7 @@ namespace Avalonia.Media
         /// <param name="cornerRadius">The corner radius.</param>
         public void FillRectangle(IBrush brush, Rect rect, float cornerRadius = 0.0f)
         {
-            if (brush != null && rect != Rect.Empty)
-            {
-                PlatformImpl.FillRectangle(brush, rect, cornerRadius);
-            }
+            DrawRectangle(brush, null, rect, cornerRadius, cornerRadius);
         }
 
         public readonly struct PushedState : IDisposable

+ 14 - 12
src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs

@@ -61,12 +61,22 @@ namespace Avalonia.Platform
         void DrawGeometry(IBrush brush, IPen pen, IGeometryImpl geometry);
 
         /// <summary>
-        /// Draws the outline of a rectangle.
+        /// Draws a rectangle with the specified Brush and Pen.
         /// </summary>
-        /// <param name="pen">The pen.</param>
+        /// <param name="brush">The brush used to fill the rectangle, or <c>null</c> for no fill.</param>
+        /// <param name="pen">The pen used to stroke the rectangle, or <c>null</c> for no stroke.</param>
         /// <param name="rect">The rectangle bounds.</param>
-        /// <param name="cornerRadius">The corner radius.</param>
-        void DrawRectangle(IPen pen, Rect rect, float cornerRadius = 0.0f);
+        /// <param name="radiusX">The radius in the X dimension of the rounded corners.
+        ///     This value will be clamped to the range of 0 to Width/2
+        /// </param>
+        /// <param name="radiusY">The radius in the Y dimension of the rounded corners.
+        ///     This value will be clamped to the range of 0 to Height/2
+        /// </param>
+        /// <remarks>
+        /// The brush and the pen can both be null. If the brush is null, then no fill is performed.
+        /// If the pen is null, then no stoke is performed. If both the pen and the brush are null, then the drawing is not visible.
+        /// </remarks>
+        void DrawRectangle(IBrush brush, IPen pen, Rect rect, double radiusX = 0, double radiusY = 0);
 
         /// <summary>
         /// Draws text.
@@ -76,14 +86,6 @@ namespace Avalonia.Platform
         /// <param name="text">The text.</param>
         void DrawText(IBrush foreground, Point origin, IFormattedTextImpl text);
 
-        /// <summary>
-        /// Draws a filled rectangle.
-        /// </summary>
-        /// <param name="brush">The brush.</param>
-        /// <param name="rect">The rectangle bounds.</param>
-        /// <param name="cornerRadius">The corner radius.</param>
-        void FillRectangle(IBrush brush, Rect rect, float cornerRadius = 0.0f);
-
         /// <summary>
         /// Creates a new <see cref="IRenderTargetBitmapImpl"/> that can be used as a render layer
         /// for the current render target.

+ 1 - 1
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@@ -445,7 +445,7 @@ namespace Avalonia.Rendering
             foreach (var r in _dirtyRectsDisplay)
             {
                 var brush = new ImmutableSolidColorBrush(Colors.Magenta, r.Opacity);
-                context.FillRectangle(brush, r.Rect);
+                context.DrawRectangle(brush,null, r.Rect);
             }
         }
 

+ 1 - 1
src/Avalonia.Visuals/Rendering/RendererBase.cs

@@ -50,7 +50,7 @@ namespace Avalonia.Rendering
             var rect = new Rect(clientRect.Right - size.Width, 0, size.Width, size.Height);
 
             context.Transform = Matrix.Identity;
-            context.FillRectangle(Brushes.Black, rect);
+            context.DrawRectangle(Brushes.Black,null, rect);
             context.DrawText(Brushes.White, rect.TopLeft, _fpsText.PlatformImpl);
         }
     }

+ 3 - 18
src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs

@@ -152,13 +152,13 @@ namespace Avalonia.Rendering.SceneGraph
         }
 
         /// <inheritdoc/>
-        public void DrawRectangle(IPen pen, Rect rect, float cornerRadius = 0)
+        public void DrawRectangle(IBrush brush, IPen pen, Rect rect, double radiusX = 0, double radiusY = 0)
         {
             var next = NextDrawAs<RectangleNode>();
 
-            if (next == null || !next.Item.Equals(Transform, null, pen, rect, cornerRadius))
+            if (next == null || !next.Item.Equals(Transform, brush, pen, rect, radiusX, radiusY))
             {
-                Add(new RectangleNode(Transform, null, pen, rect, cornerRadius, CreateChildScene(pen.Brush)));
+                Add(new RectangleNode(Transform, brush, pen, rect, radiusX, radiusY, CreateChildScene(brush)));
             }
             else
             {
@@ -190,21 +190,6 @@ namespace Avalonia.Rendering.SceneGraph
             }
         }
 
-        /// <inheritdoc/>
-        public void FillRectangle(IBrush brush, Rect rect, float cornerRadius = 0)
-        {
-            var next = NextDrawAs<RectangleNode>();
-
-            if (next == null || !next.Item.Equals(Transform, brush, null, rect, cornerRadius))
-            {
-                Add(new RectangleNode(Transform, brush, null, rect, cornerRadius, CreateChildScene(brush)));
-            }
-            else
-            {
-                ++_drawOperationindex;
-            }
-        }
-
         public IRenderTargetBitmapImpl CreateLayer(Size size)
         {
             throw new NotSupportedException("Creating layers on a deferred drawing context not supported");

+ 23 - 20
src/Avalonia.Visuals/Rendering/SceneGraph/RectangleNode.cs

@@ -1,6 +1,7 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
+using System;
 using System.Collections.Generic;
 using Avalonia.Media;
 using Avalonia.Media.Immutable;
@@ -21,14 +22,16 @@ namespace Avalonia.Rendering.SceneGraph
         /// <param name="brush">The fill brush.</param>
         /// <param name="pen">The stroke pen.</param>
         /// <param name="rect">The rectangle to draw.</param>
-        /// <param name="cornerRadius">The rectangle corner radius.</param>
+        /// <param name="radiusY">The radius in the Y dimension of the rounded corners.</param>
+        /// <param name="radiusX">The radius in the X dimension of the rounded corners.</param>
         /// <param name="childScenes">Child scenes for drawing visual brushes.</param>
         public RectangleNode(
             Matrix transform,
             IBrush brush,
             IPen pen,
             Rect rect,
-            float cornerRadius,
+            double radiusX,
+            double radiusY,
             IDictionary<IVisual, Scene> childScenes = null)
             : base(rect, transform, pen)
         {
@@ -36,7 +39,8 @@ namespace Avalonia.Rendering.SceneGraph
             Brush = brush?.ToImmutable();
             Pen = pen?.ToImmutable();
             Rect = rect;
-            CornerRadius = cornerRadius;
+            RadiusX = radiusX;
+            RadiusY = radiusY;
             ChildScenes = childScenes;
         }
 
@@ -61,9 +65,14 @@ namespace Avalonia.Rendering.SceneGraph
         public Rect Rect { get; }
 
         /// <summary>
-        /// Gets the rectangle corner radius.
+        /// The radius in the X dimension of the rounded corners.
         /// </summary>
-        public float CornerRadius { get; }
+        public double RadiusX { get; }
+
+        /// <summary>
+        /// The radius in the Y dimension of the rounded corners.
+        /// </summary>
+        public double RadiusY { get; }
 
         /// <inheritdoc/>
         public override IDictionary<IVisual, Scene> ChildScenes { get; }
@@ -75,19 +84,21 @@ namespace Avalonia.Rendering.SceneGraph
         /// <param name="brush">The fill of the other draw operation.</param>
         /// <param name="pen">The stroke of the other draw operation.</param>
         /// <param name="rect">The rectangle of the other draw operation.</param>
-        /// <param name="cornerRadius">The rectangle corner radius of the other draw operation.</param>
+        /// <param name="radiusX"></param>
+        /// <param name="radiusY"></param>
         /// <returns>True if the draw operations are the same, otherwise false.</returns>
         /// <remarks>
         /// The properties of the other draw operation are passed in as arguments to prevent
         /// allocation of a not-yet-constructed draw operation object.
         /// </remarks>
-        public bool Equals(Matrix transform, IBrush brush, IPen pen, Rect rect, float cornerRadius)
+        public bool Equals(Matrix transform, IBrush brush, IPen pen, Rect rect, double radiusX, double radiusY)
         {
             return transform == Transform &&
-                Equals(brush, Brush) &&
-                Equals(Pen, pen) &&
-                rect == Rect &&
-                cornerRadius == CornerRadius;
+                   Equals(brush, Brush) &&
+                   Equals(Pen, pen) &&
+                   rect == Rect &&
+                   Math.Abs(radiusX - RadiusX) < double.Epsilon &&
+                   Math.Abs(radiusY - RadiusY) < double.Epsilon;
         }
 
         /// <inheritdoc/>
@@ -95,15 +106,7 @@ namespace Avalonia.Rendering.SceneGraph
         {
             context.Transform = Transform;
 
-            if (Brush != null)
-            {
-                context.FillRectangle(Brush, Rect, CornerRadius);
-            }
-
-            if (Pen != null)
-            {
-                context.DrawRectangle(Pen, Rect, CornerRadius);
-            }
+            context.DrawRectangle(Brush, Pen, Rect, RadiusX, RadiusY);
         }
 
         /// <inheritdoc/>

+ 26 - 23
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@@ -184,37 +184,40 @@ namespace Avalonia.Skia
         }
 
         /// <inheritdoc />
-        public void DrawRectangle(IPen pen, Rect rect, float cornerRadius = 0)
+        public void DrawRectangle(IBrush brush, IPen pen, Rect rect, double radiusX, double radiusY)
         {
-            using (var paint = CreatePaint(pen, rect.Size))
-            {
-                var rc = rect.ToSKRect();
+            var rc = rect.ToSKRect();
+            var isRounded = Math.Abs(radiusX) > double.Epsilon || Math.Abs(radiusX) > double.Epsilon;
 
-                if (Math.Abs(cornerRadius) < float.Epsilon)
-                {
-                    Canvas.DrawRect(rc, paint.Paint);
-                }
-                else
+            if (brush != null)
+            {
+                using (var paint = CreatePaint(brush, rect.Size))
                 {
-                    Canvas.DrawRoundRect(rc, cornerRadius, cornerRadius, paint.Paint);
+                    if (isRounded)
+                    {
+                        Canvas.DrawRoundRect(rc, (float)radiusX, (float)radiusY, paint.Paint);
+                    }
+                    else
+                    {
+                        Canvas.DrawRect(rc, paint.Paint);
+                    }
+                  
                 }
             }
-        }
 
-        /// <inheritdoc />
-        public void FillRectangle(IBrush brush, Rect rect, float cornerRadius = 0)
-        {
-            using (var paint = CreatePaint(brush, rect.Size))
+            if (pen?.Brush != null)
             {
-                var rc = rect.ToSKRect();
-
-                if (Math.Abs(cornerRadius) < float.Epsilon)
-                {
-                    Canvas.DrawRect(rc, paint.Paint);
-                }
-                else
+                using (var paint = CreatePaint(pen, rect.Size))
                 {
-                    Canvas.DrawRoundRect(rc, cornerRadius, cornerRadius, paint.Paint);
+                    if (isRounded)
+                    {
+                        Canvas.DrawRoundRect(rc, (float)radiusX, (float)radiusY, paint.Paint);
+                    }
+                    else
+                    {
+                        Canvas.DrawRect(rc, paint.Paint);
+                    }
+                   
                 }
             }
         }

+ 52 - 57
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@@ -230,34 +230,64 @@ namespace Avalonia.Direct2D1.Media
             }
         }
 
-        /// <summary>
-        /// Draws the outline of a rectangle.
-        /// </summary>
-        /// <param name="pen">The pen.</param>
-        /// <param name="rect">The rectangle bounds.</param>
-        /// <param name="cornerRadius">The corner radius.</param>
-        public void DrawRectangle(IPen pen, Rect rect, float cornerRadius)
+        /// <inheritdoc />
+        public void DrawRectangle(IBrush brush, IPen pen, Rect rect, double radiusX, double radiusY)
         {
-            using (var brush = CreateBrush(pen.Brush, rect.Size))
-            using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext))
+            var rc = rect.ToDirect2D();
+            var isRounded = Math.Abs(radiusX) > double.Epsilon || Math.Abs(radiusX) > double.Epsilon;
+
+            if (brush != null)
             {
-                if (brush.PlatformBrush != null)
+                using (var b = CreateBrush(brush, rect.Size))
                 {
-                    if (cornerRadius == 0)
+                    if (b.PlatformBrush != null)
                     {
-                        _deviceContext.DrawRectangle(
-                            rect.ToDirect2D(),
-                            brush.PlatformBrush,
-                            (float)pen.Thickness,
-                            d2dStroke);
+                        if (isRounded)
+                        {
+                            _deviceContext.FillRoundedRectangle(
+                                new RoundedRectangle
+                                {
+                                    Rect = new RawRectangleF(
+                                        (float)rect.X,
+                                        (float)rect.Y,
+                                        (float)rect.Right,
+                                        (float)rect.Bottom),
+                                    RadiusX = (float)radiusX,
+                                    RadiusY = (float)radiusY
+                                },
+                                b.PlatformBrush);
+                        }
+                        else
+                        {
+                            _deviceContext.FillRectangle(rc, b.PlatformBrush);
+                        }
                     }
-                    else
+                }
+            }
+
+            if (pen?.Brush != null)
+            {
+                using (var wrapper = CreateBrush(pen.Brush, rect.Size))
+                using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext))
+                {
+                    if (wrapper.PlatformBrush != null)
                     {
-                        _deviceContext.DrawRoundedRectangle(
-                            new RoundedRectangle { Rect = rect.ToDirect2D(), RadiusX = cornerRadius, RadiusY = cornerRadius },
-                            brush.PlatformBrush,
-                            (float)pen.Thickness,
-                            d2dStroke);
+                        if (isRounded)
+                        {
+                            _deviceContext.DrawRoundedRectangle(
+                                new RoundedRectangle { Rect = rc, RadiusX = (float)radiusX, RadiusY = (float)radiusY },
+                                wrapper.PlatformBrush,
+                                (float)pen.Thickness,
+                                d2dStroke);
+                        }
+                        else
+                        {
+                            _deviceContext.DrawRectangle(
+                                rc,
+                                wrapper.PlatformBrush,
+                                (float)pen.Thickness,
+                                d2dStroke);
+                        }
                     }
                 }
             }
@@ -286,41 +316,6 @@ namespace Avalonia.Direct2D1.Media
             }
         }
 
-        /// <summary>
-        /// Draws a filled rectangle.
-        /// </summary>
-        /// <param name="brush">The brush.</param>
-        /// <param name="rect">The rectangle bounds.</param>
-        /// <param name="cornerRadius">The corner radius.</param>
-        public void FillRectangle(IBrush brush, Rect rect, float cornerRadius)
-        {
-            using (var b = CreateBrush(brush, rect.Size))
-            {
-                if (b.PlatformBrush != null)
-                {
-                    if (cornerRadius == 0)
-                    {
-                        _deviceContext.FillRectangle(rect.ToDirect2D(), b.PlatformBrush);
-                    }
-                    else
-                    {
-                        _deviceContext.FillRoundedRectangle(
-                            new RoundedRectangle
-                            {
-                                Rect = new RawRectangleF(
-                                        (float)rect.X,
-                                        (float)rect.Y,
-                                        (float)rect.Right,
-                                        (float)rect.Bottom),
-                                RadiusX = cornerRadius,
-                                RadiusY = cornerRadius
-                            },
-                            b.PlatformBrush);
-                    }
-                }
-            }
-        }
-
         public IRenderTargetBitmapImpl CreateLayer(Size size)
         {
             if (_layerFactory != null)

+ 5 - 5
tests/Avalonia.RenderTests/Media/BitmapTests.cs

@@ -78,9 +78,9 @@ namespace Avalonia.Direct2D1.RenderTests.Media
             {
                 ctx.Clear(Colors.Transparent);
                 ctx.PushOpacity(0.8);
-                ctx.FillRectangle(Brushes.Chartreuse, new Rect(0, 0, 20, 100));
-                ctx.FillRectangle(Brushes.Crimson, new Rect(20, 0, 20, 100));
-                ctx.FillRectangle(Brushes.Gold, new Rect(40, 0, 20, 100));
+                ctx.DrawRectangle(Brushes.Chartreuse, null, new Rect(0, 0, 20, 100));
+                ctx.DrawRectangle(Brushes.Crimson, null, new Rect(20, 0, 20, 100));
+                ctx.DrawRectangle(Brushes.Gold,null, new Rect(40, 0, 20, 100));
                 ctx.PopOpacity();
             }
 
@@ -90,8 +90,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media
             {
                 using (var ctx = rtb.CreateDrawingContext(null))
                 {
-                    ctx.FillRectangle(Brushes.Blue, new Rect(0, 0, 100, 100));
-                    ctx.FillRectangle(Brushes.Pink, new Rect(0, 20, 100, 10));
+                    ctx.DrawRectangle(Brushes.Blue, null, new Rect(0, 0, 100, 100));
+                    ctx.DrawRectangle(Brushes.Pink, null, new Rect(0, 20, 100, 10));
 
                     var rc = new Rect(0, 0, 60, 60);
                     ctx.DrawImage(bmp.PlatformImpl, 1, rc, rc);

+ 4 - 4
tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs

@@ -466,7 +466,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
             var animation = new BehaviorSubject<double>(0.5);
 
             context.Verify(x => x.PushOpacity(0.5), Times.Once);
-            context.Verify(x => x.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100), 0), Times.Once);
+            context.Verify(x => x.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100), 0, 0), Times.Once);
             context.Verify(x => x.PopOpacity(), Times.Once);
         }
 
@@ -496,7 +496,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
             var animation = new BehaviorSubject<double>(0.5);
 
             context.Verify(x => x.PushOpacity(0.5), Times.Never);
-            context.Verify(x => x.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100), 0), Times.Never);
+            context.Verify(x => x.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100), 0, 0), Times.Never);
             context.Verify(x => x.PopOpacity(), Times.Never);
         }
 
@@ -522,7 +522,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
             var animation = new BehaviorSubject<double>(0.5);
 
             context.Verify(x => x.PushOpacityMask(Brushes.Green, new Rect(0, 0, 100, 100)), Times.Once);
-            context.Verify(x => x.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100), 0), Times.Once);
+            context.Verify(x => x.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100), 0, 0), Times.Once);
             context.Verify(x => x.PopOpacityMask(), Times.Once);
         }
 
@@ -641,7 +641,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
             var context = GetLayerContext(target, border);
 
             context.Verify(x => x.PushOpacity(0.5), Times.Never);
-            context.Verify(x => x.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100), 0), Times.Once);
+            context.Verify(x => x.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100), 0, 0), Times.Once);
             context.Verify(x => x.PopOpacity(), Times.Never);
         }
 

+ 12 - 14
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DeferredDrawingContextImplTests.cs

@@ -100,20 +100,18 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
 
             using (target.BeginUpdate(node))
             {
-                target.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100));
-                target.DrawRectangle(new Pen(Brushes.Green, 1), new Rect(0, 0, 100, 100));
+                target.DrawRectangle(Brushes.Red, new Pen(Brushes.Green, 1), new Rect(0, 0, 100, 100));
             }
 
-            Assert.Equal(2, node.DrawOperations.Count);
+            Assert.Equal(1, node.DrawOperations.Count);
             Assert.IsType<RectangleNode>(node.DrawOperations[0].Item);
-            Assert.IsType<RectangleNode>(node.DrawOperations[1].Item);
         }
 
         [Fact]
         public void Should_Not_Replace_Identical_DrawOperation()
         {
             var node = new VisualNode(new TestRoot(), null);
-            var operation = RefCountable.Create(new RectangleNode(Matrix.Identity, Brushes.Red, null, new Rect(0, 0, 100, 100), 0));
+            var operation = RefCountable.Create(new RectangleNode(Matrix.Identity, Brushes.Red, null, new Rect(0, 0, 100, 100), 0, 0));
             var layers = new SceneLayers(node.Visual);
             var target = new DeferredDrawingContextImpl(null, layers);
 
@@ -122,7 +120,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
 
             using (target.BeginUpdate(node))
             {
-                target.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100));
+                target.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100));
             }
 
             Assert.Equal(1, node.DrawOperations.Count);
@@ -135,7 +133,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
         public void Should_Replace_Different_DrawOperation()
         {
             var node = new VisualNode(new TestRoot(), null);
-            var operation = RefCountable.Create(new RectangleNode(Matrix.Identity, Brushes.Red, null, new Rect(0, 0, 100, 100), 0));
+            var operation = RefCountable.Create(new RectangleNode(Matrix.Identity, Brushes.Red, null, new Rect(0, 0, 100, 100), 0, 0));
             var layers = new SceneLayers(node.Visual);
             var target = new DeferredDrawingContextImpl(null, layers);
 
@@ -144,7 +142,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
 
             using (target.BeginUpdate(node))
             {
-                target.FillRectangle(Brushes.Green, new Rect(0, 0, 100, 100));
+                target.DrawRectangle(Brushes.Green, null, new Rect(0, 0, 100, 100));
             }
 
             Assert.Equal(1, node.DrawOperations.Count);
@@ -157,7 +155,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
         public void Should_Update_DirtyRects()
         {
             var node = new VisualNode(new TestRoot(), null);
-            var operation = new RectangleNode(Matrix.Identity, Brushes.Red, null, new Rect(0, 0, 100, 100), 0);
+            var operation = new RectangleNode(Matrix.Identity, Brushes.Red, null, new Rect(0, 0, 100, 100), 0, 0);
             var layers = new SceneLayers(node.Visual);
             var target = new DeferredDrawingContextImpl(null, layers);
 
@@ -165,7 +163,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
 
             using (target.BeginUpdate(node))
             {
-                target.FillRectangle(Brushes.Green, new Rect(0, 0, 100, 100));
+                target.DrawRectangle(Brushes.Green, null, new Rect(0, 0, 100, 100));
             }
 
             Assert.Equal(new Rect(0, 0, 100, 100), layers.Single().Dirty.Single());
@@ -192,8 +190,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
 
             using (target.BeginUpdate(node))
             {
-                target.FillRectangle(Brushes.Green, new Rect(0, 0, 10, 100));
-                target.FillRectangle(Brushes.Blue, new Rect(0, 0, 20, 100));
+                target.DrawRectangle(Brushes.Green, null, new Rect(0, 0, 10, 100));
+                target.DrawRectangle(Brushes.Blue, null, new Rect(0, 0, 20, 100));
             }
 
             Assert.Equal(2, node.DrawOperations.Count);
@@ -208,7 +206,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
         public void Trimmed_DrawOperations_Releases_Reference()
         {
             var node = new VisualNode(new TestRoot(), null);
-            var operation = RefCountable.Create(new RectangleNode(Matrix.Identity, Brushes.Red, null, new Rect(0, 0, 100, 100), 0));
+            var operation = RefCountable.Create(new RectangleNode(Matrix.Identity, Brushes.Red, null, new Rect(0, 0, 100, 100), 0, 0));
             var layers = new SceneLayers(node.Visual);
             var target = new DeferredDrawingContextImpl(null, layers);
 
@@ -218,7 +216,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
 
             using (target.BeginUpdate(node))
             {
-                target.FillRectangle(Brushes.Green, new Rect(0, 0, 100, 100));
+                target.DrawRectangle(Brushes.Green, null, new Rect(0, 0, 100, 100));
             }
 
             Assert.Equal(1, node.DrawOperations.Count);