Example #1
0
        /// <summary>
        /// Fetches text runs.
        /// </summary>
        /// <param name="textSource">The text source.</param>
        /// <param name="firstTextSourceIndex">The first text source index.</param>
        /// <param name="endOfLine"></param>
        /// <param name="textRange"></param>
        /// <returns>
        /// The formatted text runs.
        /// </returns>
        private static List <TextCharacters> FetchTextRuns(ITextSource textSource, int firstTextSourceIndex,
                                                           out TextEndOfLine?endOfLine, out TextRange textRange)
        {
            var length = 0;

            endOfLine = null;

            var textRuns = new List <TextCharacters>();

            var textRunEnumerator = new TextRunEnumerator(textSource, firstTextSourceIndex);

            while (textRunEnumerator.MoveNext())
            {
                var textRun = textRunEnumerator.Current;

                if (textRun == null)
                {
                    break;
                }

                switch (textRun)
                {
                case TextCharacters textCharacters:
                {
                    if (TryGetLineBreak(textCharacters, out var runLineBreak))
                    {
                        var splitResult = new TextCharacters(textCharacters.Text.Take(runLineBreak.PositionWrap),
                                                             textCharacters.Properties);

                        textRuns.Add(splitResult);

                        length += runLineBreak.PositionWrap;

                        textRange = new TextRange(firstTextSourceIndex, length);

                        return(textRuns);
                    }

                    textRuns.Add(textCharacters);

                    break;
                }

                case TextEndOfLine textEndOfLine:
                    endOfLine = textEndOfLine;
                    break;
                }

                length += textRun.Text.Length;
            }

            textRange = new TextRange(firstTextSourceIndex, length);

            return(textRuns);
        }
Example #2
0
        /// <summary>
        /// Fetches text runs.
        /// </summary>
        /// <param name="textSource">The text source.</param>
        /// <param name="firstTextSourceIndex">The first text source index.</param>
        /// <param name="previousLineBreak">Previous line break. Can be null.</param>
        /// <param name="nextLineBreak">Next line break. Can be null.</param>
        /// <returns>
        /// The formatted text runs.
        /// </returns>
        private static IReadOnlyList <ShapedTextCharacters> FetchTextRuns(ITextSource textSource,
                                                                          int firstTextSourceIndex, TextLineBreak previousLineBreak, out TextLineBreak nextLineBreak)
        {
            nextLineBreak = default;

            var currentLength = 0;

            var textRuns = new List <ShapedTextCharacters>();

            if (previousLineBreak != null)
            {
                foreach (var shapedCharacters in previousLineBreak.RemainingCharacters)
                {
                    if (shapedCharacters == null)
                    {
                        continue;
                    }

                    textRuns.Add(shapedCharacters);

                    if (TryGetLineBreak(shapedCharacters, out var runLineBreak))
                    {
                        var splitResult = SplitTextRuns(textRuns, currentLength + runLineBreak.PositionWrap);

                        nextLineBreak = new TextLineBreak(splitResult.Second);

                        return(splitResult.First);
                    }

                    currentLength += shapedCharacters.Text.Length;
                }
            }

            firstTextSourceIndex += currentLength;

            var textRunEnumerator = new TextRunEnumerator(textSource, firstTextSourceIndex);

            while (textRunEnumerator.MoveNext())
            {
                var textRun = textRunEnumerator.Current;

                switch (textRun)
                {
                case TextCharacters textCharacters:
                {
                    var shapeableRuns = textCharacters.GetShapeableCharacters();

                    foreach (var run in shapeableRuns)
                    {
                        var glyphRun = TextShaper.Current.ShapeText(run.Text, run.Properties.Typeface,
                                                                    run.Properties.FontRenderingEmSize, run.Properties.CultureInfo);

                        var shapedCharacters = new ShapedTextCharacters(glyphRun, run.Properties);

                        textRuns.Add(shapedCharacters);
                    }

                    break;
                }
                }

                if (TryGetLineBreak(textRun, out var runLineBreak))
                {
                    var splitResult = SplitTextRuns(textRuns, currentLength + runLineBreak.PositionWrap);

                    nextLineBreak = new TextLineBreak(splitResult.Second);

                    return(splitResult.First);
                }

                currentLength += textRun.Text.Length;
            }

            return(textRuns);
        }