示例#1
0
        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);
                }
            }
        }
示例#2
0
        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);
            }
        }
示例#3
0
        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;
                }
            }
        }
示例#4
0
        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;
                }
            }
        }
示例#5
0
        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;
                }
            }
        }
示例#8
0
        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);
            }
        }
示例#9
0
        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]);
示例#10
0
        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);
            }
        }
示例#13
0
        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);
            }
        }
示例#14
0
        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);
            }
        }
示例#15
0
        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);
            }
        }
示例#16
0
        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);
                    }
                }
            }
        }
示例#18
0
        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);
            }
        }
示例#20
0
        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);
            }
        }
示例#21
0
        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);
            }
        }
示例#22
0
        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);
                }
            }
        }
示例#23
0
        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]);