// Token: 0x0600664C RID: 26188 RVA: 0x001CBF94 File Offset: 0x001CA194 internal LineMetrics(LineMetrics source, double start, double width) { this._start = start; this._width = width; this._height = source.Height; this._baseline = source.Baseline; this._textLineBreak = source.TextLineBreak; this._packedData = (source._packedData | LineMetrics.HasBeenUpdatedMask); }
internal LineMetrics(LineMetrics source, double start, double width) { #if DEBUG _wrappingWidth = source.WrappingWidth; #endif _start = start; _width = width; _height = source.Height; _baseline = source.Baseline; _textLineBreak = source.TextLineBreak; _packedData = source._packedData | HasBeenUpdatedMask; }
private LineMetrics UpdateLine(int index, LineMetrics metrics, double start, double width) { metrics = new LineMetrics(metrics, start, width); if (index == 0) { _firstLine = metrics; } else { _subsequentLines[index - 1] = metrics; } return metrics; }
/// <summary> /// Content measurement. /// </summary> /// <param name="constraint">Constraint size.</param> /// <returns>Computed desired size.</returns> protected sealed override Size MeasureOverride(Size constraint) { VerifyReentrancy(); #if TEXTPANELLAYOUTDEBUG MS.Internal.PtsHost.TextPanelDebug.BeginScope("TextBlock.MeasureOverride", MS.Internal.PtsHost.TextPanelDebug.Category.MeasureArrange); MS.Internal.PtsHost.TextPanelDebug.StartTimer("TextBlock.MeasureOverride", MS.Internal.PtsHost.TextPanelDebug.Category.MeasureArrange); #endif // Clear and repopulate our text block cache. (Handles multiple measure before arrange) _textBlockCache = null; EnsureTextBlockCache(); LineProperties lineProperties = _textBlockCache._lineProperties; // Hook up our TextContainer event listeners if we haven't yet. if (CheckFlags(Flags.PendingTextContainerEventInit)) { Invariant.Assert(_complexContent != null); InitializeTextContainerListeners(); SetFlags(false, Flags.PendingTextContainerEventInit); } // Find out if we can skip measure process. Measure cannot be skipped in following situations: // a) content is dirty (properties or content) // b) there are inline objects (they may be dynamically sized) int lineCount = LineCount; if ((lineCount > 0) && IsMeasureValid && InlineObjects == null) { // Assuming that all of above conditions are true, Measure can be // skipped in following situations: // 1) TextTrimming == None and: // a) Width is the same, or // b) TextWrapping == NoWrap // 2) Width is the same and TextWrapping == NoWrap bool bypassMeasure; if (lineProperties.TextTrimming == TextTrimming.None) { bypassMeasure = DoubleUtil.AreClose(constraint.Width, _referenceSize.Width) || (lineProperties.TextWrapping == TextWrapping.NoWrap); } else { bypassMeasure = DoubleUtil.AreClose(constraint.Width, _referenceSize.Width) && (lineProperties.TextWrapping == TextWrapping.NoWrap) && (DoubleUtil.AreClose(constraint.Height, _referenceSize.Height) || lineCount == 1); } if (bypassMeasure) { _referenceSize = constraint; #if TEXTPANELLAYOUTDEBUG MS.Internal.PtsHost.TextPanelDebug.Log("MeasureOverride bypassed.", MS.Internal.PtsHost.TextPanelDebug.Category.MeasureArrange); MS.Internal.PtsHost.TextPanelDebug.StopTimer("TextBlock.MeasureOverride", MS.Internal.PtsHost.TextPanelDebug.Category.MeasureArrange); MS.Internal.PtsHost.TextPanelDebug.EndScope(MS.Internal.PtsHost.TextPanelDebug.Category.MeasureArrange); #endif return _previousDesiredSize; } } // Store constraint size, it is used when measuring inline objects. _referenceSize = constraint; // Store previous ITextEmbeddable values bool formattedOnce = CheckFlags(Flags.FormattedOnce); double baselineOffsetPrevious = _baselineOffset; // Reset inline objects cache and line metrics cache. // They will be fully updated during lines formatting. InlineObjects = null; // before erasing the line metrics, keep track of how big it was last time // so that we can initialize the metrics array to that size this time int subsequentLinesInitialSize = (_subsequentLines == null) ? 1 : _subsequentLines.Count; ClearLineMetrics(); if (_complexContent != null) { _complexContent.TextView.Invalidate(); } // To determine natural size of the text TextAlignment has to be ignored. // Since for rendering/hittesting lines are recreated, it can be done without // any problems. lineProperties.IgnoreTextAlignment = true; SetFlags(true, Flags.RequiresAlignment); // Need to update LineMetrics.Start when FinalSize is known. SetFlags(true, Flags.FormattedOnce); SetFlags(false, Flags.HasParagraphEllipses); SetFlags(true, Flags.MeasureInProgress | Flags.TreeInReadOnlyMode); Size desiredSize = new Size(); bool exceptionThrown = true; try { // Create and format lines until end of paragraph is reached. // Since we are disposing line object, it can be reused to format following lines. Line line = CreateLine(lineProperties); bool endOfParagraph = false; int dcp = 0; TextLineBreak textLineBreakIn = null; Thickness padding = this.Padding; Size contentSize = new Size(Math.Max(0.0, constraint.Width - (padding.Left + padding.Right)), Math.Max(0.0, constraint.Height - (padding.Top + padding.Bottom))); // Make sure that TextFormatter limitations are not exceeded. // TextDpi.EnsureValidLineWidth(ref contentSize); while (!endOfParagraph) { using(line) { // Format line. Set showParagraphEllipsis flag to false because we do not know whether or not the line will have // paragraph ellipsis at this time. Since TextBlock is auto-sized we do not know the RenderSize until we finish Measure line.Format(dcp, contentSize.Width, GetLineProperties(dcp == 0, lineProperties), textLineBreakIn, _textBlockCache._textRunCache, /*Show paragraph ellipsis*/ false); double lineHeight = CalcLineAdvance(line.Height, lineProperties); #if DEBUG LineMetrics metrics = new LineMetrics(contentSize.Width, line.Length, line.Width, lineHeight, line.BaselineOffset, line.HasInlineObjects(), textLineBreakIn); #else LineMetrics metrics = new LineMetrics(line.Length, line.Width, lineHeight, line.BaselineOffset, line.HasInlineObjects(), textLineBreakIn); #endif if (!CheckFlags(Flags.HasFirstLine)) { SetFlags(true, Flags.HasFirstLine); _firstLine = metrics; } else { if (_subsequentLines == null) { _subsequentLines = new List<LineMetrics>(subsequentLinesInitialSize); } _subsequentLines.Add(metrics); } // Desired width is always max of calculated line widths. // Desired height is sum of all line heights. But if TextTrimming is on // do not overflow the requested height with the exception for the first line. desiredSize.Width = Math.Max(desiredSize.Width, line.GetCollapsedWidth()); if ((lineProperties.TextTrimming == TextTrimming.None) || (contentSize.Height >= (desiredSize.Height + lineHeight)) || (dcp == 0)) { // BaselineOffset is always distance from the Text's top // to the baseline offset of the last line. _baselineOffset = desiredSize.Height + line.BaselineOffset; desiredSize.Height += lineHeight; } else { // Note the fact that there are paragraph ellipses SetFlags(true, Flags.HasParagraphEllipses); } textLineBreakIn = line.GetTextLineBreak(); endOfParagraph = line.EndOfParagraph; dcp += line.Length; // don't wrap a line that was artificially broken because of excessive length if (!endOfParagraph && lineProperties.TextWrapping == TextWrapping.NoWrap && line.Length == MS.Internal.TextFormatting.TextStore.MaxCharactersPerLine) { endOfParagraph = true; } } } desiredSize.Width += (padding.Left + padding.Right); desiredSize.Height += (padding.Top + padding.Bottom); Invariant.Assert(textLineBreakIn == null); // End of paragraph should have no line break record exceptionThrown = false; } finally { // Restore original line properties lineProperties.IgnoreTextAlignment = false; SetFlags(false, Flags.MeasureInProgress | Flags.TreeInReadOnlyMode); if(exceptionThrown) { _textBlockCache._textRunCache = null; ClearLineMetrics(); } } // Notify ITextHost that ITextEmbeddable values have been changed, if necessary. if (!DoubleUtil.AreClose(baselineOffsetPrevious, _baselineOffset)) { CoerceValue(BaselineOffsetProperty); } #if TEXTPANELLAYOUTDEBUG MS.Internal.PtsHost.TextPanelDebug.StopTimer("TextBlock.MeasureOverride", MS.Internal.PtsHost.TextPanelDebug.Category.MeasureArrange); MS.Internal.PtsHost.TextPanelDebug.EndScope(MS.Internal.PtsHost.TextPanelDebug.Category.MeasureArrange); #endif _previousDesiredSize = desiredSize; return desiredSize; }