Browse Source

More TextAlignment fixes

pull/8347/head
Benedikt Stebner 4 years ago
parent
commit
6502fa1ef7
  1. 4
      src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs
  2. 2
      src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
  3. 97
      tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs

4
src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs

@ -404,6 +404,10 @@ namespace Avalonia.Media.TextFormatting
{
endOfLine = textEndOfLine;
textSourceLength += textEndOfLine.TextSourceLength;
textRuns.Add(textRun);
break;
}

2
src/Avalonia.Base/Media/TextFormatting/TextLayout.cs

@ -439,7 +439,7 @@ namespace Avalonia.Media.TextFormatting
var textLine = TextFormatter.Current.FormatLine(_textSource, _textSourceLength, MaxWidth,
_paragraphProperties, previousLine?.TextLineBreak);
if(textLine == null || textLine.Length == 0)
if(textLine == null || textLine.Length == 0 || textLine.TextRuns.Count == 0 && textLine.TextLineBreak?.TextEndOfLine is TextEndOfParagraph)
{
if(previousLine != null && previousLine.NewLineLength > 0)
{

97
tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs

@ -134,7 +134,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var defaultProperties = new GenericTextRunProperties(Typeface.Default);
const string text = "👍 👍 👍 👍";
var textSource = new SingleBufferTextSource(text, defaultProperties);
var formatter = new TextFormatterImpl();
@ -144,7 +144,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
new GenericTextParagraphProperties(defaultProperties));
Assert.Equal(1, textLine.TextRuns.Count);
}
}
}
[Fact]
@ -163,9 +163,9 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var textLine =
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
new GenericTextParagraphProperties(defaultProperties));
var firstRun = textLine.TextRuns[0];
Assert.Equal(4, firstRun.Text.Length);
}
}
@ -191,7 +191,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var textLine =
formatter.FormatLine(textSource, currentPosition, 1,
new GenericTextParagraphProperties(defaultProperties, textWrap : TextWrapping.WrapWithOverflow));
new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.WrapWithOverflow));
if (text.Length - currentPosition > expectedCharactersPerLine)
{
@ -347,8 +347,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
}
}
[InlineData("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor",
new []{ "Lorem ipsum ", "dolor sit amet, ", "consectetur ", "adipisicing elit, ", "sed do eiusmod "})]
[InlineData("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor",
new[] { "Lorem ipsum ", "dolor sit amet, ", "consectetur ", "adipisicing elit, ", "sed do eiusmod " })]
[Theory]
public void Should_Produce_Wrapped_And_Trimmed_Lines(string text, string[] expectedLines)
@ -368,7 +368,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
new ValueSpan<TextRunProperties>(28, 28,
new GenericTextRunProperties(new Typeface("Verdana", FontStyle.Italic),32))
};
var textSource = new FormattedTextSource(text.AsMemory(), defaultProperties, styleSpans);
var formatter = new TextFormatterImpl();
@ -389,19 +389,19 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
if (textLine.Width > 300 || currentHeight + textLine.Height > 240)
{
textLine = textLine.Collapse(new TextTrailingWordEllipsis(new ReadOnlySlice<char>(new[] {TextTrimming.s_defaultEllipsisChar}), 300, defaultProperties));
textLine = textLine.Collapse(new TextTrailingWordEllipsis(new ReadOnlySlice<char>(new[] { TextTrimming.s_defaultEllipsisChar }), 300, defaultProperties));
}
currentHeight += textLine.Height;
var currentText = text.Substring(textLine.FirstTextSourceIndex, textLine.Length);
Assert.Equal(expectedLines[currentLineIndex], currentText);
currentLineIndex++;
}
Assert.Equal(expectedLines.Length,currentLineIndex);
Assert.Equal(expectedLines.Length, currentLineIndex);
}
}
@ -412,11 +412,11 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
[InlineData("0123456789", TextAlignment.Left, FlowDirection.RightToLeft)]
[InlineData("0123456789", TextAlignment.Center, FlowDirection.RightToLeft)]
[InlineData("0123456789", TextAlignment.Right, FlowDirection.RightToLeft)]
[InlineData("שנבגק", TextAlignment.Left, FlowDirection.RightToLeft)]
[InlineData("שנבגק", TextAlignment.Center, FlowDirection.RightToLeft)]
[InlineData("שנבגק", TextAlignment.Right, FlowDirection.RightToLeft)]
[Theory]
public void Should_Align_TextLine(string text, TextAlignment textAlignment, FlowDirection flowDirection)
{
@ -426,44 +426,29 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var paragraphProperties = new GenericTextParagraphProperties(flowDirection, textAlignment, true, true,
defaultProperties, TextWrapping.NoWrap, 0, 0);
var textSource = new SingleBufferTextSource(text, defaultProperties);
var formatter = new TextFormatterImpl();
var textLine =
formatter.FormatLine(textSource, 0, 100, paragraphProperties);
var expectedOffset = 0d;
if (flowDirection == FlowDirection.LeftToRight)
switch (textAlignment)
{
switch (textAlignment)
{
case TextAlignment.Center:
expectedOffset = 50 - textLine.Width / 2;
break;
case TextAlignment.Right:
expectedOffset = 100 - textLine.WidthIncludingTrailingWhitespace;
break;
}
}
else
{
switch (textAlignment)
{
case TextAlignment.Left:
expectedOffset = 100 - textLine.WidthIncludingTrailingWhitespace;
break;
case TextAlignment.Center:
expectedOffset = 50 - textLine.Width / 2;
break;
}
case TextAlignment.Center:
expectedOffset = 50 - textLine.Width / 2;
break;
case TextAlignment.Right:
expectedOffset = 100 - textLine.WidthIncludingTrailingWhitespace;
break;
}
Assert.Equal(expectedOffset, textLine.Start);
}
}
[Fact]
public void Should_Wrap_Syriac()
{
@ -488,7 +473,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
formatter.FormatLine(textSource, textPosition, 50, paragraphProperties, lastBreak);
Assert.Equal(textLine.Length, textLine.TextRuns.Sum(x => x.TextSourceLength));
textPosition += textLine.Length;
lastBreak = textLine.TextLineBreak;
@ -503,13 +488,13 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var defaultProperties = new GenericTextRunProperties(Typeface.Default);
var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap);
var textSource = new SingleBufferTextSource("0123456789_0123456789_0123456789_0123456789", defaultProperties);
var formatter = new TextFormatterImpl();
var textLine =
formatter.FormatLine(textSource, 0, 33, paragraphProperties);
Assert.NotNull(textLine.TextLineBreak?.RemainingRuns);
}
}
@ -524,12 +509,12 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
using (Start())
{
var formatter = new TextFormatterImpl();
var defaultProperties = new GenericTextRunProperties(Typeface.Default);
var paragraphProperties =
new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.NoWrap);
var foreground = new SolidColorBrush(Colors.Red).ToImmutable();
var expectedTextLine = formatter.FormatLine(new SingleBufferTextSource(text, defaultProperties),
@ -548,16 +533,16 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
new ValueSpan<TextRunProperties>(i, j,
new GenericTextRunProperties(Typeface.Default, 12, foregroundBrush: foreground))
};
var textSource = new FormattedTextSource(text.AsMemory(), defaultProperties, spans);
var textLine =
formatter.FormatLine(textSource, 0, double.PositiveInfinity, paragraphProperties);
var shapedRuns = textLine.TextRuns.Cast<ShapedTextCharacters>().ToList();
var actualGlyphs = shapedRuns.SelectMany(x => x.GlyphRun.GlyphIndices).ToList();
Assert.Equal(expectedGlyphs, actualGlyphs);
}
}
@ -575,9 +560,9 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var textLine =
TextFormatter.Current.FormatLine(textSource, 0, double.PositiveInfinity, paragraphProperties);
Assert.Equal(3, textLine.TextRuns.Count);
Assert.True(textLine.TextRuns[1] is RectangleRun);
}
}
@ -590,12 +575,12 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var defaultRunProperties = new GenericTextRunProperties(Typeface.Default);
var paragraphProperties = new GenericTextParagraphProperties(defaultRunProperties);
var textSource = new EndOfLineTextSource();
var textLine =
TextFormatter.Current.FormatLine(textSource, 0, double.PositiveInfinity, paragraphProperties);
Assert.NotNull(textLine.TextLineBreak);
Assert.Equal(TextRun.DefaultTextSourceLength, textLine.Length);
}
}
@ -616,7 +601,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
_text = text;
}
public TextRun GetTextRun(int textSourceIndex)
{
if (textSourceIndex >= _text.Length + TextRun.DefaultTextSourceLength + _text.Length)

Loading…
Cancel
Save