/// <summary> /// format text line using LS /// </summary> /// <param name="fullText">state of the full text backing store</param> /// <param name="cpFirst">first cp to format</param> /// <param name="lineLength">character length of the line</param> /// <param name="formatWidth">width used to format</param> /// <param name="finiteFormatWidth">width used to detect overflowing of format result</param> /// <param name="paragraphWidth">paragraph width</param> /// <param name="lineFlags">line formatting control flags</param> /// <param name="collapsingSymbol">line end collapsing symbol</param> private void FormatLine( FullTextState fullText, int cpFirst, int lineLength, int formatWidth, int finiteFormatWidth, int paragraphWidth, LineFlags lineFlags, FormattedTextSymbols collapsingSymbol ) { _fullText = fullText; _paragraphWidth = paragraphWidth; TextStore store = fullText.TextStore; FormatSettings settings = store.Settings; ParaProp pap = settings.Pap; _paragraphTextDecorations = pap.TextDecorations; if (_paragraphTextDecorations != null) { if (_paragraphTextDecorations.Count != 0) { _defaultTextDecorationsBrush = pap.DefaultTextDecorationsBrush; } else { _paragraphTextDecorations = null; } } _metrics = GetLineMetrics(fullText, cpFirst, lineLength, formatWidth, finiteFormatWidth, paragraphWidth, lineFlags, collapsingSymbol); lineLength = _metrics._cchLength; if (lineLength > _metrics._cchNewline) { var lineBreakpoints = store.FindLineBreakpoints(cpFirst, lineLength); // check for line wrap if (pap.Wrap && _metrics._textStart + _metrics._textWidthAtTrailing > finiteFormatWidth) { for (int i = lineLength - 1; i > 0; i--) { if (lineBreakpoints.GetBreakConditionBefore(i + cpFirst) == DWriteBreakCondition.CanBreak) { var trailingWhitespace = lineBreakpoints.WhitespaceLengthBefore(i + cpFirst); var trimmedMetrics = GetLineMetrics(fullText, cpFirst, i - trailingWhitespace, formatWidth, finiteFormatWidth, paragraphWidth, lineFlags, collapsingSymbol); if (trimmedMetrics._textStart + trimmedMetrics._textWidthAtTrailing <= finiteFormatWidth) { _metrics = GetLineMetrics(fullText, cpFirst, i, formatWidth, finiteFormatWidth, paragraphWidth, lineFlags, collapsingSymbol); _metrics._cchTrailing = trailingWhitespace; _metrics._textWidthAtTrailing = trimmedMetrics._textWidth; break; } } } } } if (collapsingSymbol == null) { // overflow detection for potential collapsible line if (_metrics._textStart + _metrics._textWidthAtTrailing > finiteFormatWidth) { bool hasOverflowed = true; if (_textFormattingMode == TextFormattingMode.Display) { // apply display-mode rounding before checking for overflow double realWidth = Width; double realFormatWidth = _metrics._formatter.IdealToReal(finiteFormatWidth, PixelsPerDip); hasOverflowed = (TextFormatterImp.CompareReal(realWidth, realFormatWidth, PixelsPerDip, _textFormattingMode) > 0); } if (hasOverflowed) { // line has overflowed _statusFlags |= StatusFlags.HasOverflowed; } } } }