Browse Source

Ignore invisible characters

pull/4591/head
Benedikt Schroeder 6 years ago
parent
commit
a2a0fba1c2
  1. 5
      src/Avalonia.Visuals/ApiCompatBaseline.txt
  2. 6
      src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs
  3. 4
      src/Avalonia.Visuals/Media/TextFormatting/TextLine.cs
  4. 17
      src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs
  5. 26
      tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs

5
src/Avalonia.Visuals/ApiCompatBaseline.txt

@ -0,0 +1,5 @@
Compat issues with assembly Avalonia.Visuals:
CannotAddAbstractMembers : Member 'public Avalonia.Media.TextFormatting.TextLineBreak Avalonia.Media.TextFormatting.TextLine.TextLineBreak' is abstract in the implementation but is missing in the contract.
MembersMustExist : Member 'public Avalonia.Media.TextFormatting.TextLineBreak Avalonia.Media.TextFormatting.TextLine.LineBreak.get()' does not exist in the implementation but it does exist in the contract.
CannotAddAbstractMembers : Member 'public Avalonia.Media.TextFormatting.TextLineBreak Avalonia.Media.TextFormatting.TextLine.TextLineBreak.get()' is abstract in the implementation but is missing in the contract.
Total Issues: 3

6
src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs

@ -221,7 +221,7 @@ namespace Avalonia.Media.TextFormatting
while (currentPosition < _text.Length)
{
var textLine = TextFormatter.Current.FormatLine(textSource, currentPosition, MaxWidth,
_paragraphProperties, previousLine?.LineBreak);
_paragraphProperties, previousLine?.TextLineBreak);
currentPosition += textLine.TextRange.Length;
@ -230,7 +230,7 @@ namespace Avalonia.Media.TextFormatting
if (textLines.Count == MaxLines || !double.IsPositiveInfinity(MaxHeight) &&
height + textLine.LineMetrics.Size.Height > MaxHeight)
{
if (previousLine?.LineBreak != null && _textTrimming != TextTrimming.None)
if (previousLine?.TextLineBreak != null && _textTrimming != TextTrimming.None)
{
var collapsedLine =
previousLine.Collapse(GetCollapsingProperties(MaxWidth));
@ -255,7 +255,7 @@ namespace Avalonia.Media.TextFormatting
previousLine = textLine;
if (currentPosition != _text.Length || textLine.LineBreak == null)
if (currentPosition != _text.Length || textLine.TextLineBreak == null)
{
continue;
}

4
src/Avalonia.Visuals/Media/TextFormatting/TextLine.cs

@ -35,9 +35,9 @@ namespace Avalonia.Media.TextFormatting
/// Gets the state of the line when broken by line breaking process.
/// </summary>
/// <returns>
/// A <see cref="LineBreak"/> value that represents the line break.
/// A <see cref="TextLineBreak"/> value that represents the line break.
/// </returns>
public abstract TextLineBreak LineBreak { get; }
public abstract TextLineBreak TextLineBreak { get; }
/// <summary>
/// Gets a value that indicates whether the line is collapsed.

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

@ -13,7 +13,7 @@ namespace Avalonia.Media.TextFormatting
{
_textRuns = textRuns;
LineMetrics = lineMetrics;
LineBreak = lineBreak;
TextLineBreak = lineBreak;
HasCollapsed = hasCollapsed;
}
@ -27,7 +27,7 @@ namespace Avalonia.Media.TextFormatting
public override TextLineMetrics LineMetrics { get; }
/// <inheritdoc/>
public override TextLineBreak LineBreak { get; }
public override TextLineBreak TextLineBreak { get; }
/// <inheritdoc/>
public override bool HasCollapsed { get; }
@ -122,7 +122,7 @@ namespace Avalonia.Media.TextFormatting
textLineMetrics = new TextLineMetrics(new Size(shapedWidth, LineMetrics.Size.Height),
LineMetrics.TextBaseline, textRange, false);
return new TextLineImpl(shapedTextCharacters, textLineMetrics, LineBreak, true);
return new TextLineImpl(shapedTextCharacters, textLineMetrics, TextLineBreak, true);
}
availableWidth -= currentRun.GlyphRun.Bounds.Width;
@ -268,6 +268,17 @@ namespace Avalonia.Media.TextFormatting
var isAtEnd = foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength ==
TextRange.Length;
var characterIndex = codepointIndex - run.Text.Start;
var codepoint = Codepoint.ReadAt(run.GlyphRun.Characters, characterIndex, out _);
if (codepoint.IsBreakChar)
{
foundCharacterHit = run.GlyphRun.FindNearestCharacterHit(codepointIndex - 1, out _);
isAtEnd = true;
}
nextCharacterHit = isAtEnd || characterHit.TrailingLength != 0 ?
foundCharacterHit :
new CharacterHit(foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength);

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

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Avalonia.Media;
using Avalonia.Media.TextFormatting;
@ -331,6 +333,30 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
}
}
[Fact]
public void Should_Ignore_Invisible_Characters()
{
using (Start())
{
var defaultTextRunProperties =
new GenericTextRunProperties(Typeface.Default);
const string text = "01234567🎉\n";
var source = new SingleBufferTextSource(text, defaultTextRunProperties);
var textParagraphProperties = new GenericTextParagraphProperties(defaultTextRunProperties);
var formatter = TextFormatter.Current;
var textLine = formatter.FormatLine(source, 0, double.PositiveInfinity, textParagraphProperties);
var nextCharacterHit = textLine.GetNextCaretCharacterHit(new CharacterHit(8, 2));
Assert.Equal(new CharacterHit(8, 2), nextCharacterHit);
}
}
private static IDisposable Start()
{
var disposable = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface

Loading…
Cancel
Save