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; } }
protected TextLine GetLine(TextRunProperties runProperties, TextSource textSource, int column = 0) { return TextFormatter.Create().FormatLine( textSource, column, 96 * 6, new SimpleParagraphProperties { defaultTextRunProperties = runProperties }, null); }
/// <summary> /// Construct a text marker object /// </summary> /// <param name="style">marker style</param> /// <param name="offset">distance from line start to the end of the marker symbol</param> /// <param name="autoNumberingIndex">autonumbering counter of counter-style marker</param> /// <param name="textParagraphProperties">text paragraph properties</param> public TextSimpleMarkerProperties( TextMarkerStyle style, double offset, int autoNumberingIndex, TextParagraphProperties textParagraphProperties ) { if (textParagraphProperties == null) throw new ArgumentNullException("textParagraphProperties"); _offset = offset; if (style != TextMarkerStyle.None) { if (TextMarkerSource.IsKnownSymbolMarkerStyle(style)) { // autoNumberingIndex is ignored } else if (TextMarkerSource.IsKnownIndexMarkerStyle(style)) { // validate autoNumberingIndex if (autoNumberingIndex < 1) { throw new ArgumentOutOfRangeException("autoNumberingIndex", SR.Get(SRID.ParameterCannotBeLessThan, 1)); } } else { // invalid style throw new ArgumentException(SR.Get(SRID.Enum_Invalid, typeof(TextMarkerStyle)), "style"); } _textSource = new TextMarkerSource( textParagraphProperties, style, autoNumberingIndex ); } }
/// <summary> /// Client to ask for the possible smallest and largest paragraph width that can fully contain the passing text content /// </summary> /// <param name="textSource">an object representing text layout clients text source for TextFormatter.</param> /// <param name="firstCharIndex">character index to specify where in the source text the line starts</param> /// <param name="paragraphProperties">properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation.</param> /// <param name="textRunCache">an object representing content cache of the client.</param> /// <returns>min max paragraph width</returns> public abstract MinMaxParagraphWidth FormatMinMaxParagraphWidth( TextSource textSource, int firstCharIndex, TextParagraphProperties paragraphProperties, TextRunCache textRunCache );
[FriendAccessAllowed] // used by Framework internal abstract TextParagraphCache CreateParagraphCache( #endif TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache );
/// <summary> /// Client to format a text line that fills a paragraph in the document. /// </summary> /// <param name="textSource">an object representing text layout clients text source for TextFormatter.</param> /// <param name="firstCharIndex">character index to specify where in the source text the line starts</param> /// <param name="paragraphWidth">width of paragraph in which the line fills</param> /// <param name="paragraphProperties">properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation.</param> /// <param name="previousLineBreak">text formatting state at the point where the previous line in the paragraph /// was broken by the text formatting process, as specified by the TextLine.LineBreak property for the previous /// line; this parameter can be null, and will always be null for the first line in a paragraph.</param> /// <param name="textRunCache">an object representing content cache of the client.</param> /// <returns>object representing a line of text that client interacts with. </returns> public abstract TextLine FormatLine( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache );
/// <summary> /// Verify all text formatting arguments /// </summary> private void VerifyTextFormattingArguments( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextRunCache textRunCache ) { if (textSource == null) throw new ArgumentNullException("textSource"); if (textRunCache == null) throw new ArgumentNullException("textRunCache"); if (paragraphProperties == null) throw new ArgumentNullException("paragraphProperties"); if (paragraphProperties.DefaultTextRunProperties == null) throw new ArgumentNullException("paragraphProperties.DefaultTextRunProperties"); if (paragraphProperties.DefaultTextRunProperties.Typeface == null) throw new ArgumentNullException("paragraphProperties.DefaultTextRunProperties.Typeface"); if (DoubleUtil.IsNaN(paragraphWidth)) throw new ArgumentOutOfRangeException("paragraphWidth", SR.Get(SRID.ParameterValueCannotBeNaN)); if (double.IsInfinity(paragraphWidth)) throw new ArgumentOutOfRangeException("paragraphWidth", SR.Get(SRID.ParameterValueCannotBeInfinity)); if ( paragraphWidth < 0 || paragraphWidth > Constants.RealInfiniteWidth) { throw new ArgumentOutOfRangeException("paragraphWidth", SR.Get(SRID.ParameterMustBeBetween, 0, Constants.RealInfiniteWidth)); } double realMaxFontRenderingEmSize = Constants.RealInfiniteWidth / Constants.GreatestMutiplierOfEm; if ( paragraphProperties.DefaultTextRunProperties.FontRenderingEmSize < 0 || paragraphProperties.DefaultTextRunProperties.FontRenderingEmSize > realMaxFontRenderingEmSize) { throw new ArgumentOutOfRangeException("paragraphProperties.DefaultTextRunProperties.FontRenderingEmSize", SR.Get(SRID.ParameterMustBeBetween, 0, realMaxFontRenderingEmSize)); } if (paragraphProperties.Indent > Constants.RealInfiniteWidth) throw new ArgumentOutOfRangeException("paragraphProperties.Indent", SR.Get(SRID.ParameterCannotBeGreaterThan, Constants.RealInfiniteWidth)); if (paragraphProperties.LineHeight > Constants.RealInfiniteWidth) throw new ArgumentOutOfRangeException("paragraphProperties.LineHeight", SR.Get(SRID.ParameterCannotBeGreaterThan, Constants.RealInfiniteWidth)); if ( paragraphProperties.DefaultIncrementalTab < 0 || paragraphProperties.DefaultIncrementalTab > Constants.RealInfiniteWidth) { throw new ArgumentOutOfRangeException("paragraphProperties.DefaultIncrementalTab", SR.Get(SRID.ParameterMustBeBetween, 0, Constants.RealInfiniteWidth)); } }
public TextLine FormatLine(TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak) { var runs = new List<Tuple<TextRun, GlyphRun, int, double>>(); int index = firstCharIndex; double x = paragraphProperties.Indent, height = 0, baseline = 0; double trailWhitespaceWidth = 0; while (true) { var run = textSource.GetTextRun(index); var textProps = run.Properties ?? paragraphProperties.DefaultTextRunProperties; var fontSize = textProps.FontRenderingEmSize; var len = run.Length; if (textProps != null) { height = Math.Max(height, (int)(textProps.Typeface.FontFamily.LineSpacing * fontSize)); baseline = Math.Max(baseline, (int)(textProps.Typeface.FontFamily.Baseline * fontSize)); } if (run is TextEndOfLine || run == null) { index += len; runs.Add(Tuple.Create(run, (GlyphRun)null, 0, 0.0)); break; } else if (run is TextCharacters) { var chrs = (TextCharacters)run; var charBuf = getCharBuf(chrs.CharacterBufferReference); var charOffset = getCharOffset(chrs.CharacterBufferReference); GlyphTypeface gl; if (!textProps.Typeface.TryGetGlyphTypeface(out gl)) throw new Exception("GlyphTypeface does not exists for font '" + textProps.Typeface.FontFamily + "'."); ushort[] glyphIndexes = new ushort[len]; double[] advanceWidths = new double[len]; double totalWidth = 0; int trailWhitespace = 0; trailWhitespaceWidth = 0; for (int n = 0; n < len; n++) { var c = charBuf[charOffset + n]; ushort glyphIndex; double width; if (c == '\t') { glyphIndex = gl.CharacterToGlyphMap[' ']; width = paragraphProperties.DefaultIncrementalTab - x % paragraphProperties.DefaultIncrementalTab; } else { if (!gl.CharacterToGlyphMap.TryGetValue(c, out glyphIndex)) glyphIndex = gl.CharacterToGlyphMap['?']; width = gl.AdvanceWidths[glyphIndex] * fontSize; } glyphIndexes[n] = glyphIndex; advanceWidths[n] = width; if (char.IsWhiteSpace(c)) { trailWhitespace++; trailWhitespaceWidth += width; } else { totalWidth += trailWhitespaceWidth + width; trailWhitespaceWidth = 0; trailWhitespace = 0; } } var origin = new Point(x, 0); var glyphRun = new GlyphRun( gl, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); runs.Add(Tuple.Create(run, glyphRun, trailWhitespace, trailWhitespaceWidth)); x += totalWidth + trailWhitespaceWidth; index += len; } else if (run is TextEmbeddedObject) { var obj = (TextEmbeddedObject)run; var metrics = obj.Format(paragraphWidth - x); runs.Add(Tuple.Create(run, (GlyphRun)null, 0, metrics.Width)); height = Math.Max(height, obj.Format(paragraphWidth - x).Height); x += metrics.Width; index += len; } } return new GlyphRunLine { entries = runs.ToArray(), baseline = baseline, width = x - trailWhitespaceWidth, height = height, mode = mode }; }
/// <summary> /// Client to ask for the possible smallest and largest paragraph width that can fully contain the passing text content /// </summary> /// <param name="textSource">an object representing text layout clients text source for TextFormatter.</param> /// <param name="firstCharIndex">character index to specify where in the source text the line starts</param> /// <param name="paragraphProperties">properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation.</param> /// <param name="textRunCache">an object representing content cache of the client.</param> /// <returns>min max paragraph width</returns> public override MinMaxParagraphWidth FormatMinMaxParagraphWidth( TextSource textSource, int firstCharIndex, TextParagraphProperties paragraphProperties, TextRunCache textRunCache ) { // prepare formatting settings FormatSettings settings = PrepareFormatSettings( textSource, firstCharIndex, 0, // infinite paragraphWidth paragraphProperties, null, // always format the whole paragraph - no previousLineBreak textRunCache, false, // optimalBreak true, // isSingleLineFormatting _textFormattingMode ); // create specialized line specifically for min/max calculation TextMetrics.FullTextLine line = new TextMetrics.FullTextLine( settings, firstCharIndex, 0, // lineLength 0, // paragraph width has no significant meaning in min/max calculation (LineFlags.KeepState | LineFlags.MinMax) ); // line width in this case is the width of a line when the entire paragraph is laid out // as a single long line. MinMaxParagraphWidth minMax = new MinMaxParagraphWidth(line.MinWidth, line.Width); line.Dispose(); return minMax; }
/// <summary> /// Client to ask for the possible smallest and largest paragraph width that can fully contain the passing text content /// </summary> /// <param name="textSource">an object representing text layout clients text source for TextFormatter.</param> /// <param name="firstCharIndex">character index to specify where in the source text the line starts</param> /// <param name="paragraphProperties">properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation.</param> /// <returns>min max paragraph width</returns> public override MinMaxParagraphWidth FormatMinMaxParagraphWidth( TextSource textSource, int firstCharIndex, TextParagraphProperties paragraphProperties ) { return FormatMinMaxParagraphWidth( textSource, firstCharIndex, paragraphProperties, new TextRunCache() // local cache, only live within this call ); }
/// <summary> /// Format and produce a text line either with or without previously known /// line break point. /// </summary> private TextLine FormatLineInternal( TextSource textSource, int firstCharIndex, int lineLength, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache ) { EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordText, EventTrace.Level.Verbose, EventTrace.Event.WClientStringBegin, "TextFormatterImp.FormatLineInternal Start"); // prepare formatting settings FormatSettings settings = PrepareFormatSettings( textSource, firstCharIndex, paragraphWidth, paragraphProperties, previousLineBreak, textRunCache, (lineLength != 0), // Do optimal break if break is given true, // isSingleLineFormatting _textFormattingMode ); TextLine textLine = null; if ( !settings.Pap.AlwaysCollapsible && previousLineBreak == null && lineLength <= 0 ) { // simple text line. textLine = SimpleTextLine.Create( settings, firstCharIndex, RealToIdealFloor(paragraphWidth) ) as TextLine; } if (textLine == null) { // content is complex, creating complex line textLine = new TextMetrics.FullTextLine( settings, firstCharIndex, lineLength, RealToIdealFloor(paragraphWidth), LineFlags.None ) as TextLine; } EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordText, EventTrace.Level.Verbose, EventTrace.Event.WClientStringEnd, "TextFormatterImp.FormatLineInternal End"); return textLine; }
internal override TextLine RecreateLine( #endif TextSource textSource, int firstCharIndex, int lineLength, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache ) { return FormatLineInternal( textSource, firstCharIndex, lineLength, paragraphWidth, paragraphProperties, previousLineBreak, textRunCache ); }
/// <summary> /// Client to format a text line that fills a paragraph in the document. /// </summary> /// <param name="textSource">an object representing text layout clients text source for TextFormatter.</param> /// <param name="firstCharIndex">character index to specify where in the source text the line starts</param> /// <param name="paragraphWidth">width of paragraph in which the line fills</param> /// <param name="paragraphProperties">properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation.</param> /// <param name="previousLineBreak">LineBreak property of the previous text line, or null if this is the first line in the paragraph</param> /// <param name="textRunCache">an object representing content cache of the client.</param> /// <returns>object representing a line of text that client interacts with. </returns> public override TextLine FormatLine( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache ) { return FormatLineInternal( textSource, firstCharIndex, 0, // lineLength paragraphWidth, paragraphProperties, previousLineBreak, textRunCache ); }
/// <summary> /// Client to format a text line that fills a paragraph in the document. /// </summary> /// <param name="textSource">an object representing text layout clients text source for TextFormatter.</param> /// <param name="firstCharIndex">character index to specify where in the source text the line starts</param> /// <param name="paragraphWidth">width of paragraph in which the line fills</param> /// <param name="paragraphProperties">properties that can change from one paragraph to the next, such as text flow direction, text alignment, or indentation.</param> /// <param name="previousLineBreak">LineBreak property of the previous text line, or null if this is the first line in the paragraph</param> /// <returns>object representing a line of text that client interacts with. </returns> public override TextLine FormatLine( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak ) { return FormatLineInternal( textSource, firstCharIndex, 0, // lineLength paragraphWidth, paragraphProperties, previousLineBreak, new TextRunCache() // local cache, only live within this call ); }
public TextLine FormatLine(TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak) { return formatter.FormatLine(textSource, firstCharIndex, paragraphWidth, paragraphProperties, previousLineBreak); }
/// <summary> /// Wrapper of TextFormatter.FormatLine that auto-collapses the line if needed. /// </summary> private TextLine FormatLine(TextSource textSource, int textSourcePosition, double maxLineLength, TextParagraphProperties paraProps, TextLineBreak lineBreak) { TextLine line = _formatter.FormatLine( textSource, textSourcePosition, maxLineLength, paraProps, lineBreak ); if (_that._trimming != TextTrimming.None && line.HasOverflowed && line.Length > 0) { // what I really need here is the last displayed text run of the line // textSourcePosition + line.Length - 1 works except the end of paragraph case, // where line length includes the fake paragraph break run Debug.Assert(_that._text.Length > 0 && textSourcePosition + line.Length <= _that._text.Length + 1); SpanRider thatFormatRider = new SpanRider( _that._formatRuns, _that._latestPosition, Math.Min(textSourcePosition + line.Length - 1, _that._text.Length - 1) ); GenericTextRunProperties lastRunProps = thatFormatRider.CurrentElement as GenericTextRunProperties; TextCollapsingProperties trailingEllipsis; if (_that._trimming == TextTrimming.CharacterEllipsis) trailingEllipsis = new TextTrailingCharacterEllipsis(maxLineLength, lastRunProps); else { Debug.Assert(_that._trimming == TextTrimming.WordEllipsis); trailingEllipsis = new TextTrailingWordEllipsis(maxLineLength, lastRunProps); } TextLine collapsedLine = line.Collapse(trailingEllipsis); if (collapsedLine != line) { line.Dispose(); line = collapsedLine; } } return line; }
private void FormatLine( FullTextState fullText, int cpFirst, int lineLength, int formatWidth, int finiteFormatWidth, int paragraphWidth, LineFlags lineFlags, FormattedTextSymbols collapsingSymbol ) { _metrics._formatter = fullText.Formatter; Debug.Assert(_metrics._formatter != null); TextStore store = fullText.TextStore; TextStore markerStore = fullText.TextMarkerStore; FormatSettings settings = store.Settings; ParaProp pap = settings.Pap; _paragraphTextDecorations = pap.TextDecorations; if (_paragraphTextDecorations != null) { if (_paragraphTextDecorations.Count != 0) { _defaultTextDecorationsBrush = pap.DefaultTextDecorationsBrush; } else { _paragraphTextDecorations = null; } } // acquiring LS context TextFormatterContext context = _metrics._formatter.AcquireContext(fullText, IntPtr.Zero); LsLInfo plslineInfo = new LsLInfo(); LsLineWidths lineWidths = new LsLineWidths(); fullText.SetTabs(context); int lscpLineLength = 0; // line length in LSCP if (lineLength > 0) { // line length is previously known (e.g. during optimal paragraph formatting), // prefetch lsruns up to the specified line length. lscpLineLength = PrefetchLSRuns(store, cpFirst, lineLength); } IntPtr ploline; LsErr lserr = context.CreateLine( cpFirst, lscpLineLength, formatWidth, lineFlags, IntPtr.Zero, // single-line formatting does not require break record out ploline, out plslineInfo, out _depthQueryMax, out lineWidths ); // Did we exceed the LineServices maximum line width? if (lserr == LsErr.TooLongParagraph) { // Determine where to insert a fake line break. FullTextState.CpMeasured // is a reasonable estimate since we know the nominal widths up to that // point fit within the margin. int cpLimit = fullText.CpMeasured; int subtract = 1; for (;;) { // The line must contain at least one character position. if (cpLimit < 1) { cpLimit = 1; } store.InsertFakeLineBreak(cpLimit); lserr = context.CreateLine( cpFirst, lscpLineLength, formatWidth, lineFlags, IntPtr.Zero, // single-line formatting does not require break record out ploline, out plslineInfo, out _depthQueryMax, out lineWidths ); if (lserr != LsErr.TooLongParagraph || cpLimit == 1) { // We're done or can't chop off any more text. break; } else { // Chop off more text and try again. Double the amount of // text we chop off each time so we retry too many times. cpLimit = fullText.CpMeasured - subtract; subtract *= 2; } } } _ploline.Value = ploline; // get the exception in context before it is released Exception callbackException = context.CallbackException; // release the context context.Release(); if(lserr != LsErr.None) { GC.SuppressFinalize(this); if(callbackException != null) { // rethrow exception thrown in callbacks throw WrapException(callbackException); } else { // throw with LS error codes TextFormatterContext.ThrowExceptionFromLsError(SR.Get(SRID.CreateLineFailure, lserr), lserr); } } // keep context alive at least till here GC.KeepAlive(context); unsafe { // construct text metrics for the line _metrics.Compute( fullText, cpFirst, paragraphWidth, collapsingSymbol, ref lineWidths, &plslineInfo ); } // keep record for min width as we may be formatting min/max _textMinWidthAtTrailing = lineWidths.upMinStartTrailing - _metrics._textStart; if (collapsingSymbol != null) { _collapsingSymbol = collapsingSymbol; _textMinWidthAtTrailing += TextFormatterImp.RealToIdeal(collapsingSymbol.Width); } else { // 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); hasOverflowed = (TextFormatterImp.CompareReal(realWidth, realFormatWidth, _textFormattingMode) > 0); } if (hasOverflowed) { // line has overflowed _statusFlags |= StatusFlags.HasOverflowed; // let's keep the full text state around. We'll need it later for collapsing _fullText = fullText; } } } if ( fullText != null && ( fullText.KeepState || (_statusFlags & StatusFlags.KeepState) != 0 ) ) { // the state of full text is to be kept after formatting is done _fullText = fullText; } // retain all line properties for interactive operations _ploc = context.Ploc; _cpFirst = cpFirst; _paragraphWidth = paragraphWidth; if (pap.RightToLeft) _statusFlags |= StatusFlags.RightToLeft; if (plslineInfo.fForcedBreak != 0) _statusFlags |= StatusFlags.IsTruncated; // retain the state of plsruns _plsrunVector = store.PlsrunVector; _lsrunsMainText = store.LsrunList; if (markerStore != null) _lsrunsMarkerText = markerStore.LsrunList; // we store the text source in the line in case drawing code calls // the TextSource to find out the text effect index. // _textSource = settings.TextSource; }
internal override TextParagraphCache CreateParagraphCache( #endif TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache ) { // prepare formatting settings FormatSettings settings = PrepareFormatSettings( textSource, firstCharIndex, paragraphWidth, paragraphProperties, previousLineBreak, textRunCache, true, // optimalBreak false, // !isSingleLineFormatting _textFormattingMode ); // // Optimal paragraph formatting session specific check // if (!settings.Pap.Wrap && settings.Pap.OptimalBreak) { // Optimal paragraph must wrap. throw new ArgumentException(SR.Get(SRID.OptimalParagraphMustWrap)); } // create paragraph content cache object return new TextParagraphCache( settings, firstCharIndex, RealToIdeal(paragraphWidth) ); }
/// <summary> /// Get text immediately preceding cpLimit. /// </summary> internal TextSpan<CultureSpecificCharacterBufferRange> GetPrecedingText(TextSource textSource, int cpLimit) { if (cpLimit > 0) { SpanRider textRunSpanRider = new SpanRider(_textRunVector, _latestPosition); if (textRunSpanRider.At(cpLimit - 1)) { CharacterBufferRange charString = CharacterBufferRange.Empty; CultureInfo culture = null; TextRun run = textRunSpanRider.CurrentElement as TextRun; if (run != null) { // Only TextRun containing text would have non-empty Character buffer range. if ( TextRunInfo.GetRunType(run) == Plsrun.Text && run.CharacterBufferReference.CharacterBuffer != null) { charString = new CharacterBufferRange( run.CharacterBufferReference, cpLimit - textRunSpanRider.CurrentSpanStart); culture = CultureMapper.GetSpecificCulture(run.Properties.CultureInfo); } return new TextSpan<CultureSpecificCharacterBufferRange>( cpLimit - textRunSpanRider.CurrentSpanStart, // cp length new CultureSpecificCharacterBufferRange(culture, charString) ); } } } // not in cache so call back to client return textSource.GetPrecedingText(cpLimit); }
/// <summary> /// Validate all the relevant text formatting initial settings and package them /// </summary> private FormatSettings PrepareFormatSettings( TextSource textSource, int firstCharIndex, double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak previousLineBreak, TextRunCache textRunCache, bool useOptimalBreak, bool isSingleLineFormatting, TextFormattingMode textFormattingMode ) { VerifyTextFormattingArguments( textSource, firstCharIndex, paragraphWidth, paragraphProperties, textRunCache ); if (textRunCache.Imp == null) { // No run cache object available, create one textRunCache.Imp = new TextRunCacheImp(); } // initialize formatting settings return new FormatSettings( this, textSource, textRunCache.Imp, new ParaProp(this, paragraphProperties, useOptimalBreak), previousLineBreak, isSingleLineFormatting, textFormattingMode, false ); }