Пример #1
0
        private double                      _baseGuidelineY;            // the Y guideline of the text line.

        /// <summary>
        /// Construct drawing state for full text
        /// </summary>
        internal DrawingState(
            DrawingContext                  drawingContext,
            Point                           lineOrigin,
            MatrixTransform                 antiInversion,
            TextMetrics.FullTextLine        currentLine
            )
        {
            _drawingContext = drawingContext;
            _antiInversion = antiInversion;
            _currentLine = currentLine;            

            if (antiInversion == null)
            {
                _lineOrigin = lineOrigin;
            }
            else
            {
                _vectorToLineOrigin = lineOrigin;
            }

            if (_drawingContext != null)
            {
                // LineServices draws GlyphRun and TextDecorations in multiple 
                // callbacks and GlyphRuns may have different baselines. Pushing guideline
                // for each DrawGlyphRun are too costly. We optimize for the common case where
                // GlyphRuns and TextDecorations in the TextLine share the same baseline. 
                _baseGuidelineY = lineOrigin.Y + currentLine.Baseline;

                _drawingContext.PushGuidelineY1(_baseGuidelineY);
            }
        }
Пример #2
0
            /// <summary>
            /// Client to collapse the line to fit for display
            /// </summary>
            /// <param name="collapsingPropertiesList">a list of collapsing properties</param>
            public override TextLine Collapse(
                params TextCollapsingProperties[]   collapsingPropertiesList
                )
            {
                if ((_statusFlags & StatusFlags.IsDisposed) != 0)
                {
                    throw new ObjectDisposedException(SR.Get(SRID.TextLineHasBeenDisposed));
                }

                if (    !HasOverflowed
                    &&  (_statusFlags & StatusFlags.KeepState) == 0)
                {
                    // Attempt to collapse a non-overflowed line results in the original line returned
                    return this;
                }

                if (collapsingPropertiesList == null || collapsingPropertiesList.Length == 0)
                    throw new ArgumentNullException("collapsingPropertiesList");

                TextCollapsingProperties collapsingProp = collapsingPropertiesList[0];
                double constraintWidth = collapsingProp.Width;

                if (TextFormatterImp.CompareReal(constraintWidth, Width, _textFormattingMode) > 0)
                {
                    // constraining width is greater than original line width, no collapsing neeeded.
                    return this;
                }

                FormattedTextSymbols symbol = null;

                if (collapsingProp.Symbol != null)
                {
                    // create formatted collapsing symbol
                    symbol = new FormattedTextSymbols(
                        _metrics._formatter.GlyphingCache,
                        collapsingProp.Symbol,
                        RightToLeft,
                        TextFormatterImp.ToIdeal,
                        _textFormattingMode,
                        false
                        );
                    constraintWidth -= symbol.Width;
                }

                Debug.Assert(_fullText != null);

                FullTextLine line = new TextMetrics.FullTextLine(_textFormattingMode, IsJustified);

                // collapsing preserves original line metrics
                Debug.Assert(_metrics._height > 0);
                line._metrics._formatter = _metrics._formatter;
                line._metrics._height = _metrics._height;
                line._metrics._baselineOffset = _metrics._baselineOffset;

                if (constraintWidth > 0)
                {
                    // format main text line with constraint width

                    int finiteFormatWidth = _fullText.TextStore.Settings.GetFiniteFormatWidth(
                        TextFormatterImp.RealToIdeal(constraintWidth)
                        );

                    bool forceWrap = _fullText.ForceWrap;
                    _fullText.ForceWrap = true;

                    if ((_statusFlags & StatusFlags.KeepState) != 0)
                    {
                        // inherit this flag so the collapsed line retains full text state too.
                        line._statusFlags |= StatusFlags.KeepState;
                    }

                    line.FormatLine(
                        _fullText,
                        _cpFirst,
                        0,  // no line length limit
                        finiteFormatWidth,
                        finiteFormatWidth,
                        _paragraphWidth,    // collapsed line is still bound to the original paragraph width
                        (collapsingProp.Style == TextCollapsingStyle.TrailingCharacter ? LineFlags.BreakAlways : LineFlags.None),
                        symbol
                        );

                    _fullText.ForceWrap = forceWrap;

                    line._metrics._cchDepend = 0; // no dependency
                }
                else if (symbol != null)
                {
                    line.AppendCollapsingSymbol(symbol);
                }

                if (line._metrics._cchLength < Length)
                {
                    line._collapsedRange = new TextCollapsedRange(
                        _cpFirst + line._metrics._cchLength,
                        Length - line._metrics._cchLength,
                        Width - line.Width
                        );

                    // collapsed line has the original length
                    line._metrics._cchLength = Length;
                }

                // mark the indication flags signify collapsing
                line._statusFlags |= StatusFlags.HasCollapsed;
                line._statusFlags &= ~StatusFlags.HasOverflowed;

                return line;
            }
        /// <summary>
        /// Client to collapse the line to fit for display
        /// </summary>
        /// <param name="collapsingPropertiesList">a list of collapsing properties</param>
        public override TextLine Collapse(
            params TextCollapsingProperties[]   collapsingPropertiesList
            )
        {
            if (!HasOverflowed)
                return this;

            Invariant.Assert(_settings != null);

            // instantiate a collapsible full text line, collapse it and return the collapsed line
            TextMetrics.FullTextLine textLine = new TextMetrics.FullTextLine(
                _settings,
                _cpFirst,
                0,  // lineLength
                TextFormatterImp.RealToIdeal(_paragraphWidth),
                LineFlags.None
                );

            // When in TextFormattingMode.Display the math processing performed by SimpleTextLine 
            // involves some rounding operations because of which the decision to collapse the text may 
            // not be unanimous amongst SimpleTextLine and FullTextLine. There are several watson 
            // crash reports that are testament to this theory. See Win8 PS bug# 643676. Hence we 
            // now allow the case where FullTextLine concludes that it doesnt need to collapse the 
            // text even though SimpleTextLine thought it should.
            
            if (textLine.HasOverflowed)
            {
                TextLine collapsedTextLine = textLine.Collapse(collapsingPropertiesList);
                if (collapsedTextLine != textLine)
                {
                    // if collapsed line is genuinely new,
                    // Dispose its maker as we no longer need it around, dispose it explicitly
                    // to reduce unnecessary finalization of this intermediate line.
                    textLine.Dispose();
                }
                return collapsedTextLine;
            }

            return textLine;
        }
Пример #4
0
        /// <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;
        }
Пример #5
0
        /// <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;
        }
Пример #6
0
        /// <summary> 
        /// Client to collapse the line to fit for display 
        /// </summary>
        /// <param name="collapsingPropertiesList">a list of collapsing properties</param> 
        public override TextLine Collapse(
            params TextCollapsingProperties[]   collapsingPropertiesList
            )
        { 
            if (!HasOverflowed)
                return this; 
 
            Invariant.Assert(_settings != null);
 
            // instantiate a collapsible full text line, collapse it and return the collapsed line
            TextMetrics.FullTextLine textLine = new TextMetrics.FullTextLine(
                _settings,
                _cpFirst, 
                0,  // lineLength
                TextFormatterImp.RealToIdeal(_paragraphWidth), 
                LineFlags.None 
                );
 
            Invariant.Assert(textLine.HasOverflowed);
            TextLine collapsedTextLine = textLine.Collapse(collapsingPropertiesList);
            if (collapsedTextLine != textLine)
            { 
                // if collapsed line is genuinely new,
                // Dispose its maker as we no longer need it around, dispose it explicitly 
                // to reduce unnecessary finalization of this intermediate line. 
                textLine.Dispose();
            } 
            return collapsedTextLine;
        }