From 1d8bf77ab164b228f0c27eacb8d42b0a37c9e35b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Mar 2019 16:33:50 +0100 Subject: [PATCH 1/5] Added failing test for #2335. --- .../Shapes/PathTests.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs diff --git a/tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs b/tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs new file mode 100644 index 0000000000..05224c2495 --- /dev/null +++ b/tests/Avalonia.Controls.UnitTests/Shapes/PathTests.cs @@ -0,0 +1,16 @@ +using Avalonia.Controls.Shapes; +using Xunit; + +namespace Avalonia.Controls.UnitTests.Shapes +{ + public class PathTests + { + [Fact] + public void Path_With_Null_Data_Does_Not_Throw_On_Measure() + { + var target = new Path(); + + target.Measure(Size.Infinity); + } + } +} From 7a738e18dd374d3dcc96ac5290fd805fcb5174f1 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Mar 2019 16:44:38 +0100 Subject: [PATCH 2/5] Allow for null DefiningGeometry in Shape. Fixes #2335. --- src/Avalonia.Controls/Shapes/Shape.cs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Avalonia.Controls/Shapes/Shape.cs b/src/Avalonia.Controls/Shapes/Shape.cs index 0387328a46..57dbeba1cc 100644 --- a/src/Avalonia.Controls/Shapes/Shape.cs +++ b/src/Avalonia.Controls/Shapes/Shape.cs @@ -195,7 +195,7 @@ namespace Avalonia.Controls.Shapes if (deferCalculateTransform) { _calculateTransformOnArrange = true; - return DefiningGeometry.Bounds.Size; + return DefiningGeometry?.Bounds.Size ?? Size.Empty; } else { @@ -217,17 +217,22 @@ namespace Avalonia.Controls.Shapes private Size CalculateShapeSizeAndSetTransform(Size availableSize) { - // This should probably use GetRenderBounds(strokeThickness) but then the calculations - // will multiply the stroke thickness as well, which isn't correct. - var (size, transform) = CalculateSizeAndTransform(availableSize, DefiningGeometry.Bounds, Stretch); - - if (_transform != transform) + if (DefiningGeometry != null) { - _transform = transform; - _renderedGeometry = null; + // This should probably use GetRenderBounds(strokeThickness) but then the calculations + // will multiply the stroke thickness as well, which isn't correct. + var (size, transform) = CalculateSizeAndTransform(availableSize, DefiningGeometry.Bounds, Stretch); + + if (_transform != transform) + { + _transform = transform; + _renderedGeometry = null; + } + + return size; } - return size; + return Size.Empty; } internal static (Size, Matrix) CalculateSizeAndTransform(Size availableSize, Rect shapeBounds, Stretch Stretch) From f322501852f15f85a05ea52076fcb9a80c07ecca Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Mar 2019 16:45:56 +0100 Subject: [PATCH 3/5] Don't draw null geometry in GeometryDrawing. And add a guard to `DrawingContext` to detect having a null `Geometry` passed, as we do for `DrawImage`, `DrawText` etc. Fixes #2053. --- src/Avalonia.Visuals/Media/DrawingContext.cs | 2 ++ src/Avalonia.Visuals/Media/GeometryDrawing.cs | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Visuals/Media/DrawingContext.cs b/src/Avalonia.Visuals/Media/DrawingContext.cs index e7d6df5a93..fd593db991 100644 --- a/src/Avalonia.Visuals/Media/DrawingContext.cs +++ b/src/Avalonia.Visuals/Media/DrawingContext.cs @@ -109,6 +109,8 @@ namespace Avalonia.Media /// The geometry. public void DrawGeometry(IBrush brush, Pen pen, Geometry geometry) { + Contract.Requires(geometry != null); + if (brush != null || PenIsVisible(pen)) { PlatformImpl.DrawGeometry(brush, pen, geometry.PlatformImpl); diff --git a/src/Avalonia.Visuals/Media/GeometryDrawing.cs b/src/Avalonia.Visuals/Media/GeometryDrawing.cs index a26a5341c8..ac0cc1c17d 100644 --- a/src/Avalonia.Visuals/Media/GeometryDrawing.cs +++ b/src/Avalonia.Visuals/Media/GeometryDrawing.cs @@ -31,7 +31,10 @@ public override void Draw(DrawingContext context) { - context.DrawGeometry(Brush, Pen, Geometry); + if (Geometry != null) + { + context.DrawGeometry(Brush, Pen, Geometry); + } } public override Rect GetBounds() @@ -41,4 +44,4 @@ return Geometry?.GetRenderBounds(pen) ?? new Rect(); } } -} \ No newline at end of file +} From 028d42c7b2ec5a114a65967744d6cfce8cebda40 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Mar 2019 18:07:48 +0100 Subject: [PATCH 4/5] Add additional failing test for #2053. --- .../Rendering/SceneGraph/DrawOperationTests.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs index 2060cc7170..6a1f08a384 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs @@ -61,6 +61,19 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Assert.Equal(1, bitmap.RefCount); } + [Fact] + public void HitTest_On_Geometry_Node_With_Zero_Transform_Does_Not_Throw() + { + var geometry = Mock.Of(); + var geometryNode = new GeometryNode( + new Matrix(), + Brushes.Black, + null, + geometry); + + geometryNode.HitTest(new Point()); + } + private class TestDrawOperation : DrawOperation { public TestDrawOperation(Rect bounds, Matrix transform, Pen pen) From 569e7d29fcad1e508bf63b536bd90bfcb0bde8b2 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Mar 2019 18:08:34 +0100 Subject: [PATCH 5/5] Don't try to invert a non-invertible matrix. Fixes #2053. --- .../Rendering/SceneGraph/GeometryNode.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryNode.cs index 46d264e518..2d01b117d9 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/GeometryNode.cs @@ -89,9 +89,14 @@ namespace Avalonia.Rendering.SceneGraph /// public override bool HitTest(Point p) { - p *= Transform.Invert(); - return (Brush != null && Geometry.FillContains(p)) || - (Pen != null && Geometry.StrokeContains(Pen, p)); + if (Transform.HasInverse) + { + p *= Transform.Invert(); + return (Brush != null && Geometry.FillContains(p)) || + (Pen != null && Geometry.StrokeContains(Pen, p)); + } + + return false; } } }