public void Should_Get_Next_Caret_CharacterHit(string text) { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); var clusters = textLine.TextRuns.Cast <ShapedTextCharacters>().SelectMany(x => x.GlyphRun.GlyphClusters) .ToArray(); var nextCharacterHit = new CharacterHit(0); for (var i = 1; i < clusters.Length; i++) { nextCharacterHit = textLine.GetNextCaretCharacterHit(nextCharacterHit); Assert.Equal(clusters[i], nextCharacterHit.FirstCharacterIndex + nextCharacterHit.TrailingLength); } } }
public void Should_Wrap_With_Overflow(string text, int expectedCharactersPerLine, int expectedNumberOfLines) { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var numberOfLines = 0; var currentPosition = 0; while (currentPosition < text.Length) { var textLine = formatter.FormatLine(textSource, currentPosition, 1, new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.WrapWithOverflow)); if (text.Length - currentPosition > expectedCharactersPerLine) { Assert.Equal(expectedCharactersPerLine, textLine.TextRange.Length); } currentPosition += textLine.TextRange.Length; numberOfLines++; } Assert.Equal(expectedNumberOfLines, numberOfLines); } }
public void Should_Not_Produce_TextLine_Wider_Than_ParagraphWidth() { using (Start()) { const string text = "Multiline TextBlock with TextWrapping.\r\rLorem ipsum dolor sit amet, consectetur adipiscing elit. " + "Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. " + "Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. " + "Vivamus pretium ornare est."; var defaultProperties = new GenericTextRunProperties(Typeface.Default); var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textSourceIndex = 0; while (textSourceIndex < text.Length) { var textLine = formatter.FormatLine(textSource, textSourceIndex, 200, paragraphProperties); Assert.True(textLine.Width <= 200); textSourceIndex += textLine.TextRange.Length; } } }
public void Should_Get_Last_CharacterHit() { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(s_multiLineText, defaultProperties); var formatter = new TextFormatterImpl(); var currentIndex = 0; while (currentIndex < s_multiLineText.Length) { var textLine = formatter.FormatLine(textSource, currentIndex, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); var lastCharacterHit = textLine.GetNextCaretCharacterHit(new CharacterHit(int.MaxValue)); Assert.Equal(textLine.TextRange.Start + textLine.TextRange.Length, lastCharacterHit.FirstCharacterIndex + lastCharacterHit.TrailingLength); currentIndex += textLine.TextRange.Length; } } }
public void Wrap_Should_Not_Produce_Empty_Lines() { using (Start()) { const string text = "012345"; var defaultProperties = new GenericTextRunProperties(Typeface.Default); var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textSourceIndex = 0; while (textSourceIndex < text.Length) { var textLine = formatter.FormatLine(textSource, textSourceIndex, 3, paragraphProperties); Assert.NotEqual(0, textLine.TextRange.Length); textSourceIndex += textLine.TextRange.Length; } Assert.Equal(text.Length, textSourceIndex); } }
public void Should_Align_TextLine(string text, TextAlignment textAlignment, FlowDirection flowDirection) { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); 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; switch (textAlignment) { case TextAlignment.Center: expectedOffset = 50 - textLine.Width / 2; break; case TextAlignment.Right: expectedOffset = 100 - textLine.WidthIncludingTrailingWhitespace; break; } Assert.Equal(expectedOffset, textLine.Start); } }
public void Should_Wrap_Syriac() { using (Start()) { const string text = "܀ ܁ ܂ ܃ ܄ ܅ ܆ ܇ ܈ ܉ ܊ ܋ ܌ ܍ ܐ ܑ ܒ ܓ ܔ ܕ ܖ ܗ ܘ ܙ ܚ ܛ ܜ ܝ ܞ ܟ ܠ ܡ ܢ ܣ ܤ ܥ ܦ ܧ ܨ ܩ ܪ ܫ ܬ ܰ ܱ ܲ ܳ ܴ ܵ ܶ ܷ ܸ ܹ ܺ ܻ ܼ ܽ ܾ ܿ ݀ ݁ ݂ ݃ ݄ ݅ ݆ ݇ ݈ ݉ ݊"; var defaultProperties = new GenericTextRunProperties(Typeface.Default); var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textPosition = 87; TextLineBreak lastBreak = null; while (textPosition < text.Length) { var textLine = formatter.FormatLine(textSource, textPosition, 50, paragraphProperties, lastBreak); Assert.Equal(textLine.Length, textLine.TextRuns.Sum(x => x.TextSourceLength)); textPosition += textLine.Length; lastBreak = textLine.TextLineBreak; } } }
public void Should_Format_TextRuns_With_Default_Style() { using (Start()) { const string text = "0123456789"; var defaultProperties = new GenericTextRunProperties(Typeface.Default, 12, foregroundBrush: Brushes.Black); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); Assert.Single(textLine.TextRuns); var textRun = textLine.TextRuns[0]; Assert.Equal(defaultProperties.Typeface, textRun.Properties.Typeface); Assert.Equal(defaultProperties.ForegroundBrush, textRun.Properties.ForegroundBrush); Assert.Equal(text.Length, textRun.Text.Length); } }
public void Should_Wrap_RightToLeft() { using (Start()) { const string text = "قطاعات الصناعة على الشبكة العالمية انترنيت ويونيكود، حيث ستتم، على الصعيدين الدولي والمحلي على حد سواء"; var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var currentTextSourceIndex = 0; while (currentTextSourceIndex < text.Length) { var textLine = formatter.FormatLine(textSource, currentTextSourceIndex, 50, new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap)); var glyphClusters = textLine.TextRuns.Cast <ShapedTextCharacters>() .SelectMany(x => x.GlyphRun.GlyphClusters).ToArray(); Assert.True(glyphClusters[0] >= glyphClusters[^ 1]); Assert.Equal(currentTextSourceIndex, glyphClusters[^ 1]);
public void Should_Produce_Wrapped_And_Trimmed_Lines(string text, string[] expectedLines) { using (Start()) { var typeface = new Typeface("Verdana"); var defaultProperties = new GenericTextRunProperties(typeface, 32, foregroundBrush: Brushes.Black); var styleSpans = new[] { new ValueSpan <TextRunProperties>(0, 5, new GenericTextRunProperties(typeface, 48)), new ValueSpan <TextRunProperties>(6, 11, new GenericTextRunProperties(new Typeface("Verdana", weight: FontWeight.Bold), 32)), 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(); var currentPosition = 0; var currentHeight = 0d; var currentLineIndex = 0; while (currentPosition < text.Length && currentLineIndex < expectedLines.Length) { var textLine = formatter.FormatLine(textSource, currentPosition, 300, new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.WrapWithOverflow)); currentPosition += textLine.TextRange.Length; if (textLine.Width > 300 || currentHeight + textLine.Height > 240) { textLine = textLine.Collapse(new TextTrailingWordEllipsis(300, defaultProperties)); } currentHeight += textLine.Height; var currentText = text.Substring(textLine.TextRange.Start, textLine.TextRange.Length); Assert.Equal(expectedLines[currentLineIndex], currentText); currentLineIndex++; } Assert.Equal(expectedLines.Length, currentLineIndex); } }
public void Should_Wrap(string text, string familyName, int numberOfCharactersPerLine) { using (Start()) { var lineBreaker = new LineBreakEnumerator(text.AsMemory()); var expected = new List <int>(); while (lineBreaker.MoveNext()) { expected.Add(lineBreaker.Current.PositionWrap - 1); } var typeface = new Typeface("resm:Avalonia.Skia.UnitTests.Assets?assembly=Avalonia.Skia.UnitTests#" + familyName); var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var glyph = typeface.GlyphTypeface.GetGlyph('a'); var advance = typeface.GlyphTypeface.GetGlyphAdvance(glyph) * (12.0 / typeface.GlyphTypeface.DesignEmHeight); var paragraphWidth = advance * numberOfCharactersPerLine; var currentPosition = 0; while (currentPosition < text.Length) { var textLine = formatter.FormatLine(textSource, currentPosition, paragraphWidth, new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap)); var end = textLine.FirstTextSourceIndex + textLine.Length - 1; Assert.True(expected.Contains(end)); var index = expected.IndexOf(end); for (var i = 0; i <= index; i++) { expected.RemoveAt(0); } currentPosition += textLine.Length; } } }
public void Should_Get_Previous_Caret_CharacterHit_Bidi() { const string text = "אבג 1 ABC"; using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); var clusters = new List <int>(); foreach (var textRun in textLine.TextRuns.OrderBy(x => x.Text.Start)) { var shapedRun = (ShapedTextCharacters)textRun; clusters.AddRange(shapedRun.IsReversed ? shapedRun.ShapedBuffer.GlyphClusters.Reverse() : shapedRun.ShapedBuffer.GlyphClusters); } clusters.Reverse(); var nextCharacterHit = new CharacterHit(text.Length - 1); foreach (var cluster in clusters) { var currentCaretIndex = nextCharacterHit.FirstCharacterIndex + nextCharacterHit.TrailingLength; Assert.Equal(cluster, currentCaretIndex); nextCharacterHit = textLine.GetPreviousCaretCharacterHit(nextCharacterHit); } var lastCharacterHit = nextCharacterHit; nextCharacterHit = textLine.GetPreviousCaretCharacterHit(lastCharacterHit); Assert.Equal(lastCharacterHit.FirstCharacterIndex, nextCharacterHit.FirstCharacterIndex); Assert.Equal(lastCharacterHit.TrailingLength, nextCharacterHit.TrailingLength); } }
public void Should_FormatLine_With_Emergency_Breaks() { using (Start()) { 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?.RemainingCharacters); } }
public void Should_Produce_Unique_Runs(string text, int numberOfRuns) { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); Assert.Equal(numberOfRuns, textLine.TextRuns.Count); } }
public void Should_Align_TextLine(TextAlignment textAlignment) { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textAlignment); var textSource = new SingleBufferTextSource("0123456789", defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, 100, paragraphProperties); var expectedOffset = TextLine.GetParagraphOffsetX(textLine.Width, 100, textAlignment); Assert.Equal(expectedOffset, textLine.Start); } }
public void Should_Get_Previous_Caret_CharacterHit(string text) { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); var clusters = textLine.TextRuns.Cast <ShapedTextCharacters>().SelectMany(x => x.GlyphRun.GlyphClusters) .ToArray(); var previousCharacterHit = new CharacterHit(clusters[^ 1]);
public void Should_Not_Alter_TextRuns_After_TextStyles_Were_Applied(string text) { 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), 0, double.PositiveInfinity, paragraphProperties); var expectedRuns = expectedTextLine.TextRuns.Cast <ShapedTextCharacters>().ToList(); var expectedGlyphs = expectedRuns.SelectMany(x => x.GlyphRun.GlyphIndices).ToList(); for (var i = 0; i < text.Length; i++) { for (var j = 1; i + j < text.Length; j++) { var spans = new[] { 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); } } } }
public void Should_Format_TextRuns_With_Multiple_Buffers() { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default, 12, foregroundBrush: Brushes.Black); var textSource = new MultiBufferTextSource(defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); Assert.Equal(5, textLine.TextRuns.Count); Assert.Equal(50, textLine.TextRange.Length); } }
public void Should_Produce_A_Single_Fallback_Run() { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); const string text = "👍 👍 👍 👍"; var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); Assert.Equal(1, textLine.TextRuns.Count); } }
public void Should_Produce_Fixed_Height_Lines() { using (Start()) { const string text = "012345"; var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties, lineHeight: 50)); Assert.Equal(50, textLine.Height); } }
public void Should_Split_Run_On_Script() { using (Start()) { const string text = "ABCDالدولي"; var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); Assert.Equal(4, textLine.TextRuns[0].Text.Length); } }
public void Should_Format_TextRuns_With_TextRunStyles() { using (Start()) { const string text = "0123456789"; var defaultProperties = new GenericTextRunProperties(Typeface.Default, 12, foregroundBrush: Brushes.Black); var GenericTextRunPropertiesRuns = new[] { new ValueSpan <TextRunProperties>(0, 3, defaultProperties), new ValueSpan <TextRunProperties>(3, 3, new GenericTextRunProperties(Typeface.Default, 13, foregroundBrush: Brushes.Black)), new ValueSpan <TextRunProperties>(6, 3, new GenericTextRunProperties(Typeface.Default, 14, foregroundBrush: Brushes.Black)), new ValueSpan <TextRunProperties>(9, 1, defaultProperties) }; var textSource = new FormattedTextSource(text.AsMemory(), defaultProperties, GenericTextRunPropertiesRuns); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); Assert.Equal(text.Length, textLine.TextRange.Length); for (var i = 0; i < GenericTextRunPropertiesRuns.Length; i++) { var GenericTextRunPropertiesRun = GenericTextRunPropertiesRuns[i]; var textRun = textLine.TextRuns[i]; Assert.Equal(GenericTextRunPropertiesRun.Length, textRun.Text.Length); } } }
public void Should_Get_Previous_Caret_CharacterHit(string text) { using (Start()) { var defaultProperties = new GenericTextRunProperties(Typeface.Default); var textSource = new SingleBufferTextSource(text, defaultProperties); var formatter = new TextFormatterImpl(); var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity, new GenericTextParagraphProperties(defaultProperties)); var clusters = textLine.TextRuns.Cast <ShapedTextCharacters>().SelectMany(x => x.GlyphRun.GlyphClusters) .ToArray(); var previousCharacterHit = new CharacterHit(text.Length); for (var i = clusters.Length - 1; i >= 0; i--) { previousCharacterHit = textLine.GetPreviousCaretCharacterHit(previousCharacterHit); Assert.Equal(clusters[i], previousCharacterHit.FirstCharacterIndex + previousCharacterHit.TrailingLength); } var firstCharacterHit = previousCharacterHit; previousCharacterHit = textLine.GetPreviousCaretCharacterHit(firstCharacterHit); Assert.Equal(firstCharacterHit.FirstCharacterIndex, previousCharacterHit.FirstCharacterIndex); Assert.Equal(0, previousCharacterHit.TrailingLength); previousCharacterHit = new CharacterHit(clusters[^ 1], text.Length - clusters[^ 1]);