Browse Source

Merge pull request #4339 from Gillibald/fixes/TextLineCaretNavigation

Make sure we always hit the outer edge at the start/end of a TextLine
release/0.10.0-preview2
danwalmsley 6 years ago
committed by GitHub
parent
commit
5184c1551e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/Avalonia.Visuals/Media/CharacterHit.cs
  2. 18
      src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs
  3. 5
      tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs

2
src/Avalonia.Visuals/Media/CharacterHit.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics;
namespace Avalonia.Media namespace Avalonia.Media
{ {
@ -9,6 +10,7 @@ namespace Avalonia.Media
/// The CharacterHit structure provides information about the index of the first /// The CharacterHit structure provides information about the index of the first
/// character that got hit as well as information about leading or trailing edge. /// character that got hit as well as information about leading or trailing edge.
/// </remarks> /// </remarks>
[DebuggerDisplay("CharacterHit({FirstCharacterIndex}, {TrailingLength})")]
public readonly struct CharacterHit : IEquatable<CharacterHit> public readonly struct CharacterHit : IEquatable<CharacterHit>
{ {
/// <summary> /// <summary>

18
src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs

@ -236,7 +236,7 @@ namespace Avalonia.Media.TextFormatting
var codepointIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength; var codepointIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
if (codepointIndex >= TextRange.Start + TextRange.Length) if (codepointIndex > TextRange.End)
{ {
return false; // Cannot go forward anymore return false; // Cannot go forward anymore
} }
@ -249,11 +249,14 @@ namespace Avalonia.Media.TextFormatting
var foundCharacterHit = run.GlyphRun.FindNearestCharacterHit(characterHit.FirstCharacterIndex + characterHit.TrailingLength, out _); var foundCharacterHit = run.GlyphRun.FindNearestCharacterHit(characterHit.FirstCharacterIndex + characterHit.TrailingLength, out _);
nextCharacterHit = characterHit.TrailingLength != 0 ? var isAtEnd = foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength ==
TextRange.Length;
nextCharacterHit = isAtEnd || characterHit.TrailingLength != 0 ?
foundCharacterHit : foundCharacterHit :
new CharacterHit(foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength); new CharacterHit(foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength);
if (nextCharacterHit.FirstCharacterIndex > characterHit.FirstCharacterIndex) if (isAtEnd || nextCharacterHit.FirstCharacterIndex > characterHit.FirstCharacterIndex)
{ {
return true; return true;
} }
@ -272,6 +275,13 @@ namespace Avalonia.Media.TextFormatting
/// <returns></returns> /// <returns></returns>
private bool TryFindPreviousCharacterHit(CharacterHit characterHit, out CharacterHit previousCharacterHit) private bool TryFindPreviousCharacterHit(CharacterHit characterHit, out CharacterHit previousCharacterHit)
{ {
if (characterHit.FirstCharacterIndex == TextRange.Start)
{
previousCharacterHit = new CharacterHit(TextRange.Start);
return true;
}
previousCharacterHit = characterHit; previousCharacterHit = characterHit;
var codepointIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength; var codepointIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
@ -354,7 +364,7 @@ namespace Avalonia.Media.TextFormatting
return new ShapedTextCharacters(glyphRun, textRun.Properties); return new ShapedTextCharacters(glyphRun, textRun.Properties);
} }
/// <summary> /// <summary>
/// Gets the shaped width of specified shaped text characters. /// Gets the shaped width of specified shaped text characters.
/// </summary> /// </summary>

5
tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Media.TextFormatting; using Avalonia.Media.TextFormatting;
@ -101,7 +102,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal(firstCharacterHit.FirstCharacterIndex, previousCharacterHit.FirstCharacterIndex); Assert.Equal(firstCharacterHit.FirstCharacterIndex, previousCharacterHit.FirstCharacterIndex);
Assert.Equal(firstCharacterHit.TrailingLength, previousCharacterHit.TrailingLength); Assert.Equal(0, previousCharacterHit.TrailingLength);
previousCharacterHit = new CharacterHit(clusters[^1], text.Length - clusters[^1]); previousCharacterHit = new CharacterHit(clusters[^1], text.Length - clusters[^1]);
@ -119,7 +120,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal(firstCharacterHit.FirstCharacterIndex, previousCharacterHit.FirstCharacterIndex); Assert.Equal(firstCharacterHit.FirstCharacterIndex, previousCharacterHit.FirstCharacterIndex);
Assert.Equal(firstCharacterHit.TrailingLength, previousCharacterHit.TrailingLength); Assert.Equal(0, previousCharacterHit.TrailingLength);
} }
} }

Loading…
Cancel
Save