示例#1
0
        /// <inheritdoc cref="TextFormatter.FormatLine"/>
        public override TextLine FormatLine(ITextSource textSource, int firstTextSourceIndex, double paragraphWidth,
                                            TextParagraphProperties paragraphProperties)
        {
            var      textTrimming = paragraphProperties.TextTrimming;
            var      textWrapping = paragraphProperties.TextWrapping;
            TextLine textLine;

            var textRuns = FormatTextRuns(textSource, firstTextSourceIndex, out var textPointer);

            if (textTrimming != TextTrimming.None)
            {
                textLine = PerformTextTrimming(textPointer, textRuns, paragraphWidth, paragraphProperties);
            }
            else
            {
                if (textWrapping == TextWrapping.Wrap)
                {
                    textLine = PerformTextWrapping(textPointer, textRuns, paragraphWidth, paragraphProperties);
                }
                else
                {
                    var textLineMetrics =
                        TextLineMetrics.Create(textRuns, paragraphWidth, paragraphProperties.TextAlignment);

                    textLine = new SimpleTextLine(textPointer, textRuns, textLineMetrics);
                }
            }

            return(textLine);
        }
示例#2
0
        /// <inheritdoc cref="TextFormatter.FormatLine"/>
        public override TextLine FormatLine(ITextSource textSource, int firstTextSourceIndex, double paragraphWidth,
                                            TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak = null)
        {
            var textWrapping = paragraphProperties.TextWrapping;

            var textRuns = FetchTextRuns(textSource, firstTextSourceIndex, previousLineBreak, out var nextLineBreak);

            var textRange = GetTextRange(textRuns);

            TextLine textLine;

            switch (textWrapping)
            {
            case TextWrapping.NoWrap:
            {
                var textLineMetrics =
                    TextLineMetrics.Create(textRuns, textRange, paragraphWidth, paragraphProperties);

                textLine = new TextLineImpl(textRuns, textLineMetrics, nextLineBreak);
                break;
            }

            case TextWrapping.WrapWithOverflow:
            case TextWrapping.Wrap:
            {
                textLine = PerformTextWrapping(textRuns, textRange, paragraphWidth, paragraphProperties);
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(textLine);
        }
示例#3
0
        /// <summary>
        /// Creates an empty text line.
        /// </summary>
        /// <returns>The empty text line.</returns>
        private TextLine CreateEmptyTextLine(int startingIndex)
        {
            var textFormat = _paragraphProperties.DefaultTextStyle.TextFormat;

            var glyphRun = TextShaper.Current.ShapeText(s_empty, textFormat);

            var textRuns = new[] { new ShapedTextRun(glyphRun, _paragraphProperties.DefaultTextStyle) };

            return(new SimpleTextLine(new TextPointer(startingIndex, 0), textRuns,
                                      TextLineMetrics.Create(textRuns, MaxWidth, _paragraphProperties.TextAlignment)));
        }
示例#4
0
        /// <summary>
        /// Creates an empty text line.
        /// </summary>
        /// <returns>The empty text line.</returns>
        private TextLine CreateEmptyTextLine(int startingIndex)
        {
            var properties = _paragraphProperties.DefaultTextRunProperties;

            var glyphRun = TextShaper.Current.ShapeText(new ReadOnlySlice <char>(s_empty, startingIndex, 1),
                                                        properties.Typeface, properties.FontRenderingEmSize, properties.CultureInfo);

            var textRuns = new[] { new ShapedTextCharacters(glyphRun, _paragraphProperties.DefaultTextRunProperties) };

            return(new TextLineImpl(textRuns,
                                    TextLineMetrics.Create(textRuns, new TextRange(startingIndex, 1), MaxWidth, _paragraphProperties)));
        }
示例#5
0
        /// <inheritdoc cref="TextFormatter.FormatLine"/>
        public override TextLine FormatLine(ITextSource textSource, int firstTextSourceIndex, double paragraphWidth,
                                            TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak = null)
        {
            var      textTrimming = paragraphProperties.TextTrimming;
            var      textWrapping = paragraphProperties.TextWrapping;
            TextLine textLine     = null;

            var textRuns = FetchTextRuns(textSource, firstTextSourceIndex, previousLineBreak, out var nextLineBreak);

            var textRange = GetTextRange(textRuns);

            if (textTrimming != TextTrimming.None)
            {
                textLine = PerformTextTrimming(textRuns, textRange, paragraphWidth, paragraphProperties);
            }
            else
            {
                switch (textWrapping)
                {
                case TextWrapping.NoWrap:
                {
                    var textLineMetrics =
                        TextLineMetrics.Create(textRuns, textRange, paragraphWidth, paragraphProperties);

                    textLine = new TextLineImpl(textRuns, textLineMetrics, nextLineBreak);
                    break;
                }

                case TextWrapping.WrapWithOverflow:
                case TextWrapping.Wrap:
                {
                    textLine = PerformTextWrapping(textRuns, textRange, paragraphWidth, paragraphProperties);
                    break;
                }
                }
            }

            return(textLine);
        }
示例#6
0
        /// <summary>
        /// Performs text wrapping returns a list of text lines.
        /// </summary>
        /// <param name="textRuns">The text run's.</param>
        /// <param name="textRange">The text range that is covered by the text runs.</param>
        /// <param name="paragraphWidth">The paragraph width.</param>
        /// <param name="paragraphProperties">The text paragraph properties.</param>
        /// <returns>The wrapped text line.</returns>
        private static TextLine PerformTextWrapping(IReadOnlyList <ShapedTextCharacters> textRuns, TextRange textRange,
                                                    double paragraphWidth, TextParagraphProperties paragraphProperties)
        {
            var availableWidth = paragraphWidth;
            var currentWidth   = 0.0;
            var runIndex       = 0;
            var currentLength  = 0;

            while (runIndex < textRuns.Count)
            {
                var currentRun = textRuns[runIndex];

                if (currentWidth + currentRun.GlyphRun.Bounds.Width > availableWidth)
                {
                    var measuredLength = MeasureCharacters(currentRun, paragraphWidth - currentWidth);

                    var breakFound = false;

                    var currentBreakPosition = 0;

                    if (measuredLength < currentRun.Text.Length)
                    {
                        var lineBreaker = new LineBreakEnumerator(currentRun.Text);

                        while (currentBreakPosition < measuredLength && lineBreaker.MoveNext())
                        {
                            var nextBreakPosition = lineBreaker.Current.PositionWrap;

                            if (nextBreakPosition == 0 || nextBreakPosition > measuredLength)
                            {
                                break;
                            }

                            breakFound = lineBreaker.Current.Required ||
                                         lineBreaker.Current.PositionWrap != currentRun.Text.Length;

                            currentBreakPosition = nextBreakPosition;
                        }
                    }

                    if (breakFound)
                    {
                        measuredLength = currentBreakPosition;
                    }
                    else
                    {
                        if (paragraphProperties.TextWrapping == TextWrapping.WrapWithOverflow)
                        {
                            var lineBreaker = new LineBreakEnumerator(currentRun.Text.Skip(currentBreakPosition));

                            if (lineBreaker.MoveNext())
                            {
                                measuredLength = currentBreakPosition + lineBreaker.Current.PositionWrap;
                            }
                        }
                    }

                    currentLength += measuredLength;

                    var splitResult = SplitTextRuns(textRuns, currentLength);

                    var textLineMetrics = TextLineMetrics.Create(splitResult.First,
                                                                 new TextRange(textRange.Start, currentLength), paragraphWidth, paragraphProperties);

                    var lineBreak = splitResult.Second != null && splitResult.Second.Count > 0 ?
                                    new TextLineBreak(splitResult.Second) :
                                    null;

                    return(new TextLineImpl(splitResult.First, textLineMetrics, lineBreak));
                }

                currentWidth += currentRun.GlyphRun.Bounds.Width;

                currentLength += currentRun.GlyphRun.Characters.Length;

                runIndex++;
            }

            return(new TextLineImpl(textRuns,
                                    TextLineMetrics.Create(textRuns, textRange, paragraphWidth, paragraphProperties)));
        }
示例#7
0
        /// <summary>
        /// Performs text trimming and returns a trimmed line.
        /// </summary>
        /// <param name="textRuns">The text runs to perform the trimming on.</param>
        /// <param name="textRange">The text range that is covered by the text runs.</param>
        /// <param name="paragraphWidth">A <see cref="double"/> value that specifies the width of the paragraph that the line fills.</param>
        /// <param name="paragraphProperties">A <see cref="TextParagraphProperties"/> value that represents paragraph properties,
        /// such as TextWrapping, TextAlignment, or TextStyle.</param>
        /// <returns></returns>
        private static TextLine PerformTextTrimming(IReadOnlyList <ShapedTextCharacters> textRuns, TextRange textRange,
                                                    double paragraphWidth, TextParagraphProperties paragraphProperties)
        {
            var textTrimming   = paragraphProperties.TextTrimming;
            var availableWidth = paragraphWidth;
            var currentWidth   = 0.0;
            var runIndex       = 0;

            while (runIndex < textRuns.Count)
            {
                var currentRun = textRuns[runIndex];

                currentWidth += currentRun.GlyphRun.Bounds.Width;

                if (currentWidth > availableWidth)
                {
                    var ellipsisRun = CreateEllipsisRun(currentRun.Properties);

                    var measuredLength = MeasureText(currentRun, availableWidth - ellipsisRun.GlyphRun.Bounds.Width);

                    if (textTrimming == TextTrimming.WordEllipsis)
                    {
                        if (measuredLength < textRange.End)
                        {
                            var currentBreakPosition = 0;

                            var lineBreaker = new LineBreakEnumerator(currentRun.Text);

                            while (currentBreakPosition < measuredLength && lineBreaker.MoveNext())
                            {
                                var nextBreakPosition = lineBreaker.Current.PositionWrap;

                                if (nextBreakPosition == 0)
                                {
                                    break;
                                }

                                if (nextBreakPosition > measuredLength)
                                {
                                    break;
                                }

                                currentBreakPosition = nextBreakPosition;
                            }

                            measuredLength = currentBreakPosition;
                        }
                    }

                    var splitResult = SplitTextRuns(textRuns, measuredLength);

                    var trimmedRuns = new List <ShapedTextCharacters>(splitResult.First.Count + 1);

                    trimmedRuns.AddRange(splitResult.First);

                    trimmedRuns.Add(ellipsisRun);

                    var textLineMetrics =
                        TextLineMetrics.Create(trimmedRuns, textRange, paragraphWidth, paragraphProperties);

                    return(new TextLineImpl(trimmedRuns, textLineMetrics));
                }

                availableWidth -= currentRun.GlyphRun.Bounds.Width;

                runIndex++;
            }

            return(new TextLineImpl(textRuns,
                                    TextLineMetrics.Create(textRuns, textRange, paragraphWidth, paragraphProperties)));
        }
示例#8
0
        /// <summary>
        /// Performs text wrapping returns a list of text lines.
        /// </summary>
        /// <param name="paragraphProperties">The text paragraph properties.</param>
        /// <param name="textRuns">The text run'S.</param>
        /// <param name="text">The text to analyze for break opportunities.</param>
        /// <param name="paragraphWidth"></param>
        /// <returns></returns>
        private static TextLine PerformTextWrapping(TextPointer text, IReadOnlyList <ShapedTextRun> textRuns,
                                                    double paragraphWidth, TextParagraphProperties paragraphProperties)
        {
            var availableWidth = paragraphWidth;
            var currentWidth   = 0.0;
            var runIndex       = 0;
            var length         = 0;

            while (runIndex < textRuns.Count)
            {
                var currentRun = textRuns[runIndex];

                if (currentWidth + currentRun.GlyphRun.Bounds.Width > availableWidth)
                {
                    var measuredLength = MeasureText(currentRun, paragraphWidth - currentWidth);

                    if (measuredLength < currentRun.Text.Length)
                    {
                        var currentBreakPosition = -1;

                        var lineBreaker = new LineBreakEnumerator(currentRun.Text);

                        while (currentBreakPosition < measuredLength && lineBreaker.MoveNext())
                        {
                            var nextBreakPosition = lineBreaker.Current.PositionWrap;

                            if (nextBreakPosition == 0)
                            {
                                break;
                            }

                            if (nextBreakPosition > measuredLength)
                            {
                                break;
                            }

                            currentBreakPosition = nextBreakPosition;
                        }

                        if (currentBreakPosition != -1)
                        {
                            measuredLength = currentBreakPosition;
                        }
                    }

                    length += measuredLength;

                    var splitResult = SplitTextRuns(textRuns, length);

                    var textLineMetrics =
                        TextLineMetrics.Create(splitResult.First, paragraphWidth, paragraphProperties.TextAlignment);

                    return(new SimpleTextLine(text.Take(length), splitResult.First, textLineMetrics));
                }

                currentWidth += currentRun.GlyphRun.Bounds.Width;

                length += currentRun.GlyphRun.Characters.Length;

                runIndex++;
            }

            return(new SimpleTextLine(text, textRuns,
                                      TextLineMetrics.Create(textRuns, paragraphWidth, paragraphProperties.TextAlignment)));
        }