From 5921d359c83a4149680265a9358172fe7e52b33d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 4 Nov 2019 15:08:21 +0000 Subject: [PATCH 1/7] fix hit testing skia formatted text. --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index eb7b65cdce..718d10a694 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -99,9 +99,17 @@ namespace Avalonia.Skia public TextHitTestResult HitTestPoint(Point point) { float y = (float)point.Y; - var line = _skiaLines.Find(l => l.Top <= y && (l.Top + l.Height) > y); - if (!line.Equals(default(AvaloniaFormattedTextLine))) + AvaloniaFormattedTextLine line = default; + + int i = 0; + + while(_skiaLines[i].Top < y && i < _skiaLines.Count) + { + line = _skiaLines[i++]; + } + + if (!line.Equals(default)) { var rects = GetRects(); From 075aeecebf1694d4c35c27f75a164a9280e9f784 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 4 Nov 2019 15:59:17 +0000 Subject: [PATCH 2/7] fix skia formatted text impl hit testing. --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 28 +++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index 718d10a694..dfdbfef136 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -102,12 +102,17 @@ namespace Avalonia.Skia AvaloniaFormattedTextLine line = default; - int i = 0; - - while(_skiaLines[i].Top < y && i < _skiaLines.Count) + foreach(var currentLine in _skiaLines) { - line = _skiaLines[i++]; - } + if(currentLine.Top <= y) + { + line = currentLine; + } + else + { + break; + } + } if (!line.Equals(default)) { @@ -135,12 +140,15 @@ namespace Avalonia.Skia line.Length : (line.Length - 1); } - return new TextHitTestResult + if (y < line.Top + line.Height) { - IsInside = false, - TextPosition = line.Start + offset, - IsTrailing = Text.Length == (line.Start + offset + 1) - }; + return new TextHitTestResult + { + IsInside = false, + TextPosition = line.Start + offset, + IsTrailing = Text.Length == (line.Start + offset + 1) + }; + } } bool end = point.X > _bounds.Width || point.Y > _lines.Sum(l => l.Height); From eb1241eea36d45b000792f373952e9e58df6e321 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 4 Nov 2019 16:26:45 +0000 Subject: [PATCH 3/7] fix skia formatted text unit tests. --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index dfdbfef136..a5e56b1d7a 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -102,14 +102,18 @@ namespace Avalonia.Skia AvaloniaFormattedTextLine line = default; + float nextTop = 0; + foreach(var currentLine in _skiaLines) { if(currentLine.Top <= y) { line = currentLine; + nextTop = currentLine.Top + currentLine.Height; } else { + nextTop = currentLine.Top; break; } } @@ -140,7 +144,7 @@ namespace Avalonia.Skia line.Length : (line.Length - 1); } - if (y < line.Top + line.Height) + if (y < nextTop) { return new TextHitTestResult { From 620be6f1050c014576f8079e6abbd29acc90772b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 5 Nov 2019 09:32:22 +0000 Subject: [PATCH 4/7] add failing unit test for empty textbox hit test. --- tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs b/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs index 353123ab2a..8eedb1dde7 100644 --- a/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs +++ b/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs @@ -157,6 +157,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media [InlineData(stringmiddle3lines, 500, 13, false, false, 8)] [InlineData(stringmiddle3lines, 30, 25, false, false, 9)] [InlineData(stringmiddle3lines, -1, 30, false, false, 10)] + [InlineData("", 0, 0, false, false, 0)] public void Should_HitTestPoint_Correctly(string input, double x, double y, bool isInside, bool isTrailing, int pos) From 69c24dc99df33a7eb8ee544ccba0a465acd9a632 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 5 Nov 2019 09:33:09 +0000 Subject: [PATCH 5/7] fix bug in skia empty formatted text hit test. --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index a5e56b1d7a..07e3700fc2 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -118,7 +118,7 @@ namespace Avalonia.Skia } } - if (!line.Equals(default)) + if (!line.Equals(default(AvaloniaFormattedTextLine))) { var rects = GetRects(); From 86d21f27a7fec5cb595fa6a7b1432611f9f26ee8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 5 Nov 2019 10:01:25 +0000 Subject: [PATCH 6/7] fix empty text hit test. direct2d --- src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs index b73deb1f0a..ede66fb265 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs @@ -72,7 +72,7 @@ namespace Avalonia.Direct2D1.Media return new TextHitTestResult { - IsInside = isInside, + IsInside = result.Width == 0 ? false : (bool)isInside, TextPosition = result.TextPosition, IsTrailing = isTrailingHit, }; From 5b3e2320a8eff35156467ce8b4025ca2df7827bb Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 5 Nov 2019 10:15:36 +0000 Subject: [PATCH 7/7] remove unit tests, skia and direct2d behave differently and making them match is beyond the scope of this bug fix. --- src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs | 2 +- tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs index ede66fb265..b73deb1f0a 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs @@ -72,7 +72,7 @@ namespace Avalonia.Direct2D1.Media return new TextHitTestResult { - IsInside = result.Width == 0 ? false : (bool)isInside, + IsInside = isInside, TextPosition = result.TextPosition, IsTrailing = isTrailingHit, }; diff --git a/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs b/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs index 8eedb1dde7..353123ab2a 100644 --- a/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs +++ b/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs @@ -157,7 +157,6 @@ namespace Avalonia.Direct2D1.RenderTests.Media [InlineData(stringmiddle3lines, 500, 13, false, false, 8)] [InlineData(stringmiddle3lines, 30, 25, false, false, 9)] [InlineData(stringmiddle3lines, -1, 30, false, false, 10)] - [InlineData("", 0, 0, false, false, 0)] public void Should_HitTestPoint_Correctly(string input, double x, double y, bool isInside, bool isTrailing, int pos)