From df35f61906c94403c0475448c93690a275fa5a22 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Thu, 23 Apr 2020 14:44:53 +0300 Subject: [PATCH 1/4] add failing tests for parsing points in xaml --- .../PointsListTypeConverterTests.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/Avalonia.Markup.Xaml.UnitTests/Converters/PointsListTypeConverterTests.cs diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Converters/PointsListTypeConverterTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/PointsListTypeConverterTests.cs new file mode 100644 index 0000000000..1e8153044a --- /dev/null +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/PointsListTypeConverterTests.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Avalonia.Controls.Shapes; +using Avalonia.Markup.Xaml.Converters; +using Xunit; + +namespace Avalonia.Markup.Xaml.UnitTests.Converters +{ + public class PointsListTypeConverterTests + { + [Theory] + [InlineData("1,2 3,4")] + [InlineData("1 2 3 4")] + [InlineData("1 2,3 4")] + [InlineData("1,2,3,4")] + public void Should_Parse_Points_in_Xaml(string input) + { + var xaml = $""; + var loader = new AvaloniaXamlLoader(); + var polygon = (Polygon)loader.Load(xaml); + + var points = polygon.Points; + + Assert.Equal(2, points.Count); + Assert.Equal(new Point(1, 2), points[0]); + Assert.Equal(new Point(3, 4), points[1]); + } + } +} From fb1da608f88989ad9eaf00c97f5318cb005dbd4b Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Thu, 23 Apr 2020 14:45:38 +0300 Subject: [PATCH 2/4] add failing tests for point parsing --- .../Converters/PointsListTypeConverterTests.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Converters/PointsListTypeConverterTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/PointsListTypeConverterTests.cs index 1e8153044a..b060905f38 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Converters/PointsListTypeConverterTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Converters/PointsListTypeConverterTests.cs @@ -7,6 +7,22 @@ namespace Avalonia.Markup.Xaml.UnitTests.Converters { public class PointsListTypeConverterTests { + [Theory] + [InlineData("1,2 3,4")] + [InlineData("1 2 3 4")] + [InlineData("1 2,3 4")] + [InlineData("1,2,3,4")] + public void TypeConverter_Should_Parse(string input) + { + var conv = new PointsListTypeConverter(); + + var points = (IList)conv.ConvertFrom(input); + + Assert.Equal(2, points.Count); + Assert.Equal(new Point(1, 2), points[0]); + Assert.Equal(new Point(3, 4), points[1]); + } + [Theory] [InlineData("1,2 3,4")] [InlineData("1 2 3 4")] From 28448b1041ec23169e277b97f93cd759e1716814 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Thu, 23 Apr 2020 14:47:14 +0300 Subject: [PATCH 3/4] improve points parsing in PointsListTypeConverter - fixes #3813 --- .../Converters/PointsListTypeConverter.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/PointsListTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/PointsListTypeConverter.cs index 871ab77cac..7246d8c583 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Converters/PointsListTypeConverter.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Converters/PointsListTypeConverter.cs @@ -4,7 +4,7 @@ using System.Globalization; namespace Avalonia.Markup.Xaml.Converters { - using System.ComponentModel; + using System.ComponentModel; public class PointsListTypeConverter : TypeConverter { @@ -16,11 +16,11 @@ namespace Avalonia.Markup.Xaml.Converters public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { string strValue = (string)value; - string[] pointStrs = strValue.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); - var result = new List(pointStrs.Length); - foreach (var pointStr in pointStrs) + string[] pointStrs = strValue.Split(new[] { ' ', '\t', '\r', '\n', ',' }, StringSplitOptions.RemoveEmptyEntries); + var result = new List(pointStrs.Length / 2); + for (int i = 0; i < pointStrs.Length; i += 2) { - result.Add(Point.Parse(pointStr)); + result.Add(Point.Parse($"{pointStrs[i]} {pointStrs[i + 1]}")); } return result; From 1217a44bc3c477d96657e6a6850c5c1833ad106a Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 24 Apr 2020 11:58:42 +0300 Subject: [PATCH 4/4] use StringTokenizer to parse PointsList --- .../Converters/PointsListTypeConverter.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/PointsListTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/PointsListTypeConverter.cs index 7246d8c583..099ffa8c8c 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Converters/PointsListTypeConverter.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Converters/PointsListTypeConverter.cs @@ -5,6 +5,7 @@ using System.Globalization; namespace Avalonia.Markup.Xaml.Converters { using System.ComponentModel; + using Avalonia.Utilities; public class PointsListTypeConverter : TypeConverter { @@ -15,15 +16,17 @@ namespace Avalonia.Markup.Xaml.Converters public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - string strValue = (string)value; - string[] pointStrs = strValue.Split(new[] { ' ', '\t', '\r', '\n', ',' }, StringSplitOptions.RemoveEmptyEntries); - var result = new List(pointStrs.Length / 2); - for (int i = 0; i < pointStrs.Length; i += 2) + var points = new List(); + + using (var tokenizer = new StringTokenizer((string)value, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PointsList.")) { - result.Add(Point.Parse($"{pointStrs[i]} {pointStrs[i + 1]}")); + while (tokenizer.TryReadDouble(out double x)) + { + points.Add(new Point(x, tokenizer.ReadDouble())); + } } - return result; + return points; } } }