示例#1
0
        // Token: 0x06006644 RID: 26180 RVA: 0x001CBE1C File Offset: 0x001CA01C
        protected TextCollapsingProperties GetCollapsingProps(double wrappingWidth, LineProperties paraProperties)
        {
            TextCollapsingProperties result;

            if (paraProperties.TextTrimming == TextTrimming.CharacterEllipsis)
            {
                result = new TextTrailingCharacterEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties);
            }
            else
            {
                result = new TextTrailingWordEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties);
            }
            return(result);
        }
示例#2
0
        // ------------------------------------------------------------------
        // Get collapsing properties.
        //
        //      wrappingWidth - wrapping width for collapsed line.
        //      paraProperties - paragraph properties.
        //
        // Returns: Line collapsing properties.
        // ------------------------------------------------------------------
        protected TextCollapsingProperties GetCollapsingProps(double wrappingWidth, LineProperties paraProperties)
        {
            Debug.Assert(paraProperties.TextTrimming != TextTrimming.None, "Text trimming must be enabled.");
            TextCollapsingProperties collapsingProps;

            if (paraProperties.TextTrimming == TextTrimming.CharacterEllipsis)
            {
                collapsingProps = new TextTrailingCharacterEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties);
            }
            else
            {
                collapsingProps = new TextTrailingWordEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties);
            }

            return(collapsingProps);
        }
示例#3
0
        // ------------------------------------------------------------------
        // Get collapsing properties.
        //
        //      wrappingWidth - wrapping width for collapsed line.
        //      paraProperties - paragraph properties.
        //
        // Returns: Line collapsing properties.
        // ------------------------------------------------------------------
        protected TextCollapsingProperties GetCollapsingProps(double wrappingWidth, LineProperties paraProperties)
        {
            Debug.Assert(paraProperties.TextTrimming != TextTrimming.None, "Text trimming must be enabled.");
            TextCollapsingProperties collapsingProps;
            if (paraProperties.TextTrimming == TextTrimming.CharacterEllipsis)
            {
                collapsingProps = new TextTrailingCharacterEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties);
            }
            else
            {
                collapsingProps = new TextTrailingWordEllipsis(wrappingWidth, paraProperties.DefaultTextRunProperties);
            }

            return collapsingProps;
        }
 // ------------------------------------------------------------------
 // Constructor.
 // ------------------------------------------------------------------
 internal FirstLineProperties(LineProperties lp)
 {
     _lp = lp;
     // properly set the local copy of hyphenator accordingly.
     Hyphenator = lp.Hyphenator;
 }
示例#5
0
        //-------------------------------------------------------------------
        //
        //  Internal Methods
        //
        //-------------------------------------------------------------------

        #region Internal Methods

        /// <summary>
        /// Create and format text line.
        /// </summary>
        /// <param name="dcp">First character position for the line.</param>
        /// <param name="formatWidth">Width to pass to LS formatter.</param>
        /// <param name="paragraphWidth">Line wrapping width.</param>
        /// <param name="lineProperties">Line's properties.</param>
        /// <param name="textRunCache">Run cache.</param>
        /// <param name="formatter">Text formatter.</param>
        /// <remarks>
        /// formatWidth/paragraphWidth is an attempt to work around bug 114719.
        /// Unfortunately, Line Services cannot guarantee that once a line
        /// has been measured, measuring the same content with the actual line
        /// width will produce the same line.
        /// 
        /// For example, suppose we format dcp 0 with paragraphWidth = 100.
        /// Suppose this results in a line from dcp 0 - 10, with width = 95.
        ///
        /// We would expect that a call to FormatLine with dcp = 0,
        /// paragraphWidth = 95 would result in the same 10 char line.
        /// But in practice it might return a 9 char line.
        /// 
        /// The workaround is to pass in an explicit formatting width across
        /// multiple calls, even if the paragraphWidth changes.
        /// </remarks>
        internal void Format(int dcp, double formatWidth, double paragraphWidth, LineProperties lineProperties, TextRunCache textRunCache, TextFormatter formatter)
        {
            _lineProperties = lineProperties;
            _dcp = dcp;
            _paragraphWidth = paragraphWidth;

            // We must ignore TextAlignment here since formatWidth does not
            // necessarilly equal paragraphWidth.  We'll adjust on later calls.
            lineProperties.IgnoreTextAlignment = (lineProperties.TextAlignment != TextAlignment.Justify);
            try
            {
                _line = formatter.FormatLine(this, dcp, formatWidth, lineProperties, null, textRunCache);
            }
            finally
            {
                lineProperties.IgnoreTextAlignment = false;
            }
        }
示例#6
0
        // Helper for IncrementalMeasureLinesAfterInsert, IncrementalMeasureLinesAfterDelete.
        // Formats line until we hit a synchronization point, a position where we know
        // following lines could not be affected by the change.
        private void SyncLineMetrics(DirtyTextRange range, double constraintWidth, LineProperties lineProperties, TextBoxLine line,
            bool endOfParagraph, int lineIndex, int lineOffset)
        {
            bool offsetSyncOk = (range.PositionsAdded == 0 || range.PositionsRemoved == 0);
            int lastCoveredCharOffset = range.StartIndex + Math.Max(range.PositionsAdded, range.PositionsRemoved);

            // Keep updating lines until we find a synchronized position.
            while (!endOfParagraph &&
                   (lineIndex == _lineMetrics.Count ||
                    !offsetSyncOk ||
                    lineOffset != _lineMetrics[lineIndex].Offset))
            {
                if (lineIndex < _lineMetrics.Count &&
                    lineOffset >= _lineMetrics[lineIndex].EndOffset)
                {
                    // If the current line offset starts past the current line metric offset,
                    // remove the metric.  This happens when the previous line
                    // frees up enough space to completely consume the following line.
                    // We can't simply replace the record without potentially missing our
                    // [....] position.
                    _lineMetrics.RemoveAt(lineIndex); // 
                    RemoveLineVisualRange(lineIndex, 1);
                }
                else
                {
                    using (line)
                    {
                        line.Format(lineOffset, constraintWidth, constraintWidth, lineProperties, _cache.TextRunCache, _cache.TextFormatter);

                        LineRecord record = new LineRecord(lineOffset, line);

                        if (lineIndex == _lineMetrics.Count ||
                            lineOffset + line.Length <= _lineMetrics[lineIndex].Offset)
                        {
                            // The new line preceeds the old line, insert a new record.

                            // 
                            _lineMetrics.Insert(lineIndex, record);
                            AddLineVisualPlaceholder(lineIndex);
                        }
                        else
                        {
                            // We expect to be colliding with the old line directly.
                            // If we extend past it, we're in danger of needlessly
                            // re-formatting the entire doc (ie, we miss the real
                            // [....] position and don't stop until EndOfParagraph).
                            Invariant.Assert(lineOffset < _lineMetrics[lineIndex].EndOffset);

                            _lineMetrics[lineIndex] = record;
                            ClearLineVisual(lineIndex);

                            // If this line ends past the invalidated region, and it
                            // has a hard line break, it's safe to synchronize on the next
                            // line metric with a matching start offset.
                            offsetSyncOk |= lastCoveredCharOffset <= record.EndOffset && line.HasLineBreak;
                        }

                        lineIndex++;
                        lineOffset += line.Length;
                        endOfParagraph = line.EndOfParagraph;
                    }
                }
            }

            // Remove any trailing lines that got absorbed into the new last line.
            if (endOfParagraph && lineIndex < _lineMetrics.Count)
            {
                int count = _lineMetrics.Count - lineIndex;
                _lineMetrics.RemoveRange(lineIndex, count);
                RemoveLineVisualRange(lineIndex, count);
            }
        }
 // ------------------------------------------------------------------
 // Constructor.
 // ------------------------------------------------------------------
 internal FirstLineProperties(LineProperties lp)
 {
     _lp = lp;
     // properly set the local copy of hyphenator accordingly.
     Hyphenator = lp.Hyphenator;
 }
示例#8
0
 //-------------------------------------------------------------------
 // Calculate line advance distance. This functionality will go away
 // when TextFormatter will be able to handle line height/stacking.
 //
 //      lineHeight - calculated line height
 //
 // Returns: Line advance distance..
 //-------------------------------------------------------------------
 private double CalcLineAdvance(double lineHeight, LineProperties lineProperties)
 {
     return lineProperties.CalcLineAdvance(lineHeight);
 }
示例#9
0
 //-------------------------------------------------------------------
 // Get line properties
 //
 //      firstLine - is it for the first line?
 //
 // Returns: Line properties for first/following lines.
 //-------------------------------------------------------------------
 private TextParagraphProperties GetLineProperties(bool firstLine, LineProperties lineProperties)
 {
     return GetLineProperties(firstLine, false, lineProperties);
 }
示例#10
0
        // Measures content invalidated due to a TextContainer change (rather than
        // a constraint change).
        //
        // Returns the full content size, omitting any unanalyzed content
        // at the document end (due to pending background layout).
        private Size IncrementalMeasure(double constraintWidth, LineProperties lineProperties)
        {
            Invariant.Assert(_dirtyList != null);
            Invariant.Assert(_dirtyList.Length > 0); // We only allocate _dirtyList when it has content.

            Size desiredSize = _contentSize;
            DirtyTextRange range = _dirtyList[0];

            // Background layout may be running, in which case we need to
            // "clip" the scope of this incremental edit.  We want to ignore
            // changes that extend past the area of the document we're already
            // tracking.
            if (range.StartIndex > _lineMetrics[_lineMetrics.Count - 1].EndOffset)
            {
                Invariant.Assert(this.IsBackgroundLayoutPending);
                return desiredSize;
            }

            // Merge the dirty list into a single superset DirtyTextRange.
            // 




            int previousOffset = range.StartIndex;
            int positionsAdded = range.PositionsAdded;
            int positionsRemoved = range.PositionsRemoved;

            for (int i = 1; i < _dirtyList.Length; i++)
            {
                range = _dirtyList[i];

                if (range.StartIndex > _lineMetrics[_lineMetrics.Count - 1].EndOffset)
                {
                    Invariant.Assert(this.IsBackgroundLayoutPending);
                    break;
                }

                int rangeDistance = range.StartIndex - previousOffset;
                positionsAdded += rangeDistance + range.PositionsAdded;
                positionsRemoved += rangeDistance + range.PositionsRemoved;

                previousOffset = range.StartIndex;
            }

            range = new DirtyTextRange(_dirtyList[0].StartIndex, positionsAdded, positionsRemoved);

            if (range.PositionsAdded >= range.PositionsRemoved)
            {
                IncrementalMeasureLinesAfterInsert(constraintWidth, lineProperties, range, ref desiredSize);
            }
            else if (range.PositionsAdded < range.PositionsRemoved)
            {
                IncrementalMeasureLinesAfterDelete(constraintWidth, lineProperties, range, ref desiredSize);
            }

            return desiredSize;
        }
示例#11
0
        // Performs one iteration of background measure.
        // Background measure always works at the end of the current
        // line metrics array -- invalidations to prevoiusly examined
        // content is handled by incremental layout, synchronously.
        //
        // Returns the full content size, omitting any unanalyzed content
        // at the document end.
        private Size FullMeasureTick(double constraintWidth, LineProperties lineProperties)
        {
            Size desiredSize;
            TextBoxLine line = new TextBoxLine(this);
            int lineOffset;
            bool endOfParagraph;

            // Find the next position for this iteration.

            if (_lineMetrics.Count == 0)
            {
                desiredSize = new Size();
                lineOffset = 0;
            }
            else
            {
                desiredSize = _contentSize;
                lineOffset = _lineMetrics[_lineMetrics.Count - 1].EndOffset;
            }

            // Calculate a stop time.
            // We limit work to just a few milliseconds per iteration
            // to avoid blocking the thread.
            DateTime stopTime;

            if ((ScrollBarVisibility)((Control)_host).GetValue(ScrollViewer.VerticalScrollBarVisibilityProperty) == ScrollBarVisibility.Auto)
            {
                // Workaround for bug 1766924.
                // When VerticalScrollBarVisiblity == Auto, there's a problem with
                // our interaction with ScrollViewer.  Disable background layout to
                // mitigate the problem until we can take a real fix in v.next.
                // 
                stopTime = DateTime.MaxValue;
            }
            else
            {
                stopTime = DateTime.Now.AddMilliseconds(_maxMeasureTimeMs);
            }

            // Format lines until we hit the end of document or run out of time.

            do
            {
                using (line)
                {
                    line.Format(lineOffset, constraintWidth, constraintWidth, lineProperties, _cache.TextRunCache, _cache.TextFormatter);

                    // This is a loop invariant, but has negligable cost.
                    // 
                    _lineHeight = lineProperties.CalcLineAdvance(line.Height);

                    _lineMetrics.Add(new LineRecord(lineOffset, line));

                    // Desired width is always max of calculated line widths. 
                    // Desired height is sum of all line heights.
                    desiredSize.Width = Math.Max(desiredSize.Width, line.Width);
                    desiredSize.Height += _lineHeight;

                    lineOffset += line.Length;
                    endOfParagraph = line.EndOfParagraph;
                }
            }
            while (!endOfParagraph && DateTime.Now < stopTime);

            if (!endOfParagraph)
            {
                // Ran out of time.  Defer to background layout.
                SetFlags(true, Flags.BackgroundLayoutPending);
                this.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(OnBackgroundMeasure), null);
            }
            else
            {
                // Finished the entire document.  Stop background layout.
                SetFlags(false, Flags.BackgroundLayoutPending);
            }

            return desiredSize;
        }
示例#12
0
        // Returns a formatted TextBoxLine at the specified index.
        // Caller must Dispose the TextBoxLine.
        // This method is expensive.
        private TextBoxLine GetFormattedLine(int lineIndex, out LineProperties lineProperties)
        {
            TextBoxLine line = new TextBoxLine(this);
            LineRecord metrics = _lineMetrics[lineIndex];
            lineProperties = GetLineProperties();

            Control hostControl = (Control)_host;
            TextFormattingMode textFormattingMode = TextOptions.GetTextFormattingMode(hostControl);
            TextFormatter formatter = TextFormatter.FromCurrentDispatcher(textFormattingMode);

            double width = GetWrappingWidth(this.RenderSize.Width);
            double formatWidth = GetWrappingWidth(_previousConstraint.Width);

            line.Format(metrics.Offset, formatWidth, width, lineProperties, new TextRunCache(), formatter);
            Invariant.Assert(metrics.Length == line.Length, "Line is out of [....] with metrics!");

            return line;
        }
示例#13
0
        internal override void ValidateVisual(PTS.FSKUPDATE fskupdInherited)
        {
            // Query paragraph details 
            PTS.FSSUBTRACKDETAILS subtrackDetails;
            PTS.Validate(PTS.FsQuerySubtrackDetails(PtsContext.Context, _paraHandle.Value, out subtrackDetails)); 
 
            // Draw border and background info.
            MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element); 
            if (ThisFlowDirection != PageFlowDirection)
            {
                mbp.MirrorBP();
            } 

            uint fswdir = PTS.FlowDirectionToFswdir((FlowDirection)Paragraph.Element.GetValue(FrameworkElement.FlowDirectionProperty)); 
 
            Brush backgroundBrush = (Brush)Paragraph.Element.GetValue(TextElement.BackgroundProperty);
 
            TextProperties textProperties = new TextProperties(Paragraph.Element, StaticTextPointer.Null, false /* inline objects */, false /* get background */);

            // There might be possibility to get empty sub-track, skip the sub-track in such case.
            if (subtrackDetails.cParas != 0) 
            {
                PTS.FSPARADESCRIPTION [] arrayParaDesc; 
                PtsHelper.ParaListFromSubtrack(PtsContext, _paraHandle.Value, ref subtrackDetails, out arrayParaDesc); 

                using(DrawingContext ctx = _visual.RenderOpen()) 
                {
                    _visual.DrawBackgroundAndBorderIntoContext(ctx, backgroundBrush, mbp.BorderBrush, mbp.Border, _rect.FromTextDpi(), IsFirstChunk, IsLastChunk);

                        // Get list of paragraphs 
                    ListMarkerLine listMarkerLine = new ListMarkerLine(Paragraph.StructuralCache.TextFormatterHost, this);
                    int indexFirstParaInSubtrack = 0; 
 
                    for(int index = 0; index < subtrackDetails.cParas; index++)
                    { 
                        List list = Paragraph.Element as List;

                        BaseParaClient listItemParaClient = PtsContext.HandleToObject(arrayParaDesc[index].pfsparaclient) as BaseParaClient;
                        PTS.ValidateHandle(listItemParaClient); 

                        if(index == 0) 
                        { 
                            indexFirstParaInSubtrack = list.GetListItemIndex(listItemParaClient.Paragraph.Element as ListItem);
                        } 

                        if(listItemParaClient.IsFirstChunk)
                        {
                            int dvBaseline = listItemParaClient.GetFirstTextLineBaseline(); 

                            if(PageFlowDirection != ThisFlowDirection) 
                            { 
                                ctx.PushTransform(new MatrixTransform(-1.0, 0.0, 0.0, 1.0, TextDpi.FromTextDpi(2 * listItemParaClient.Rect.u + listItemParaClient.Rect.du), 0.0));
                            } 

                            int adjustedIndex;
                            if (int.MaxValue - index < indexFirstParaInSubtrack)
                            { 
                                adjustedIndex = int.MaxValue;
                            } 
                            else 
                            {
                                adjustedIndex = indexFirstParaInSubtrack + index; 
                            }
                            LineProperties lineProps = new LineProperties(Paragraph.Element, Paragraph.StructuralCache.FormattingOwner, textProperties, new MarkerProperties(list, adjustedIndex));
                            listMarkerLine.FormatAndDrawVisual(ctx, lineProps, listItemParaClient.Rect.u, dvBaseline);
 
                            if(PageFlowDirection != ThisFlowDirection)
                            { 
                                ctx.Pop(); 
                            }
                        } 
                    }


                    listMarkerLine.Dispose(); 
                }
 
                // Render list of paragraphs 
                PtsHelper.UpdateParaListVisuals(PtsContext, _visual.Children, fskupdInherited, arrayParaDesc);
            } 
            else
            {
                _visual.Children.Clear();
            } 

        } 
示例#14
0
        /// <summary>
        /// Create and format text line. 
        /// </summary>
        /// <param name="ctx"> 
        /// DrawingContext for text line. 
        /// </param>
        /// <param name="lineProps"> 
        /// LineProperties of text line
        /// </param>
        /// <param name="ur">
        /// Horizontal draw location 
        /// </param>
        /// <param name="vrBaseline"> 
        /// Vertical baseline draw location 
        /// </param>
        internal void FormatAndDrawVisual(DrawingContext ctx, LineProperties lineProps, int ur, int vrBaseline) 
        {
            System.Windows.Media.TextFormatting.TextLine line;
            bool mirror = (lineProps.FlowDirection == FlowDirection.RightToLeft);
 
            _host.Context = this;
 
            try 
            {
                // Create line object 
                line = _host.TextFormatter.FormatLine(_host, 0, 0, lineProps.FirstLineProps, null, new TextRunCache());

                Point drawLocation = new Point(TextDpi.FromTextDpi(ur), TextDpi.FromTextDpi(vrBaseline) - line.Baseline);
 
                line.Draw(ctx, drawLocation, (mirror ? InvertAxes.Horizontal : InvertAxes.None));
                line.Dispose(); 
            } 
            finally
            { 
                // clear the context
                _host.Context = null;
            }
        } 
示例#15
0
 // ------------------------------------------------------------------
 // Create appropriate line object.
 // a) SimpleLine, if the content is represented by a string.
 // b) ComplexLine, if the content is represented by a TextContainer.
 // ------------------------------------------------------------------
 private Line CreateLine(LineProperties lineProperties)
 {
     Line line;
     if (_complexContent == null)
         line = new SimpleLine(this, Text, lineProperties.DefaultTextRunProperties);
     else
         line = new ComplexLine(this);
     return line;
 }
示例#16
0
        // ------------------------------------------------------------------
        // Refetch and cache line properties, if needed.
        // ------------------------------------------------------------------
        private LineProperties GetLineProperties()
        {
            // For default text properties always set background to null.
            // REASON: If element associated with the text run is TextBlock element, ignore background
            //         brush, because it is handled outside as FrameworkElement's background.

            TextProperties defaultTextProperties = new TextProperties(this, this.IsTypographyDefaultValue);

            // Do not allow hyphenation for plain Text so always pass null for IHyphenate.
            // Pass page width and height as double.MaxValue when creating LineProperties, since TextBlock does not restrict
            // TextIndent or LineHeight
            LineProperties lineProperties = new LineProperties(this, this, defaultTextProperties, null);

            bool isHyphenationEnabled = (bool) this.GetValue(IsHyphenationEnabledProperty);
            if(isHyphenationEnabled)
            {
                lineProperties.Hyphenator = EnsureHyphenator();
            }


            return lineProperties;

        }
示例#17
0
        // Measures content invalidated due to a TextContainer change.
        private void IncrementalMeasureLinesAfterInsert(double constraintWidth, LineProperties lineProperties, DirtyTextRange range, ref Size desiredSize)
        {
            int delta = range.PositionsAdded - range.PositionsRemoved;
            Invariant.Assert(delta >= 0);
            
            int lineIndex = GetLineIndexFromOffset(range.StartIndex, LogicalDirection.Forward);

            if (delta > 0)
            {
                // Increment of the offsets of all following lines.
                // 
                for (int i = lineIndex + 1; i < _lineMetrics.Count; i++)
                {
                    _lineMetrics[i].Offset += delta;
                }
            }

            TextBoxLine line = new TextBoxLine(this);
            int lineOffset;
            bool endOfParagraph = false;

            // We need to re-format the previous line, because if someone inserted
            // a hard break, the first directly affected line might now be shorter
            // and mergeable with its predecessor.
            if (lineIndex > 0) // 
            {
                FormatFirstIncrementalLine(lineIndex - 1, constraintWidth, lineProperties, line, out lineOffset, out endOfParagraph);
            }
            else
            {
                lineOffset = _lineMetrics[lineIndex].Offset;
            }

            // Format the line directly affected by the change.
            // If endOfParagraph == true, then the line was absorbed into its
            // predessor (because its new content is thinner, or because the
            // TextWrapping property changed).
            if (!endOfParagraph)
            {
                using (line)
                {
                    line.Format(lineOffset, constraintWidth, constraintWidth, lineProperties, _cache.TextRunCache, _cache.TextFormatter);

                    _lineMetrics[lineIndex] = new LineRecord(lineOffset, line);

                    lineOffset += line.Length;
                    endOfParagraph = line.EndOfParagraph;
                }
                ClearLineVisual(lineIndex);
                lineIndex++;
            }

            // Recalc the following lines not directly affected as needed.
            SyncLineMetrics(range, constraintWidth, lineProperties, line, endOfParagraph, lineIndex, lineOffset);

            desiredSize = BruteForceCalculateDesiredSize();
        }
示例#18
0
 private TextParagraphProperties GetLineProperties(bool firstLine, bool showParagraphEllipsis, LineProperties lineProperties)
 {
     GetLineProperties();
     firstLine = firstLine && lineProperties.HasFirstLineProperties;
     if (!showParagraphEllipsis)
     {
         return firstLine ? lineProperties.FirstLineProps : lineProperties;
     }
     else
     {
         return lineProperties.GetParaEllipsisLineProps(firstLine);
     }
 }
示例#19
0
        // Measures content invalidated due to a TextContainer change.
        private void IncrementalMeasureLinesAfterDelete(double constraintWidth, LineProperties lineProperties, DirtyTextRange range, ref Size desiredSize)
        {
            int delta = range.PositionsAdded - range.PositionsRemoved;
            Invariant.Assert(delta < 0);

            int firstLineIndex = GetLineIndexFromOffset(range.StartIndex);

            // Clip the scope of the affected lines to the region of the document
            // we've already inspected.  Clipping happens when background layout
            // has not yet completed but an incremental update happens.
            int endOffset = range.StartIndex + -delta - 1;
            if (endOffset > _lineMetrics[_lineMetrics.Count - 1].EndOffset)
            {
                Invariant.Assert(this.IsBackgroundLayoutPending);
                endOffset = _lineMetrics[_lineMetrics.Count - 1].EndOffset;
                if (range.StartIndex == endOffset)
                {
                    // Nothing left to do until background layout runs.
                    return;
                }
            }

            int lastLineIndex = GetLineIndexFromOffset(endOffset);

            // Increment the offsets of all following lines.
            // 
            for (int i = lastLineIndex + 1; i < _lineMetrics.Count; i++)
            {
                _lineMetrics[i].Offset += delta;
            }

            TextBoxLine line = new TextBoxLine(this);
            int lineIndex = firstLineIndex;
            int lineOffset;
            bool endOfParagraph;

            // We need to re-format the previous line, because if someone inserted
            // a hard break, the first directly affected line might now be shorter
            // and mergeable with its predecessor.
            if (lineIndex > 0) // 
            {
                FormatFirstIncrementalLine(lineIndex - 1, constraintWidth, lineProperties, line, out lineOffset, out endOfParagraph);
            }
            else
            {
                lineOffset = _lineMetrics[lineIndex].Offset;
                endOfParagraph = false;
            }

            // 



            // Update the first affected line.  If it's completely covered, remove it entirely below.
            if (!endOfParagraph &&
                (range.StartIndex > lineOffset || range.StartIndex + -delta < _lineMetrics[lineIndex].EndOffset))
            {
                // Only part of the line is covered, reformat it.
                using (line)
                {
                    line.Format(lineOffset, constraintWidth, constraintWidth, lineProperties, _cache.TextRunCache, _cache.TextFormatter);

                    _lineMetrics[lineIndex] = new LineRecord(lineOffset, line);

                    lineOffset += line.Length;
                    endOfParagraph = line.EndOfParagraph;
                }
                ClearLineVisual(lineIndex);
                lineIndex++;
            }

            // Remove all the following lines that are completely covered.
            // 
            _lineMetrics.RemoveRange(lineIndex, lastLineIndex - lineIndex + 1);
            RemoveLineVisualRange(lineIndex, lastLineIndex - lineIndex + 1);

            // Recalc the following lines not directly affected as needed.
            SyncLineMetrics(range, constraintWidth, lineProperties, line, endOfParagraph, lineIndex, lineOffset);

            desiredSize = BruteForceCalculateDesiredSize();
        }
示例#20
0
        // Helper for IncrementalMeasureLinesAfterInsert, IncrementalMeasureLinesAfterDelete.
        // Formats the line preceding the first directly affected line after a TextContainer change.
        // In general this line might grow as content in the following line is absorbed.
        private void FormatFirstIncrementalLine(int lineIndex, double constraintWidth, LineProperties lineProperties, TextBoxLine line,
            out int lineOffset, out bool endOfParagraph)
        {
            int originalEndOffset = _lineMetrics[lineIndex].EndOffset;
            lineOffset = _lineMetrics[lineIndex].Offset;

            using (line)
            {
                line.Format(lineOffset, constraintWidth, constraintWidth, lineProperties, _cache.TextRunCache, _cache.TextFormatter);

                _lineMetrics[lineIndex] = new LineRecord(lineOffset, line);

                lineOffset += line.Length;
                endOfParagraph = line.EndOfParagraph;
            }

            // Don't clear the cached Visual unless something changed.
            if (originalEndOffset != _lineMetrics[lineIndex].EndOffset)
            {
                ClearLineVisual(lineIndex);
            }
        }
 // Token: 0x06008A92 RID: 35474 RVA: 0x00257536 File Offset: 0x00255736
 internal FirstLineProperties(LineProperties lp)
 {
     this._lp        = lp;
     this.Hyphenator = lp.Hyphenator;
 }