Example #1
0
 // 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;
        }
Example #3
0
        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;
        }
Example #4
0
        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;
        }
Example #5
0
        /// <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;
        }