From 25b00749c58cd69b317305d780f597684309bff4 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 3 Sep 2018 09:36:10 +0200 Subject: [PATCH 1/9] Updated portable.xaml submodule to latest develop. --- .../Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github index 8abbe09592..31ea8e6900 160000 --- a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github +++ b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github @@ -1 +1 @@ -Subproject commit 8abbe09592668efb573ac4d5548ba2d7e464ba78 +Subproject commit 31ea8e6900d859a8d1bf45972954b075d2a59f30 From 0ef1bbce7658c07af084ee6ba128d4e25ced9fb5 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Tue, 18 Sep 2018 06:11:43 +0200 Subject: [PATCH 2/9] Fix #1904 --- .../Utils/BorderRenderHelper.cs | 153 +++++++++--------- 1 file changed, 81 insertions(+), 72 deletions(-) diff --git a/src/Avalonia.Controls/Utils/BorderRenderHelper.cs b/src/Avalonia.Controls/Utils/BorderRenderHelper.cs index 0fd6593fbe..62867f1d22 100644 --- a/src/Avalonia.Controls/Utils/BorderRenderHelper.cs +++ b/src/Avalonia.Controls/Utils/BorderRenderHelper.cs @@ -88,24 +88,79 @@ namespace Avalonia.Controls.Utils } else { - var borderThickness = borders.Left; - var cornerRadius = (float)radii.TopLeft; - var rect = new Rect(size); + var borderThickness = borders.Top; + var cornerRadius = (float)Math.Max(0, radii.TopLeft - borderThickness); if (background != null) { - context.FillRectangle(background, rect.Deflate(borders), cornerRadius); + var innerRect = new Rect(new Point(borders.Left, borders.Top), new Point(size.Width - borders.Right, size.Height - borders.Bottom)); + context.DrawRectangle(new Pen(background, borderThickness), innerRect, cornerRadius); + context.FillRectangle(background, innerRect, cornerRadius); } if (borderBrush != null && borderThickness > 0) { - context.DrawRectangle(new Pen(borderBrush, borderThickness), rect.Deflate(borderThickness), cornerRadius); + var top = borderThickness * 0.5; + var outerRect = new Rect(new Point(top, top), new Point(size.Width - top, size.Height - top)); + context.DrawRectangle(new Pen(borderBrush, borderThickness), outerRect, (float)radii.TopLeft); } } + } + + private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderGeometryKeypoints keypoints) + { + context.BeginFigure(keypoints.TopLeft, true); + + // Top + context.LineTo(keypoints.TopRight); + + // TopRight corner + var radiusX = boundRect.TopRight.X - keypoints.TopRight.X; + var radiusY = keypoints.RightTop.Y - boundRect.TopRight.Y; + if (radiusX != 0 || radiusY != 0) + { + context.ArcTo(keypoints.RightTop, new Size(radiusY, radiusY), 0, false, SweepDirection.Clockwise); + } + + // Right + context.LineTo(keypoints.RightBottom); + + // BottomRight corner + radiusX = boundRect.BottomRight.X - keypoints.BottomRight.X; + radiusY = boundRect.BottomRight.Y - keypoints.RightBottom.Y; + if (radiusX != 0 || radiusY != 0) + { + context.ArcTo(keypoints.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); + } + + // Bottom + context.LineTo(keypoints.BottomLeft); + + // BottomLeft corner + radiusX = keypoints.BottomLeft.X - boundRect.BottomLeft.X; + radiusY = boundRect.BottomLeft.Y - keypoints.LeftBottom.Y; + if (radiusX != 0 || radiusY != 0) + { + context.ArcTo(keypoints.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); + } + + // Left + context.LineTo(keypoints.LeftTop); + + // TopLeft corner + radiusX = keypoints.TopLeft.X - boundRect.TopLeft.X; + radiusY = keypoints.LeftTop.Y - boundRect.TopLeft.Y; + + if (radiusX != 0 || radiusY != 0) + { + context.ArcTo(keypoints.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); + } + + context.EndFigure(true); } private class BorderGeometryKeypoints - { + { internal BorderGeometryKeypoints(Rect boundRect, Thickness borderThickness, CornerRadius cornerRadius, bool inner) { var left = 0.5 * borderThickness.Left; @@ -135,25 +190,24 @@ namespace Avalonia.Controls.Utils } else { - leftTopY = cornerRadius.TopLeft + top + boundRect.TopLeft.Y; - topLeftX = cornerRadius.TopLeft + left + boundRect.TopLeft.X; + topLeftX = cornerRadius.TopLeft + left + boundRect.TopLeft.X; topRightX = boundRect.Width - (cornerRadius.TopRight + right) + boundRect.TopLeft.X; - rightTopY = cornerRadius.TopRight + top + boundRect.TopLeft.Y; + rightTopY = cornerRadius.TopRight + top + boundRect.TopLeft.Y; rightBottomY = boundRect.Height - (cornerRadius.BottomRight + bottom) + boundRect.TopLeft.Y; - bottomRightX = boundRect.Width - (cornerRadius.BottomRight + right) + boundRect.TopLeft.X; - bottomLeftX = cornerRadius.BottomLeft + left + boundRect.TopLeft.X; + bottomRightX = boundRect.Width - (cornerRadius.BottomRight + right) + boundRect.TopLeft.X; + bottomLeftX = cornerRadius.BottomLeft + left + boundRect.TopLeft.X; leftBottomY = boundRect.Height - (cornerRadius.BottomLeft + bottom) + boundRect.TopLeft.Y; - } + } - var leftTopX = boundRect.TopLeft.X; - var topLeftY = boundRect.TopLeft.Y; + var leftTopX = boundRect.TopLeft.X; + var topLeftY = boundRect.TopLeft.Y; var topRightY = boundRect.TopLeft.Y; - var rightTopX = boundRect.Width + boundRect.TopLeft.X; - var rightBottomX = boundRect.Width + boundRect.TopLeft.X; - var bottomRightY = boundRect.Height + boundRect.TopLeft.Y; + var rightTopX = boundRect.Width + boundRect.TopLeft.X; + var rightBottomX = boundRect.Width + boundRect.TopLeft.X; + var bottomRightY = boundRect.Height + boundRect.TopLeft.Y; var bottomLeftY = boundRect.Height + boundRect.TopLeft.Y; - var leftBottomX = boundRect.TopLeft.X; + var leftBottomX = boundRect.TopLeft.X; LeftTop = new Point(leftTopX, leftTopY); TopLeft = new Point(topLeftX, topLeftY); @@ -164,7 +218,7 @@ namespace Avalonia.Controls.Utils BottomLeft = new Point(bottomLeftX, bottomLeftY); LeftBottom = new Point(leftBottomX, leftBottomY); - //Fix overlap + // Fix overlap if (TopLeft.X > TopRight.X) { var scaledX = topLeftX / (topLeftX + topRightX) * boundRect.Width; @@ -194,66 +248,21 @@ namespace Avalonia.Controls.Utils } } - internal Point LeftTop { get; private set; } - internal Point TopLeft { get; private set; } - internal Point TopRight { get; private set; } - internal Point RightTop { get; private set; } - internal Point RightBottom { get; private set; } - internal Point BottomRight { get; private set; } - internal Point BottomLeft { get; private set; } - internal Point LeftBottom { get; private set; } - } + internal Point LeftTop { get; } - private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderGeometryKeypoints keypoints) - { - context.BeginFigure(keypoints.TopLeft, true); + internal Point TopLeft { get; } - //Top - context.LineTo(keypoints.TopRight); + internal Point TopRight { get; } - //TopRight corner - var radiusX = boundRect.TopRight.X - keypoints.TopRight.X; - var radiusY = keypoints.RightTop.Y - boundRect.TopRight.Y; - if (radiusX != 0 || radiusY != 0) - { - context.ArcTo(keypoints.RightTop, new Size(radiusY, radiusY), 0, false, SweepDirection.Clockwise); - } + internal Point RightTop { get; } - //Right - context.LineTo(keypoints.RightBottom); + internal Point RightBottom { get; } - //BottomRight corner - radiusX = boundRect.BottomRight.X - keypoints.BottomRight.X; - radiusY = boundRect.BottomRight.Y - keypoints.RightBottom.Y; - if (radiusX != 0 || radiusY != 0) - { - context.ArcTo(keypoints.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); - } - - //Bottom - context.LineTo(keypoints.BottomLeft); - - //BottomLeft corner - radiusX = keypoints.BottomLeft.X - boundRect.BottomLeft.X; - radiusY = boundRect.BottomLeft.Y - keypoints.LeftBottom.Y; - if (radiusX != 0 || radiusY != 0) - { - context.ArcTo(keypoints.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); - } + internal Point BottomRight { get; } - //Left - context.LineTo(keypoints.LeftTop); - - //TopLeft corner - radiusX = keypoints.TopLeft.X - boundRect.TopLeft.X; - radiusY = keypoints.LeftTop.Y - boundRect.TopLeft.Y; - - if (radiusX != 0 || radiusY != 0) - { - context.ArcTo(keypoints.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); - } + internal Point BottomLeft { get; } - context.EndFigure(true); + internal Point LeftBottom { get; } } } } From f619cbed484c49f9cae052e1e4eded2d163ee648 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Tue, 18 Sep 2018 08:57:33 +0200 Subject: [PATCH 3/9] Fix code style --- src/Avalonia.Controls/Utils/BorderRenderHelper.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Utils/BorderRenderHelper.cs b/src/Avalonia.Controls/Utils/BorderRenderHelper.cs index 62867f1d22..628648d090 100644 --- a/src/Avalonia.Controls/Utils/BorderRenderHelper.cs +++ b/src/Avalonia.Controls/Utils/BorderRenderHelper.cs @@ -93,15 +93,19 @@ namespace Avalonia.Controls.Utils if (background != null) { - var innerRect = new Rect(new Point(borders.Left, borders.Top), new Point(size.Width - borders.Right, size.Height - borders.Bottom)); - context.DrawRectangle(new Pen(background, borderThickness), innerRect, cornerRadius); + 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.DrawRectangle(new Pen(background), innerRect, cornerRadius); context.FillRectangle(background, innerRect, cornerRadius); } if (borderBrush != null && borderThickness > 0) { var top = borderThickness * 0.5; - var outerRect = new Rect(new Point(top, top), new Point(size.Width - top, size.Height - top)); + 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); } } From 292b1d0253ee005f8a84a1034b71bc028a3dd20f Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Tue, 18 Sep 2018 10:06:57 +0200 Subject: [PATCH 4/9] Remove extra DrawRectangle call --- src/Avalonia.Controls/Utils/BorderRenderHelper.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Utils/BorderRenderHelper.cs b/src/Avalonia.Controls/Utils/BorderRenderHelper.cs index 628648d090..a91e6a3a48 100644 --- a/src/Avalonia.Controls/Utils/BorderRenderHelper.cs +++ b/src/Avalonia.Controls/Utils/BorderRenderHelper.cs @@ -89,20 +89,19 @@ namespace Avalonia.Controls.Utils else { var borderThickness = borders.Top; - var cornerRadius = (float)Math.Max(0, radii.TopLeft - borderThickness); + 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.DrawRectangle(new Pen(background), innerRect, cornerRadius); context.FillRectangle(background, innerRect, cornerRadius); } if (borderBrush != null && borderThickness > 0) { - var top = borderThickness * 0.5; var topLeft = new Point(top, top); var bottomRight = new Point(size.Width - top, size.Height - top); var outerRect = new Rect(topLeft, bottomRight); From d4c102998cae116d9d961c05d1da2d0a957b6db4 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 26 Sep 2018 11:56:11 +0200 Subject: [PATCH 5/9] Updated portable.xml submodule. --- .../Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github index 31ea8e6900..8e4700d4b2 160000 --- a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github +++ b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github @@ -1 +1 @@ -Subproject commit 31ea8e6900d859a8d1bf45972954b075d2a59f30 +Subproject commit 8e4700d4b24935ed5400e5e0d6fce96b5b4a317a From 63928f62420df2f96f0cbee1366d112b367c5241 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 26 Sep 2018 13:09:27 +0100 Subject: [PATCH 6/9] [Image] Measure is triggered when source or stretch property is changed. --- src/Avalonia.Controls/Image.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia.Controls/Image.cs b/src/Avalonia.Controls/Image.cs index 802b700a07..40203bab02 100644 --- a/src/Avalonia.Controls/Image.cs +++ b/src/Avalonia.Controls/Image.cs @@ -26,6 +26,7 @@ namespace Avalonia.Controls static Image() { AffectsRender(SourceProperty, StretchProperty); + AffectsMeasure(SourceProperty, StretchProperty); } /// From f1622f48026a4f4e825df98a128146bc4cbd75f7 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 28 Sep 2018 17:56:56 +0300 Subject: [PATCH 7/9] don't reset data template on attached to visual tree, but on attached to logical tree --- src/Avalonia.Controls/Presenters/ContentPresenter.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index 8d703cfc1c..83d8616e90 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -197,13 +197,6 @@ namespace Avalonia.Controls.Presenters } } - /// - protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) - { - base.OnAttachedToVisualTree(e); - _dataTemplate = null; - } - /// /// Updates the control based on the control's . /// @@ -268,6 +261,7 @@ namespace Avalonia.Controls.Presenters protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) { base.OnAttachedToLogicalTree(e); + _dataTemplate = null; _createdChild = false; InvalidateMeasure(); } From cabdb077a13769eaf1e0219129fad51955dcd259 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 28 Sep 2018 18:33:10 +0300 Subject: [PATCH 8/9] add failing test for #1930 PathMarkupParser does not end figure when trailing spaces (newlines) are present --- .../Media/PathMarkupParserTests.cs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs index 8dca52e6a7..5570378063 100644 --- a/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs @@ -9,6 +9,8 @@ namespace Avalonia.Visuals.UnitTests.Media { using System.Globalization; using System.IO; + using Avalonia.Platform; + using Moq; public class PathMarkupParserTests { @@ -18,7 +20,7 @@ namespace Avalonia.Visuals.UnitTests.Media var pathGeometry = new PathGeometry(); using (var context = new PathGeometryContext(pathGeometry)) using (var parser = new PathMarkupParser(context)) - { + { parser.Parse("M10 10"); var figure = pathGeometry.Figures[0]; @@ -202,6 +204,25 @@ namespace Avalonia.Visuals.UnitTests.Media } } + [Theory] + [InlineData("M0 0L10 10")] + [InlineData("M0 0L10 10z")] + [InlineData("M0 0L10 10 \n ")] + [InlineData("M0 0L10 10z \n ")] + [InlineData("M0 0L10 10 ")] + [InlineData("M0 0L10 10z ")] + public void Should_AlwaysEndFigure(string pathData) + { + var context = new Mock(); + + using (var parser = new PathMarkupParser(context.Object)) + { + parser.Parse(pathData); + } + + context.Verify(v => v.EndFigure(It.IsAny()), Times.AtLeastOnce()); + } + [Theory] [InlineData("0 0")] [InlineData("j")] @@ -215,4 +236,4 @@ namespace Avalonia.Visuals.UnitTests.Media } } } -} \ No newline at end of file +} From 6844cc1450dc7046fdb59e85dc46f2c223195411 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 28 Sep 2018 18:33:57 +0300 Subject: [PATCH 9/9] fixes #1930 PathMarkupParser ends figure always --- src/Avalonia.Visuals/Media/PathMarkupParser.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Visuals/Media/PathMarkupParser.cs b/src/Avalonia.Visuals/Media/PathMarkupParser.cs index 656526890a..8852883dcc 100644 --- a/src/Avalonia.Visuals/Media/PathMarkupParser.cs +++ b/src/Avalonia.Visuals/Media/PathMarkupParser.cs @@ -107,7 +107,7 @@ namespace Avalonia.Media { if(!ReadCommand(ref span, out var command, out var relative)) { - return; + break; } bool initialCommand = true; @@ -565,4 +565,4 @@ namespace Avalonia.Media return true; } } -} \ No newline at end of file +}