Browse Source

Fix text wrapping behavior (#7397)

* Allow one-character runs line breaks

* Remove unuseful ignored nullable

* Prevent redundant allocations

* Fix empty line handling

* Update TextFormatterImpl.cs

Co-authored-by: Benedikt Stebner <b.stebner@outlook.de>
Co-authored-by: Benedikt Stebner <Gillibald@users.noreply.github.com>
pull/7411/head
ingen084 5 years ago
committed by GitHub
parent
commit
3908e4d71d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
  2. 10
      src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs

23
src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs

@ -193,7 +193,7 @@ namespace Avalonia.Media.TextFormatting
{ {
var currentRun = textRuns[i]; var currentRun = textRuns[i];
if (currentLength + currentRun.GlyphRun.Characters.Length < length) if (currentLength + currentRun.GlyphRun.Characters.Length <= length)
{ {
currentLength += currentRun.GlyphRun.Characters.Length; currentLength += currentRun.GlyphRun.Characters.Length;
continue; continue;
@ -283,26 +283,26 @@ namespace Avalonia.Media.TextFormatting
{ {
var shapedCharacters = previousLineBreak.RemainingCharacters[index]; var shapedCharacters = previousLineBreak.RemainingCharacters[index];
if (shapedCharacters == null)
{
continue;
}
textRuns.Add(shapedCharacters); textRuns.Add(shapedCharacters);
if (TryGetLineBreak(shapedCharacters, out var runLineBreak)) if (TryGetLineBreak(shapedCharacters, out var runLineBreak))
{ {
var splitResult = SplitTextRuns(textRuns, currentLength + runLineBreak.PositionWrap); var splitResult = SplitTextRuns(textRuns, currentLength + runLineBreak.PositionWrap);
if (splitResult.Second == null)
{
return splitResult.First;
}
if (++index < previousLineBreak.RemainingCharacters.Count) if (++index < previousLineBreak.RemainingCharacters.Count)
{ {
for (; index < previousLineBreak.RemainingCharacters.Count; index++) for (; index < previousLineBreak.RemainingCharacters.Count; index++)
{ {
splitResult.Second!.Add(previousLineBreak.RemainingCharacters[index]); splitResult.Second.Add(previousLineBreak.RemainingCharacters[index]);
} }
} }
nextLineBreak = new TextLineBreak(splitResult.Second!); nextLineBreak = new TextLineBreak(splitResult.Second);
return splitResult.First; return splitResult.First;
} }
@ -346,7 +346,10 @@ namespace Avalonia.Media.TextFormatting
{ {
var splitResult = SplitTextRuns(textRuns, currentLength + runLineBreak.PositionWrap); var splitResult = SplitTextRuns(textRuns, currentLength + runLineBreak.PositionWrap);
nextLineBreak = new TextLineBreak(splitResult.Second!); if (splitResult.Second != null)
{
nextLineBreak = new TextLineBreak(splitResult.Second);
}
return splitResult.First; return splitResult.First;
} }
@ -532,7 +535,7 @@ namespace Avalonia.Media.TextFormatting
/// <returns>The text range that is covered by the text runs.</returns> /// <returns>The text range that is covered by the text runs.</returns>
private static TextRange GetTextRange(IReadOnlyList<TextRun> textRuns) private static TextRange GetTextRange(IReadOnlyList<TextRun> textRuns)
{ {
if (textRuns is null || textRuns.Count == 0) if (textRuns.Count == 0)
{ {
return new TextRange(); return new TextRange();
} }

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

@ -401,14 +401,12 @@ namespace Avalonia.Media.TextFormatting
previousLine = textLine; previousLine = textLine;
if (currentPosition != _text.Length || textLine.TextLineBreak?.RemainingCharacters == null) if (currentPosition == _text.Length && textLine.NewLineLength > 0)
{ {
continue; var emptyTextLine = CreateEmptyTextLine(currentPosition);
}
var emptyTextLine = CreateEmptyTextLine(currentPosition); textLines.Add(emptyTextLine);
}
textLines.Add(emptyTextLine);
} }
Size = new Size(width, height); Size = new Size(width, height);

Loading…
Cancel
Save