|
|
@@ -766,12 +766,14 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- [Fact]
|
|
|
- public void Line_Formatting_For_Oversized_Embedded_Runs_Does_Not_Produce_Empty_Lines()
|
|
|
+
|
|
|
+ [Theory]
|
|
|
+ [InlineData(TextWrapping.NoWrap),InlineData(TextWrapping.Wrap),InlineData(TextWrapping.WrapWithOverflow)]
|
|
|
+ public void Line_Formatting_For_Oversized_Embedded_Runs_Does_Not_Produce_Empty_Lines(TextWrapping wrapping)
|
|
|
{
|
|
|
var defaultRunProperties = new GenericTextRunProperties(Typeface.Default, foregroundBrush: Brushes.Black);
|
|
|
var paragraphProperties = new GenericTextParagraphProperties(defaultRunProperties,
|
|
|
- textWrap: TextWrapping.WrapWithOverflow);
|
|
|
+ textWrap: wrapping);
|
|
|
|
|
|
using (Start())
|
|
|
{
|
|
|
@@ -780,6 +782,48 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
|
|
Assert.Equal(200d, textLine.WidthIncludingTrailingWhitespace);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ [Theory]
|
|
|
+ [InlineData(TextWrapping.NoWrap),InlineData(TextWrapping.Wrap),InlineData(TextWrapping.WrapWithOverflow)]
|
|
|
+ public void Line_Formatting_For_Oversized_Embedded_Runs_Inside_Normal_Text_Does_Not_Produce_Empty_Lines(
|
|
|
+ TextWrapping wrapping)
|
|
|
+ {
|
|
|
+ var defaultRunProperties = new GenericTextRunProperties(Typeface.Default, foregroundBrush: Brushes.Black);
|
|
|
+ var paragraphProperties = new GenericTextParagraphProperties(defaultRunProperties,
|
|
|
+ textWrap: wrapping);
|
|
|
+
|
|
|
+ using (Start())
|
|
|
+ {
|
|
|
+ var typeface = new Typeface(FontFamily.Parse("resm:Avalonia.Skia.UnitTests.Fonts?assembly=Avalonia.Skia.UnitTests#DejaVu Sans"));
|
|
|
+
|
|
|
+ var text1 = new TextCharacters("Hello",
|
|
|
+ new GenericTextRunProperties(typeface, foregroundBrush: Brushes.Black));
|
|
|
+ var text2 = new TextCharacters("world",
|
|
|
+ new GenericTextRunProperties(typeface, foregroundBrush: Brushes.Black));
|
|
|
+
|
|
|
+ var source = new ListTextSource(
|
|
|
+ text1,
|
|
|
+ new RectangleRun(new Rect(0, 0, 200, 10), Brushes.Aqua),
|
|
|
+ new InvisibleRun(1),
|
|
|
+ new TextEndOfLine(),
|
|
|
+ text2,
|
|
|
+ new TextEndOfParagraph(1));
|
|
|
+
|
|
|
+ var lines = new List<TextLine>();
|
|
|
+ var dcp = 0;
|
|
|
+ for (var c = 0;; c++)
|
|
|
+ {
|
|
|
+ Assert.True(c < 1000, "Infinite loop");
|
|
|
+ var textLine = TextFormatter.Current.FormatLine(source, dcp, 30, paragraphProperties);
|
|
|
+ Assert.NotNull(textLine);
|
|
|
+ lines.Add(textLine);
|
|
|
+ dcp += textLine.Length;
|
|
|
+
|
|
|
+ if (textLine.TextLineBreak is {} eol && eol.TextEndOfLine is TextEndOfParagraph)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
class IncrementalTabProperties : TextParagraphProperties
|
|
|
{
|
|
|
@@ -910,7 +954,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
|
|
|
|
|
private class ListTextSource : ITextSource
|
|
|
{
|
|
|
- private Dictionary<int, TextRun> _runs = new();
|
|
|
+ private List<TextRun> _runs = new();
|
|
|
|
|
|
public ListTextSource(params TextRun[] runs) : this((IEnumerable<TextRun>)runs)
|
|
|
{
|
|
|
@@ -919,18 +963,27 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
|
|
|
|
|
public ListTextSource(IEnumerable<TextRun> runs)
|
|
|
{
|
|
|
- var off = 0;
|
|
|
- foreach (var r in runs)
|
|
|
- {
|
|
|
- _runs[off] = r;
|
|
|
- off += r.Length;
|
|
|
- }
|
|
|
+ _runs = runs.ToList();
|
|
|
}
|
|
|
|
|
|
public TextRun GetTextRun(int textSourceIndex)
|
|
|
{
|
|
|
- _runs.TryGetValue(textSourceIndex, out var rv);
|
|
|
- return rv;
|
|
|
+ var off = 0;
|
|
|
+ for (var c = 0; c < _runs.Count; c++)
|
|
|
+ {
|
|
|
+ var run = _runs[c];
|
|
|
+ if (textSourceIndex >= off && textSourceIndex - off < run.Length)
|
|
|
+ {
|
|
|
+ if (run.Length == 1)
|
|
|
+ return run;
|
|
|
+ var chars = ((TextCharacters)run);
|
|
|
+ return new TextCharacters(chars.Text.Slice(textSourceIndex - off), chars.Properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ off += run.Length;
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
}
|
|
|
}
|
|
|
|