Browse Source

Include last line when constraint is surpassed

pull/3681/head
Benedikt Schroeder 6 years ago
parent
commit
f7aa466803
  1. 27
      src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs
  2. 58
      tests/Avalonia.Skia.UnitTests/TextLayoutTests.cs

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

@ -233,16 +233,16 @@ namespace Avalonia.Media.TextFormatting
var textLine = TextFormatter.Current.FormatLine(textSource, 0, MaxWidth, _paragraphProperties); var textLine = TextFormatter.Current.FormatLine(textSource, 0, MaxWidth, _paragraphProperties);
UpdateBounds(textLine, ref left, ref right, ref bottom);
textLines.Add(textLine);
if (!double.IsPositiveInfinity(MaxHeight) && bottom + textLine.LineMetrics.Size.Height > MaxHeight) if (!double.IsPositiveInfinity(MaxHeight) && bottom + textLine.LineMetrics.Size.Height > MaxHeight)
{ {
currentPosition = _text.Length; currentPosition = _text.Length;
break; break;
} }
UpdateBounds(textLine, ref left, ref right, ref bottom);
textLines.Add(textLine);
if (_paragraphProperties.TextTrimming != TextTrimming.None) if (_paragraphProperties.TextTrimming != TextTrimming.None)
{ {
currentPosition += remainingLength; currentPosition += remainingLength;
@ -254,22 +254,15 @@ namespace Avalonia.Media.TextFormatting
currentPosition += textLine.Text.Length; currentPosition += textLine.Text.Length;
} }
}
if (lineBreaker.Current.Required && currentPosition == _text.Length) if (lineBreaker.Current.Required && currentPosition == _text.Length)
{ {
var emptyTextLine = CreateEmptyTextLine(currentPosition); var emptyTextLine = CreateEmptyTextLine(currentPosition);
if (!double.IsPositiveInfinity(MaxHeight) && bottom + emptyTextLine.LineMetrics.Size.Height > MaxHeight)
{
break;
}
UpdateBounds(emptyTextLine, ref left, ref right, ref bottom);
textLines.Add(emptyTextLine); UpdateBounds(emptyTextLine, ref left, ref right, ref bottom);
break; textLines.Add(emptyTextLine);
}
} }
Bounds = new Rect(left, 0, right, bottom); Bounds = new Rect(left, 0, right, bottom);

58
tests/Avalonia.Skia.UnitTests/TextLayoutTests.cs

@ -29,10 +29,10 @@ namespace Avalonia.Skia.UnitTests
var layout = new TextLayout( var layout = new TextLayout(
s_multiLineText, s_multiLineText,
Typeface.Default, Typeface.Default,
12.0f, 12.0f,
Brushes.Black.ToImmutable(), Brushes.Black.ToImmutable(),
textStyleOverrides : spans); textStyleOverrides: spans);
var textLine = layout.TextLines[0]; var textLine = layout.TextLines[0];
@ -72,16 +72,16 @@ namespace Avalonia.Skia.UnitTests
12.0f, 12.0f,
Brushes.Black.ToImmutable(), Brushes.Black.ToImmutable(),
textWrapping: TextWrapping.Wrap, textWrapping: TextWrapping.Wrap,
maxWidth : 25); maxWidth: 25);
var actual = new TextLayout( var actual = new TextLayout(
s_multiLineText, s_multiLineText,
Typeface.Default, Typeface.Default,
12.0f, 12.0f,
Brushes.Black.ToImmutable(), Brushes.Black.ToImmutable(),
textWrapping : TextWrapping.Wrap, textWrapping: TextWrapping.Wrap,
maxWidth : 25, maxWidth: 25,
textStyleOverrides : spans); textStyleOverrides: spans);
Assert.Equal(expected.TextLines.Count, actual.TextLines.Count); Assert.Equal(expected.TextLines.Count, actual.TextLines.Count);
@ -115,7 +115,7 @@ namespace Avalonia.Skia.UnitTests
Typeface.Default, Typeface.Default,
12.0f, 12.0f,
Brushes.Black.ToImmutable(), Brushes.Black.ToImmutable(),
textStyleOverrides : spans); textStyleOverrides: spans);
var textLine = layout.TextLines[0]; var textLine = layout.TextLines[0];
@ -153,7 +153,7 @@ namespace Avalonia.Skia.UnitTests
Typeface.Default, Typeface.Default,
12.0f, 12.0f,
Brushes.Black.ToImmutable(), Brushes.Black.ToImmutable(),
textStyleOverrides : spans); textStyleOverrides: spans);
var textLine = layout.TextLines[0]; var textLine = layout.TextLines[0];
@ -190,7 +190,7 @@ namespace Avalonia.Skia.UnitTests
Typeface.Default, Typeface.Default,
12.0f, 12.0f,
Brushes.Black.ToImmutable(), Brushes.Black.ToImmutable(),
textStyleOverrides : spans); textStyleOverrides: spans);
var textLine = layout.TextLines[0]; var textLine = layout.TextLines[0];
@ -301,8 +301,8 @@ namespace Avalonia.Skia.UnitTests
Typeface.Default, Typeface.Default,
12.0f, 12.0f,
Brushes.Black.ToImmutable(), Brushes.Black.ToImmutable(),
textWrapping : TextWrapping.Wrap, textWrapping: TextWrapping.Wrap,
maxWidth : 180, maxWidth: 180,
textStyleOverrides: spans); textStyleOverrides: spans);
Assert.Equal( Assert.Equal(
@ -332,8 +332,8 @@ namespace Avalonia.Skia.UnitTests
Typeface.Default, Typeface.Default,
12.0f, 12.0f,
Brushes.Black.ToImmutable(), Brushes.Black.ToImmutable(),
maxWidth : 200, maxWidth: 200,
maxHeight : 125, maxHeight: 125,
textStyleOverrides: spans); textStyleOverrides: spans);
Assert.Equal(foreground, layout.TextLines[0].TextRuns[1].Style.Foreground); Assert.Equal(foreground, layout.TextLines[0].TextRuns[1].Style.Foreground);
@ -430,7 +430,7 @@ namespace Avalonia.Skia.UnitTests
Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).GlyphRun.GlyphClusters[5]); Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).GlyphRun.GlyphClusters[5]);
if(expectedLength == 7) if (expectedLength == 7)
{ {
Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).GlyphRun.GlyphClusters[6]); Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).GlyphRun.GlyphClusters[6]);
} }
@ -480,12 +480,38 @@ namespace Avalonia.Skia.UnitTests
} }
} }
[InlineData("0123456789\r0123456789", 2)]
[InlineData("0123456789", 1)]
[Theory]
public void Should_Include_Last_Line_When_Constraint_Is_Surpassed(string text, int numberOfLines)
{
using (Start())
{
var glyphTypeface = Typeface.Default.GlyphTypeface;
var emHeight = glyphTypeface.DesignEmHeight;
var lineHeight = (glyphTypeface.Descent - glyphTypeface.Ascent) * (12.0 / emHeight);
var layout = new TextLayout(
text,
Typeface.Default,
12,
Brushes.Black.ToImmutable(),
maxHeight: lineHeight * numberOfLines - lineHeight * 0.5);
Assert.Equal(numberOfLines, layout.TextLines.Count);
Assert.Equal(numberOfLines * lineHeight, layout.Bounds.Height);
}
}
public static IDisposable Start() public static IDisposable Start()
{ {
var disposable = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface var disposable = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface
.With(renderInterface: new PlatformRenderInterface(null), .With(renderInterface: new PlatformRenderInterface(null),
textShaperImpl: new TextShaperImpl(), textShaperImpl: new TextShaperImpl(),
fontManagerImpl : new CustomFontManagerImpl())); fontManagerImpl: new CustomFontManagerImpl()));
return disposable; return disposable;
} }

Loading…
Cancel
Save