public override IReadOnlyList <TextRun>?Collapse(TextLine textLine) { return(TextEllipsisHelper.Collapse(textLine, this, false)); }
public override void Justify(TextLine textLine) { var paragraphWidth = Width; if (double.IsInfinity(paragraphWidth)) { return; } if (textLine.NewLineLength > 0) { return; } var textLineBreak = textLine.TextLineBreak; if (textLineBreak is not null && textLineBreak.TextEndOfLine is not null) { if (textLineBreak.RemainingRuns is null || textLineBreak.RemainingRuns.Count == 0) { return; } } var breakOportunities = new Queue <int>(); foreach (var textRun in textLine.TextRuns) { var text = textRun.Text; if (text.IsEmpty) { continue; } var start = text.Start; var lineBreakEnumerator = new LineBreakEnumerator(text); while (lineBreakEnumerator.MoveNext()) { var currentBreak = lineBreakEnumerator.Current; if (!currentBreak.Required && currentBreak.PositionWrap != text.Length) { breakOportunities.Enqueue(start + currentBreak.PositionMeasure); } } } if (breakOportunities.Count == 0) { return; } var remainingSpace = Math.Max(0, paragraphWidth - textLine.WidthIncludingTrailingWhitespace); var spacing = remainingSpace / breakOportunities.Count; foreach (var textRun in textLine.TextRuns) { var text = textRun.Text; if (text.IsEmpty) { continue; } if (textRun is ShapedTextCharacters shapedText) { var glyphRun = shapedText.GlyphRun; var shapedBuffer = shapedText.ShapedBuffer; var currentPosition = text.Start; while (breakOportunities.Count > 0) { var characterIndex = breakOportunities.Dequeue(); if (characterIndex < currentPosition) { continue; } var glyphIndex = glyphRun.FindGlyphIndex(characterIndex); var glyphInfo = shapedBuffer.GlyphInfos[glyphIndex]; shapedBuffer.GlyphInfos[glyphIndex] = new GlyphInfo(glyphInfo.GlyphIndex, glyphInfo.GlyphCluster, glyphInfo.GlyphAdvance + spacing); } glyphRun.GlyphAdvances = shapedBuffer.GlyphAdvances; } } }
public override List <DrawableTextRun>?Collapse(TextLine textLine) { return(TextEllipsisHelper.Collapse(textLine, this, true)); }
/// <summary> /// Updates the layout and applies specified text style overrides. /// </summary> private void UpdateLayout() { if (_text.IsEmpty || MathUtilities.IsZero(MaxWidth) || MathUtilities.IsZero(MaxHeight)) { var textLine = CreateEmptyTextLine(0); TextLines = new List <TextLine> { textLine }; Size = new Size(0, textLine.LineMetrics.Size.Height); } else { var textLines = new List <TextLine>(); double width = 0.0, height = 0.0; var currentPosition = 0; var textSource = new FormattedTextSource(_text, _paragraphProperties.DefaultTextRunProperties, _textStyleOverrides); TextLine previousLine = null; while (currentPosition < _text.Length) { var textLine = TextFormatter.Current.FormatLine(textSource, currentPosition, MaxWidth, _paragraphProperties, previousLine?.LineBreak); currentPosition += textLine.TextRange.Length; if (textLines.Count > 0) { if (textLines.Count == MaxLines || !double.IsPositiveInfinity(MaxHeight) && height + textLine.LineMetrics.Size.Height > MaxHeight) { if (previousLine?.LineBreak != null && _textTrimming != TextTrimming.None) { var collapsedLine = previousLine.Collapse(GetCollapsingProperties(MaxWidth)); textLines[textLines.Count - 1] = collapsedLine; } break; } } var hasOverflowed = textLine.LineMetrics.HasOverflowed; if (hasOverflowed && _textTrimming != TextTrimming.None) { textLine = textLine.Collapse(GetCollapsingProperties(MaxWidth)); } textLines.Add(textLine); UpdateBounds(textLine, ref width, ref height); previousLine = textLine; if (currentPosition != _text.Length || textLine.LineBreak == null) { continue; } var emptyTextLine = CreateEmptyTextLine(currentPosition); textLines.Add(emptyTextLine); } Size = new Size(width, height); TextLines = textLines; } }
/// <summary> /// Collapses given text line. /// </summary> /// <param name="textLine">Text line to collapse.</param> public abstract IReadOnlyList <TextRun>?Collapse(TextLine textLine);