diff --git a/src/Avalonia.Visuals/Media/GlyphRun.cs b/src/Avalonia.Visuals/Media/GlyphRun.cs index a5e70ae2b1..43151deece 100644 --- a/src/Avalonia.Visuals/Media/GlyphRun.cs +++ b/src/Avalonia.Visuals/Media/GlyphRun.cs @@ -193,16 +193,15 @@ namespace Avalonia.Media { var distance = 0.0; - var end = _glyphClusters.AsSpan().BinarySearch((ushort)characterHit.FirstCharacterIndex); + var end = characterHit.FirstCharacterIndex + characterHit.TrailingLength; - if (end < 0) + for (var i = 0; i < _glyphClusters.Length; i++) { - return 0; - } + if (_glyphClusters[i] >= end) + { + break; + } - // If TrailingLength > 0 we have to use the next cluster while TrailingLength != 0 - for (var i = 0; i < end + characterHit.TrailingLength; i++) - { if (GlyphAdvances.IsEmpty) { var glyph = GlyphIndices[i]; @@ -279,7 +278,6 @@ namespace Avalonia.Media public CharacterHit GetNextCaretCharacterHit(CharacterHit characterHit) { - if (characterHit.TrailingLength == 0) { return FindNearestCharacterHit(characterHit.FirstCharacterIndex, out _); @@ -412,7 +410,7 @@ namespace Avalonia.Media { if (_glyphRunImpl != null) { - throw new InvalidOperationException("GlyphRun can't be changed after is has been initialized.'"); + throw new InvalidOperationException("GlyphRun can't be changed after it has been initialized.'"); } field = value; diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/GlyphRunNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/GlyphRunNode.cs index b862dc218f..b3c4fdbac0 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/GlyphRunNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/GlyphRunNode.cs @@ -10,7 +10,7 @@ using Avalonia.VisualTree; namespace Avalonia.Rendering.SceneGraph { /// - /// A node in the scene graph which represents a text draw. + /// A node in the scene graph which represents a glyph run draw. /// internal class GlyphRunNode : BrushDrawOperation { @@ -48,7 +48,7 @@ namespace Avalonia.Rendering.SceneGraph public IBrush Foreground { get; } /// - /// Gets the text to draw. + /// Gets the glyph run to draw. /// public GlyphRun GlyphRun { get; } @@ -72,7 +72,7 @@ namespace Avalonia.Rendering.SceneGraph /// /// The transform of the other draw operation. /// The foreground of the other draw operation. - /// The text of the other draw operation. + /// The glyph run of the other draw operation. /// True if the draw operations are the same, otherwise false. /// /// The properties of the other draw operation are passed in as arguments to prevent diff --git a/tests/Avalonia.Visuals.UnitTests/Media/GlyphRunTests.cs b/tests/Avalonia.Visuals.UnitTests/Media/GlyphRunTests.cs index c0820f2046..f5e4cdc099 100644 --- a/tests/Avalonia.Visuals.UnitTests/Media/GlyphRunTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Media/GlyphRunTests.cs @@ -13,12 +13,30 @@ namespace Avalonia.Visuals.UnitTests.Media .Bind().ToSingleton(); } + [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 0, 0 }, 0, 0, 0)] + [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 0, 0 }, 0, 3, 30)] + [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 1, 2 }, 1, 0, 10)] + [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 1, 2 }, 2, 0, 20)] + [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 1, 2 }, 2, 1, 30)] + [Theory] + public void Should_Get_Distance_From_CharacterHit(double[] advances, ushort[] clusters, int start, int trailingLength, double expectedDistance) + { + using (var glyphRun = CreateGlyphRun(advances, clusters)) + { + var characterHit = new CharacterHit(start, trailingLength); + + var distance = glyphRun.GetDistanceFromCharacterHit(characterHit); + + Assert.Equal(expectedDistance, distance); + } + } + [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 0, 0 }, 25.0, 0, 3, true)] [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 1, 2 }, 20.0, 2, 0, true)] [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 1, 2 }, 26.0, 2, 1, true)] [InlineData(new double[] { 10, 10, 10 }, new ushort[] { 0, 1, 2 }, 35.0, 2, 1, false)] [Theory] - public void Should_Get_TextBounds_FromDistance(double[] advances, ushort[] clusters, double distance, int start, + public void Should_Get_CharacterHit_FromDistance(double[] advances, ushort[] clusters, double distance, int start, int trailingLengthExpected, bool isInsideExpected) { using (var glyphRun = CreateGlyphRun(advances, clusters))