internal FormatSettings( TextFormatterImp formatter, TextSource textSource, TextRunCacheImp runCache, ParaProp pap, TextLineBreak previousLineBreak, bool isSingleLineFormatting, TextFormattingMode textFormattingMode, bool isSideways ) { _isSideways = isSideways; _textFormattingMode = textFormattingMode; _formatter = formatter; _textSource = textSource; _runCache = runCache; _pap = pap; _digitState = new DigitState(); _previousLineBreak = previousLineBreak; _maxLineWidth = Constants.IdealInfiniteWidth; if (isSingleLineFormatting) { // Apply text indent on each line in single line mode _textIndent = _pap.Indent; } }
private TextMetrics GetRunMetrics(FullTextState textState, TextRun textRun, CharacterBufferRange chars) { if (textRun is TextCharacters) { var textChars = (TextCharacters)textRun; var result = new TextMetrics(); var props = textChars.Properties; var typeface = props.Typeface; var ideal_emsize = TextFormatterImp.RealToIdeal(props.FontRenderingEmSize); result._textAscent = (int)Math.Round(typeface.Baseline(ideal_emsize, Constants.DefaultIdealToReal, props.PixelsPerDip, _textFormattingMode)); result._textHeight = (int)Math.Round(typeface.LineSpacing(ideal_emsize, Constants.DefaultIdealToReal, props.PixelsPerDip, _textFormattingMode)); result._height = result._textHeight; result._baselineOffset = result._textAscent; // width calculation var formatted = GetFormattedTextSymbols(textChars, chars, 0); // isSideways result._textWidth = formatted.UnscaledWidth; return(result); } else if (textRun is TextHidden) { var result = new TextMetrics(); // Default should be empty return(result); } else { throw new NotImplementedException(String.Format("Managed.TextFormatting.FullTextLine.GetRunMetrics for {0}", textRun.GetType().FullName)); } }
/// <summary> /// Get distance from the start of main text to the end of marker /// </summary> /// <remarks> /// Positive distance is filtered out. Marker overlapping the main text is not supported. /// </remarks> internal int GetMainTextToMarkerIdealDistance() { if (_markerStore != null) { return(Math.Min(0, TextFormatterImp.RealToIdeal(_markerStore.Pap.TextMarkerProperties.Offset) - _store.Settings.TextIndent)); } return(0); }
public override void Draw(DrawingContext drawingContext, Point origin, InvertAxes inversion) { if (drawingContext == null) { throw new ArgumentNullException("drawingContext"); } if ((_statusFlags & StatusFlags.IsDisposed) != 0) { throw new ObjectDisposedException(SR.Get(SRID.TextLineHasBeenDisposed)); } MatrixTransform antiInversion = TextFormatterImp.CreateAntiInversionTransform( inversion, _metrics._formatter.IdealToReal(_paragraphWidth, PixelsPerDip), _metrics._formatter.IdealToReal(_metrics._height, PixelsPerDip) ); origin = AdjustOffset(origin); if (antiInversion == null) { DrawTextLine(drawingContext, origin, null); } else { // Apply anti-inversion transform to correct the visual drawingContext.PushTransform(antiInversion); try { DrawTextLine(drawingContext, origin, antiInversion); } finally { drawingContext.Pop(); } } }
/// <summary> /// Constructing paragraph properties /// </summary> /// <param name="formatter">Text formatter</param> /// <param name="paragraphProperties">paragraph properties</param> /// <param name="optimalBreak">produce optimal break</param> internal ParaProp( TextFormatterImp formatter, TextParagraphProperties paragraphProperties, bool optimalBreak ) { _paragraphProperties = paragraphProperties; _emSize = TextFormatterImp.RealToIdeal(paragraphProperties.DefaultTextRunProperties.FontRenderingEmSize); _indent = TextFormatterImp.RealToIdeal(paragraphProperties.Indent); _paragraphIndent = TextFormatterImp.RealToIdeal(paragraphProperties.ParagraphIndent); _height = TextFormatterImp.RealToIdeal(paragraphProperties.LineHeight); if (_paragraphProperties.FlowDirection == FlowDirection.RightToLeft) { _statusFlags |= StatusFlags.Rtl; } if (optimalBreak) { _statusFlags |= StatusFlags.OptimalBreak; } }
/// <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; } } } }