// Token: 0x06006720 RID: 26400 RVA: 0x001CD9EC File Offset: 0x001CBBEC
 internal void UpdateBackgroundFormatInfo()
 {
     this._cpInterrupted               = -1;
     this._lastCPUninterruptible       = 0;
     this._doesFinalDTRCoverRestOfText = false;
     this._cchAllText = this._structuralCache.TextContainer.SymbolCount;
     if (this._structuralCache.DtrList != null)
     {
         int num = 0;
         for (int i = 0; i < this._structuralCache.DtrList.Length - 1; i++)
         {
             num += this._structuralCache.DtrList[i].PositionsAdded - this._structuralCache.DtrList[i].PositionsRemoved;
         }
         DirtyTextRange dirtyTextRange = this._structuralCache.DtrList[this._structuralCache.DtrList.Length - 1];
         if (dirtyTextRange.StartIndex + num + dirtyTextRange.PositionsAdded >= this._cchAllText)
         {
             this._doesFinalDTRCoverRestOfText = true;
             this._lastCPUninterruptible       = dirtyTextRange.StartIndex + num;
         }
     }
     else
     {
         this._doesFinalDTRCoverRestOfText = true;
     }
     this._backgroundFormatStopTime = DateTime.UtcNow.AddMilliseconds(200.0);
 }
예제 #2
0
        // ------------------------------------------------------------------
        // Merge DRT at position 'index' with the next one, if possible.
        //
        //      index - Index of the DTR to be merged with next one.
        // ------------------------------------------------------------------
        private void MergeWithNext(int index)
        {
            while (index + 1 < _count)
            {
                DirtyTextRange dtrNext = _dtrs[index + 1];

                // DTR starts in the range of the previous DTR. In this case
                // merge these 2 DTRs.
                if (dtrNext.StartIndex <= _dtrs[index].StartIndex + _dtrs[index].PositionsRemoved)
                {
                    //_dtrs[index].dcp: no need to change it
                    _dtrs[index].PositionsAdded   += dtrNext.PositionsAdded;
                    _dtrs[index].PositionsRemoved += dtrNext.PositionsRemoved;

                    // Remove merged entry
                    for (int i = index + 2; i < _count; i++)
                    {
                        _dtrs[i - 1] = _dtrs[i];
                    }

                    --_count;
                }
                else
                {
                    break;
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Merges the DtrList into a single DirtyTextRange containing all
        /// ranges in the list.
        /// </summary>
        /// <returns>A DirtyTextRange containing all ranges in this list</returns>
        internal DirtyTextRange GetMergedRange()
        {
            if (_count > 0)
            {
                DirtyTextRange range = _dtrs[0];

                int  previousOffset     = range.StartIndex;
                int  positionsAdded     = range.PositionsAdded;
                int  positionsRemoved   = range.PositionsRemoved;
                bool fromHighlightLayer = range.FromHighlightLayer;

                for (int i = 1; i < _count; i++)
                {
                    range = _dtrs[i];

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

                    // Prefer not from highlight layer when squashing
                    fromHighlightLayer &= range.FromHighlightLayer;

                    previousOffset = range.StartIndex;
                }

                return(new DirtyTextRange(_dtrs[0].StartIndex, positionsAdded, positionsRemoved, fromHighlightLayer));
            }

            return(new DirtyTextRange(0, 0, 0, false));
        }
예제 #4
0
        //-------------------------------------------------------------------
        //
        //  Internal Methods
        //
        //-------------------------------------------------------------------

        #region Internal Methods

        /// <summary>
        /// Updates background layout information from a structuralCache
        /// </summary>
        internal void UpdateBackgroundFormatInfo()
        {
            _cpInterrupted               = -1;
            _lastCPUninterruptible       = 0;
            _doesFinalDTRCoverRestOfText = false;

            _cchAllText = _structuralCache.TextContainer.SymbolCount;

            if (_structuralCache.DtrList != null)
            {
                int positionsAdded = 0;

                // Sum for all dtrs but the last
                for (int dtrIndex = 0; dtrIndex < _structuralCache.DtrList.Length - 1; dtrIndex++)
                {
                    positionsAdded += _structuralCache.DtrList[dtrIndex].PositionsAdded - _structuralCache.DtrList[dtrIndex].PositionsRemoved;
                }

                DirtyTextRange dtrLast = _structuralCache.DtrList[_structuralCache.DtrList.Length - 1];

                if ((dtrLast.StartIndex + positionsAdded + dtrLast.PositionsAdded) >= _cchAllText)
                {
                    _doesFinalDTRCoverRestOfText = true;
                    _lastCPUninterruptible       = dtrLast.StartIndex + positionsAdded;
                }
            }
            else
            {
                _doesFinalDTRCoverRestOfText = true;
            }

            // And set a good stop time for formatting
            _backgroundFormatStopTime = DateTime.UtcNow.AddMilliseconds(_stopTimeDelta);
        }
예제 #5
0
        // ------------------------------------------------------------------
        // Table has been structurally altered
        // ------------------------------------------------------------------
        private void TableStructureChanged(object sender, EventArgs e)
        {
            // Disconnect obsolete paragraphs.
            BaseParagraph paraInvalid = _firstChild;

            while (paraInvalid != null)
            {
                paraInvalid.Dispose();
                paraInvalid = paraInvalid.Next;
            }
            _firstChild = null;

            //
            // Since whole table content is disposed, we need
            // - to create dirty text range corresponding to the Table content
            // - notify formatter that Table's content is changed.
            //
            int charCount = Table.SymbolCount - 2;// This is equivalent to (ContentEndOffset – ContentStartOffset) but is more performant.

            if (charCount > 0)
            {
                DirtyTextRange dtr = new DirtyTextRange(Table.ContentStartOffset, charCount, charCount);
                StructuralCache.AddDirtyTextRange(dtr);
            }
            if (StructuralCache.FormattingOwner.Formatter != null)
            {
                StructuralCache.FormattingOwner.Formatter.OnContentInvalidated(true, Table.ContentStart, Table.ContentEnd);
            }
        }
예제 #6
0
 // ------------------------------------------------------------------
 // Constructor
 // ------------------------------------------------------------------
 internal UpdateRecord()
 {
     Dtr = new DirtyTextRange(0,0,0);
     FirstPara = SyncPara = null;
     ChangeType = PTS.FSKCHANGE.fskchNone;
     Next = null;
     InProcessing = false;
 }
예제 #7
0
 /// <summary>
 /// Add new DirtyTextRange.
 /// </summary>
 /// <param name="dtr">New DTR being added.</param>
 internal void AddDirtyTextRange(DirtyTextRange dtr)
 {
     if (_dtrs == null)
     {
         _dtrs = new DtrList();
     }
     _dtrs.Merge(dtr);
 }
예제 #8
0
 // ------------------------------------------------------------------
 // Constructor
 // ------------------------------------------------------------------
 internal UpdateRecord()
 {
     Dtr          = new DirtyTextRange(0, 0, 0);
     FirstPara    = SyncPara = null;
     ChangeType   = PTS.FSKCHANGE.fskchNone;
     Next         = null;
     InProcessing = false;
 }
예제 #9
0
        // ------------------------------------------------------------------
        // Retrieve list of dtrs from range.
        //
        //      dcpNew - Distance from the beginning of TextContainer after all
        //              tree changes.
        //      cchOld - Number of characters in the range, but before any
        //              tree changes.
        //
        // Returns: List of DRTs for specified range.
        // ------------------------------------------------------------------
        internal DtrList DtrsFromRange(int dcpNew, int cchOld)
        {
            DtrList dtrs = null;
            int     i = 0;
            int     first, last;
            int     positionsAdded = 0;

            // Find the first dtr intersecting with the specified range.
            // Since DTRs store dcp before any changes, during iteration
            // accumulate positionsAdded (number of characters added to the tree
            // up to the current point).
            while (i < _count)
            {
                if (dcpNew <= _dtrs[i].StartIndex + positionsAdded + _dtrs[i].PositionsAdded)
                {
                    break;
                }
                positionsAdded += _dtrs[i].PositionsAdded - _dtrs[i].PositionsRemoved;
                ++i;
            }
            first = i;

            // Find the last dtr intersecting with the specified range.
            // dcpNew-positionsAdded points to position before any tree changes, from
            // where we start counting cchOld.
            // Do not add characters (positionsAdded), since start position has been already found.
            while (i < _count)
            {
                if (dcpNew - positionsAdded + cchOld <= _dtrs[i].StartIndex + _dtrs[i].PositionsRemoved)
                {
                    // If there is no intersection with the current DTR, go to the previous one.
                    if (dcpNew - positionsAdded + cchOld < _dtrs[i].StartIndex)
                    {
                        --i;
                    }
                    break;
                }
                ++i;
            }
            last = (i < _count) ? i : _count - 1;

            // If there are DTRs in the specified range, create new DtrList object
            if (last >= first)
            {
                dtrs = new DtrList();
                while (last >= first)
                {
                    // Since dcpNew is after tree changes, add positionsAdded to all dtrs
                    // to build dtr list relative to dcpNew position.
                    DirtyTextRange dtr = _dtrs[first];
                    dtr.StartIndex += positionsAdded;
                    dtrs.Append(dtr);
                    ++first;
                }
            }
            return(dtrs);
        }
예제 #10
0
 // ------------------------------------------------------------------
 // Append new DTR to the list.
 //
 //      dtr - DTR to be appended to the list.
 // ------------------------------------------------------------------
 private void Append(DirtyTextRange dtr)
 {
     if (_count == _dtrs.Length)
     {
         Resize();
     }
     _dtrs[_count] = dtr;
     ++_count;
 }
예제 #11
0
 // Token: 0x060067B6 RID: 26550 RVA: 0x001D1476 File Offset: 0x001CF676
 private void Append(DirtyTextRange dtr)
 {
     if (this._count == this._dtrs.Length)
     {
         this.Resize();
     }
     this._dtrs[this._count] = dtr;
     this._count++;
 }
예제 #12
0
        // ------------------------------------------------------------------
        // Increases the capacity of the DTR array.
        // <new size> = <current size>*2.
        // ------------------------------------------------------------------
        private void Resize()
        {
            Debug.Assert(_dtrs.Length > 0);

            // Allocate new array and copy all existing entries into it
            DirtyTextRange [] newdtrs = new DirtyTextRange[_dtrs.Length * 2];
            Array.Copy(_dtrs, newdtrs, _dtrs.Length);
            _dtrs = newdtrs;
        }
예제 #13
0
        // Token: 0x060069F2 RID: 27122 RVA: 0x001E20F4 File Offset: 0x001E02F4
        private void DeferFormattingToBackground()
        {
            int            cpinterrupted = this._section.StructuralCache.BackgroundFormatInfo.CPInterrupted;
            int            cchAllText    = this._section.StructuralCache.BackgroundFormatInfo.CchAllText;
            DirtyTextRange dtr           = new DirtyTextRange(cpinterrupted, cchAllText - cpinterrupted, cchAllText - cpinterrupted, false);

            this._section.StructuralCache.AddDirtyTextRange(dtr);
            this._backgroundFormatOperation = Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, PtsPage.BackgroundUpdateCallback, this);
        }
예제 #14
0
        // Token: 0x060067B4 RID: 26548 RVA: 0x001D1260 File Offset: 0x001CF460
        internal DtrList DtrsFromRange(int dcpNew, int cchOld)
        {
            DtrList dtrList = null;
            int     i       = 0;
            int     num     = 0;

            while (i < this._count && dcpNew > this._dtrs[i].StartIndex + num + this._dtrs[i].PositionsAdded)
            {
                num += this._dtrs[i].PositionsAdded - this._dtrs[i].PositionsRemoved;
                i++;
            }
            int num2 = i;

            while (i < this._count)
            {
                if (dcpNew - num + cchOld <= this._dtrs[i].StartIndex + this._dtrs[i].PositionsRemoved)
                {
                    if (dcpNew - num + cchOld < this._dtrs[i].StartIndex)
                    {
                        i--;
                        break;
                    }
                    break;
                }
                else
                {
                    i++;
                }
            }
            int j = (i < this._count) ? i : (this._count - 1);

            if (j >= num2)
            {
                dtrList = new DtrList();
                while (j >= num2)
                {
                    DirtyTextRange dtr = this._dtrs[num2];
                    dtr.StartIndex += num;
                    dtrList.Append(dtr);
                    num2++;
                }
            }
            return(dtrList);
        }
        // Token: 0x06006ADC RID: 27356 RVA: 0x001E94F0 File Offset: 0x001E76F0
        private void TableStructureChanged(object sender, EventArgs e)
        {
            for (BaseParagraph baseParagraph = this._firstChild; baseParagraph != null; baseParagraph = baseParagraph.Next)
            {
                baseParagraph.Dispose();
            }
            this._firstChild = null;
            int num = this.Table.SymbolCount - 2;

            if (num > 0)
            {
                DirtyTextRange dtr = new DirtyTextRange(this.Table.ContentStartOffset, num, num, false);
                base.StructuralCache.AddDirtyTextRange(dtr);
            }
            if (base.StructuralCache.FormattingOwner.Formatter != null)
            {
                base.StructuralCache.FormattingOwner.Formatter.OnContentInvalidated(true, this.Table.ContentStart, this.Table.ContentEnd);
            }
        }
        // Token: 0x060067A6 RID: 26534 RVA: 0x001D0CB8 File Offset: 0x001CEEB8
        private UpdateRecord UpdateRecordFromDtr(DtrList dtrs, DirtyTextRange dtr, int dcpContent)
        {
            UpdateRecord updateRecord = new UpdateRecord();

            updateRecord.Dtr = dtr;
            BaseParagraph baseParagraph = this._firstChild;
            int           num           = dcpContent;

            if (num < updateRecord.Dtr.StartIndex)
            {
                while (baseParagraph != null && num + baseParagraph.LastFormatCch <= updateRecord.Dtr.StartIndex && (num + baseParagraph.LastFormatCch != updateRecord.Dtr.StartIndex || !(baseParagraph is TextParagraph)))
                {
                    num          += baseParagraph.LastFormatCch;
                    baseParagraph = baseParagraph.Next;
                }
            }
            updateRecord.FirstPara = baseParagraph;
            if (baseParagraph == null)
            {
                updateRecord.ChangeType = PTS.FSKCHANGE.fskchNew;
            }
            else if (num < updateRecord.Dtr.StartIndex)
            {
                updateRecord.ChangeType = PTS.FSKCHANGE.fskchInside;
            }
            else
            {
                updateRecord.ChangeType = PTS.FSKCHANGE.fskchNew;
            }
            updateRecord.SyncPara = null;
            while (baseParagraph != null)
            {
                if (num + baseParagraph.LastFormatCch > updateRecord.Dtr.StartIndex + updateRecord.Dtr.PositionsRemoved || (num + baseParagraph.LastFormatCch == updateRecord.Dtr.StartIndex + updateRecord.Dtr.PositionsRemoved && updateRecord.ChangeType != PTS.FSKCHANGE.fskchNew))
                {
                    updateRecord.SyncPara = baseParagraph.Next;
                    break;
                }
                num          += baseParagraph.LastFormatCch;
                baseParagraph = baseParagraph.Next;
            }
            return(updateRecord);
        }
예제 #17
0
 // Token: 0x060067B3 RID: 26547 RVA: 0x001D119C File Offset: 0x001CF39C
 internal DirtyTextRange GetMergedRange()
 {
     if (this._count > 0)
     {
         DirtyTextRange dirtyTextRange   = this._dtrs[0];
         int            startIndex       = dirtyTextRange.StartIndex;
         int            positionsAdded   = dirtyTextRange.PositionsAdded;
         int            positionsRemoved = dirtyTextRange.PositionsRemoved;
         bool           flag             = dirtyTextRange.FromHighlightLayer;
         for (int i = 1; i < this._count; i++)
         {
             dirtyTextRange = this._dtrs[i];
             int num = dirtyTextRange.StartIndex - startIndex;
             positionsAdded   = num + dirtyTextRange.PositionsAdded;
             positionsRemoved = num + dirtyTextRange.PositionsRemoved;
             flag            &= dirtyTextRange.FromHighlightLayer;
             startIndex       = dirtyTextRange.StartIndex;
         }
         return(new DirtyTextRange(this._dtrs[0].StartIndex, positionsAdded, positionsRemoved, flag));
     }
     return(new DirtyTextRange(0, 0, 0, false));
 }
예제 #18
0
 // Token: 0x060067B5 RID: 26549 RVA: 0x001D1380 File Offset: 0x001CF580
 private void MergeWithNext(int index)
 {
     while (index + 1 < this._count)
     {
         DirtyTextRange dirtyTextRange = this._dtrs[index + 1];
         if (dirtyTextRange.StartIndex > this._dtrs[index].StartIndex + this._dtrs[index].PositionsRemoved)
         {
             break;
         }
         DirtyTextRange[] dtrs = this._dtrs;
         dtrs[index].PositionsAdded = dtrs[index].PositionsAdded + dirtyTextRange.PositionsAdded;
         DirtyTextRange[] dtrs2 = this._dtrs;
         dtrs2[index].PositionsRemoved = dtrs2[index].PositionsRemoved + dirtyTextRange.PositionsRemoved;
         DirtyTextRange[] dtrs3 = this._dtrs;
         dtrs3[index].FromHighlightLayer = (dtrs3[index].FromHighlightLayer & dirtyTextRange.FromHighlightLayer);
         for (int i = index + 2; i < this._count; i++)
         {
             this._dtrs[i - 1] = this._dtrs[i];
         }
         this._count--;
     }
 }
 // Token: 0x0600679A RID: 26522 RVA: 0x001CFD2C File Offset: 0x001CDF2C
 internal void UpdGetSegmentChange(out PTS.FSKCHANGE fskch)
 {
     if (base.StructuralCache.CurrentFormatContext.FinitePage)
     {
         DtrList dtrList = base.StructuralCache.DtrsFromRange(TextContainerHelper.GetCPFromElement(base.StructuralCache.TextContainer, base.Element, ElementEdge.BeforeStart), base.LastFormatCch);
         if (dtrList != null)
         {
             int            cpfromElement  = TextContainerHelper.GetCPFromElement(base.StructuralCache.TextContainer, base.Element, ElementEdge.AfterStart);
             DirtyTextRange dirtyTextRange = dtrList[0];
             int            num            = cpfromElement;
             BaseParagraph  baseParagraph  = this._firstChild;
             if (num < dirtyTextRange.StartIndex)
             {
                 while (baseParagraph != null && num + baseParagraph.LastFormatCch <= dirtyTextRange.StartIndex && (num + baseParagraph.LastFormatCch != dirtyTextRange.StartIndex || !(baseParagraph is TextParagraph)))
                 {
                     num          += baseParagraph.Cch;
                     baseParagraph = baseParagraph.Next;
                 }
                 if (baseParagraph != null)
                 {
                     baseParagraph.SetUpdateInfo(PTS.FSKCHANGE.fskchInside, false);
                 }
             }
             else
             {
                 baseParagraph.SetUpdateInfo(PTS.FSKCHANGE.fskchNew, false);
             }
             if (baseParagraph != null)
             {
                 for (baseParagraph = baseParagraph.Next; baseParagraph != null; baseParagraph = baseParagraph.Next)
                 {
                     baseParagraph.SetUpdateInfo(PTS.FSKCHANGE.fskchNew, false);
                 }
             }
             this._changeType = PTS.FSKCHANGE.fskchInside;
         }
     }
     fskch = this._changeType;
 }
예제 #20
0
파일: DtrList.cs 프로젝트: JianwenSun/cc
 // ------------------------------------------------------------------
 // Append new DTR to the list.
 //
 //      dtr - DTR to be appended to the list.
 // ------------------------------------------------------------------
 private void Append(DirtyTextRange dtr)
 {
     if (_count == _dtrs.Length) { Resize(); }
     _dtrs[_count] = dtr;
     ++_count;
 }
예제 #21
0
 // Token: 0x060067B7 RID: 26551 RVA: 0x001D14B0 File Offset: 0x001CF6B0
 private void Resize()
 {
     DirtyTextRange[] array = new DirtyTextRange[this._dtrs.Length * 2];
     Array.Copy(this._dtrs, array, this._dtrs.Length);
     this._dtrs = array;
 }
예제 #22
0
        /// <summary>
        /// OnChildDesiredSizeChanged
        /// Called from FlowDocumentPage for IContentHost implementation
        /// 



        internal void OnChildDesiredSizeChanged(UIElement child)
        {
            if (_structuralCache != null && _structuralCache.IsFormattedOnce && !_structuralCache.ForceReformat)
            {
                // If executed during formatting process, delay invalidation.
                // This may happen during formatting when text host notifies its about
                // baseline changes.
                if (_structuralCache.IsFormattingInProgress)
                {
                    Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                        new DispatcherOperationCallback(OnChildDesiredSizeChangedAsync), child);
                    return;
                }

                // Get start and end positions
                int childStartIndex = TextContainerHelper.GetCPFromEmbeddedObject(child, ElementEdge.BeforeStart);
                if (childStartIndex < 0)
                {
                    return;
                }

                TextPointer childStart = new TextPointer(_structuralCache.TextContainer.Start);
                childStart.MoveByOffset(childStartIndex);
                TextPointer childEnd = new TextPointer(childStart);
                childEnd.MoveByOffset(TextContainerHelper.EmbeddedObjectLength);

                // Create new DTR for changing UIElement and add it to DRTList.
                DirtyTextRange dtr = new DirtyTextRange(childStartIndex, TextContainerHelper.EmbeddedObjectLength, TextContainerHelper.EmbeddedObjectLength);
                _structuralCache.AddDirtyTextRange(dtr);

                // Notify formatter about content invalidation.
                if (_formatter != null)
                {
                    _formatter.OnContentInvalidated(true, childStart, childEnd);
                }
            }
        }
예제 #23
0
파일: DtrList.cs 프로젝트: JianwenSun/cc
        // ------------------------------------------------------------------
        // Increases the capacity of the DTR array.
        // <new size> = <current size>*2.
        // ------------------------------------------------------------------
        private void Resize()
        {
            Debug.Assert(_dtrs.Length > 0);

            // Allocate new array and copy all existing entries into it
            DirtyTextRange [] newdtrs = new DirtyTextRange[_dtrs.Length * 2];
            Array.Copy(_dtrs, newdtrs, _dtrs.Length);
            _dtrs = newdtrs;
        }
예제 #24
0
        // Callback from the TextContainer when a highlight changes.
        private void OnHighlightChanged(object sender, HighlightChangedEventArgs args)
        {
            // The only supported highlight type for TextBoxView is SpellerHighlight.
            if (args.OwnerType != typeof(SpellerHighlightLayer))
            {
                return;
            }

            if (_dirtyList == null)
            {
                _dirtyList = new DtrList();
            }

            //
            // Add the change to our dirty list.
            //

            foreach (TextSegment segment in args.Ranges)
            {
                int positionsCovered = segment.End.Offset - segment.Start.Offset;
                DirtyTextRange dirtyTextRange = new DirtyTextRange(segment.Start.Offset, positionsCovered, positionsCovered);
                _dirtyList.Merge(dirtyTextRange);
            }

            //
            // Force a re-measure.
            //
            // NB: it's not currently possible to InvalidateArrange here.
            // "Render only" changes from the highlight layer change the way we
            // ultimately feed text to the formatter.  Introducing breaks for
            // highlights may actually change the layout of the text as
            // characters are interpreted in different contexts.  Dev10 Bugs
            // 511849 has an example.
            //
            InvalidateMeasure();
        }
예제 #25
0
        /// <summary>
        /// Handler for TextContainer change notifications.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnTextContainerChange(object sender, TextContainerChangeEventArgs args)
        {
            DirtyTextRange dtr;
            ITextPointer segmentEnd;

            Invariant.Assert(args != null);
            Invariant.Assert(sender == _structuralCache.TextContainer);
            Invariant.Assert(_structuralCache != null && _structuralCache.IsFormattedOnce, "Unexpected TextContainer.Change callback before first format!");

            if (args.Count == 0)
            {
                // A no-op for this control.  Happens when IMECharCount updates happen
                // without corresponding SymbolCount changes.
                return;
            }

            try
            {
                // Detect invalid content change operations.
                if (_structuralCache.IsFormattingInProgress)
                {
                    _structuralCache.OnInvalidOperationDetected();
                    throw new InvalidOperationException(SR.Get(SRID.FlowDocumentInvalidContnetChange));
                }

                // Since content is changeing, do partial invalidation of BreakRecordTable.
                if (args.TextChange != TextChangeType.ContentRemoved)
                {
                    segmentEnd = args.ITextPosition.CreatePointer(args.Count, LogicalDirection.Forward);
                }
                else
                {
                    segmentEnd = args.ITextPosition;
                }

                // Invalidate affected pages and break records.
                // We DTR invalidate if we're using a formatter as well for incremental update.
                if (!args.AffectsRenderOnly || (_formatter != null && _formatter is FlowDocumentFormatter))
                {
                    // Create new DTR for changing range and add it to DRTList.
                    dtr = new DirtyTextRange(args);
                    _structuralCache.AddDirtyTextRange(dtr);
                }
                else
                {
                    // Clear format caches.
                    _structuralCache.InvalidateFormatCache(/*Clear structure*/ false);
                }

                // Notify formatter about content invalidation.
                if (_formatter != null)
                {
                    _formatter.OnContentInvalidated(!args.AffectsRenderOnly, args.ITextPosition, segmentEnd);
                }
            }
            finally
            {
                // Content has been changed, so reset appropriate flag.
                _structuralCache.IsContentChangeInProgress = false;
            }
        }
예제 #26
0
        // ------------------------------------------------------------------
        // Table has been structurally altered
        // ------------------------------------------------------------------
        private void TableStructureChanged(object sender, EventArgs e)
        {
            // Disconnect obsolete paragraphs.
            BaseParagraph paraInvalid = _firstChild;
            while (paraInvalid != null)
            {
                paraInvalid.Dispose();
                paraInvalid = paraInvalid.Next;
            }
            _firstChild = null;

            //
            // Since whole table content is disposed, we need 
            // - to create dirty text range corresponding to the Table content
            // - notify formatter that Table's content is changed.
            //
            int charCount = Table.SymbolCount - 2;// This is equivalent to (ContentEndOffset – ContentStartOffset) but is more performant.
            if (charCount > 0)
            {
                DirtyTextRange dtr = new DirtyTextRange(Table.ContentStartOffset, charCount, charCount);
                StructuralCache.AddDirtyTextRange(dtr);
            }
            if (StructuralCache.FormattingOwner.Formatter != null)
            {
                StructuralCache.FormattingOwner.Formatter.OnContentInvalidated(true, Table.ContentStart, Table.ContentEnd);
            }
        }
예제 #27
0
        // ------------------------------------------------------------------
        // Merge new DTR with list of exising DTRs:
        // 1) Convert startIndex to index reflecting position before any changes.
        // 2) Merge it with existing list of DTRs.
        //
        //      dtr - New DTR to be merged with exising list of DTRs.
        // ------------------------------------------------------------------
        internal void Merge(DirtyTextRange dtr)
        {
            bool merge         = false;
            int  i             = 0;
            int  startIndexOld = dtr.StartIndex;

            // 1) Convert StartIndex to index reflecting position before any changes.
            //    And find out if there is a need to merge DTRs
            if (_count > 0)
            {
                while (i < _count)
                {
                    // a) New DTR starts before the next one. In this case there are
                    //    two possibilities:
                    //    * new DTR does not intersect with the beginning of the next DTR,
                    //      in this case insert new DTR before the next one.
                    //    * new DTR does intersect with the beginning of the next DTR,
                    //      in this case merge these 2 DTRs
                    if (startIndexOld < _dtrs[i].StartIndex)
                    {
                        if (startIndexOld + dtr.PositionsRemoved > _dtrs[i].StartIndex)
                        {
                            merge = true;
                        }
                        // else new dtr has to be inserted at position 'i'
                        break;
                    }
                    // b) New DTR starts in the range of the previous DTR. In this case
                    //    merge these 2 DTRs
                    else if (startIndexOld <= _dtrs[i].StartIndex + _dtrs[i].PositionsAdded)
                    {
                        // merge with existing dtr at position 'i'
                        merge = true;
                        break;
                    }
                    // c) No intersection has been found, go to the next DTR in the list.
                    startIndexOld -= _dtrs[i].PositionsAdded - _dtrs[i].PositionsRemoved;
                    ++i;
                }
                // Update dcp of the new DTR, to reflect position before any tree changes.
                dtr.StartIndex = startIndexOld;
            }

            // 2) Insert new DTR into the list, merge if necessary
            if (i < _count)
            {
                if (merge)
                {
                    // The simplest way to merge these two DTRs is to add together
                    // cchAdded/cchDeleted form both DTRs, but it will invalidate more
                    // than required. Formula used below is more accurate.

                    // a) New DTR does intersect with the beginning of the next DTR,
                    //    in this case merge these 2 DTRs.
                    // * dcp = dcpN (since it starts before dcpO)
                    // * add = addN + addO - min(addO, delN - (dcpO - dcpN))
                    // * del = delN + delO - min(addO, delN - (dcpO - dcpN))
                    // NOTE: dcpO - dcpN is always <= delN
                    if (dtr.StartIndex < _dtrs[i].StartIndex)
                    {
                        int delta  = _dtrs[i].StartIndex - dtr.StartIndex;
                        int adjust = Math.Min(_dtrs[i].PositionsAdded, dtr.PositionsRemoved - delta);
                        _dtrs[i].StartIndex        = dtr.StartIndex;
                        _dtrs[i].PositionsAdded   += dtr.PositionsAdded - adjust;
                        _dtrs[i].PositionsRemoved += dtr.PositionsRemoved - adjust;
                    }
                    // b) New DTR starts in the range of the previous DTR. In this case
                    //    merge these 2 DTRs.
                    // * dcp = dcpO (since it starts before dcpN)
                    // * add = addN + addO - min(delN, addO - (dcpN - dcpO))
                    // * del = delN + delO - min(delN, addO - (dcpN - dcpO))
                    // NOTE: dcpN - dcpO is always <= addO
                    else
                    {
                        int delta  = dtr.StartIndex - _dtrs[i].StartIndex;
                        int adjust = Math.Min(dtr.PositionsRemoved, _dtrs[i].PositionsAdded - delta);
                        //_dtrs[i].dcp: no need to change it
                        _dtrs[i].PositionsAdded   += dtr.PositionsAdded - adjust;
                        _dtrs[i].PositionsRemoved += dtr.PositionsRemoved - adjust;
                    }
                }
                else
                {
                    // The new DTR has to be inserted before DTR at position 'i'.
                    if (_count == _dtrs.Length)
                    {
                        Resize();
                    }
                    Array.Copy(_dtrs, i, _dtrs, i + 1, _count - i);
                    _dtrs[i] = dtr;
                    ++_count;
                }
                MergeWithNext(i);
            }
            else
            {
                // The new DTR has to be appended to the end of the list.
                if (_count == _dtrs.Length)
                {
                    Resize();
                }
                _dtrs[_count] = dtr;
                ++_count;
            }

#if TEXTPANELLAYOUTDEBUG
            System.Text.StringBuilder msg = new System.Text.StringBuilder();
            msg.Append("Merge DTR (" + dtr.StartIndex + "," + dtr.PositionsAdded + "," + dtr.PositionsRemoved + ") ->");
            for (i = 0; i < _count; i++)
            {
                msg.Append(" (" + _dtrs[i].StartIndex + "," + _dtrs[i].PositionsAdded + "," + _dtrs[i].PositionsRemoved + ")");
            }
            TextPanelDebug.Log(msg.ToString(), TextPanelDebug.Category.ContentChange);
#endif
        }
예제 #28
0
 /// <summary>
 /// Add new DirtyTextRange.
 /// </summary>
 /// <param name="dtr">New DTR being added.</param> 
 internal void AddDirtyTextRange(DirtyTextRange dtr)
 { 
     if (_dtrs == null) 
     {
         _dtrs = new DtrList(); 
     }
     _dtrs.Merge(dtr);
 }
예제 #29
0
파일: DtrList.cs 프로젝트: JianwenSun/cc
        // ------------------------------------------------------------------
        // Merge new DTR with list of exising DTRs:
        // 1) Convert startIndex to index reflecting position before any changes.
        // 2) Merge it with existing list of DTRs.
        //
        //      dtr - New DTR to be merged with exising list of DTRs.
        // ------------------------------------------------------------------
        internal void Merge(DirtyTextRange dtr)
        {
            bool merge = false;
            int i = 0;
            int startIndexOld = dtr.StartIndex;

            // 1) Convert StartIndex to index reflecting position before any changes.
            //    And find out if there is a need to merge DTRs
            if (_count > 0)
            {
                while (i < _count)
                {
                    // a) New DTR starts before the next one. In this case there are
                    //    two possibilities:
                    //    * new DTR does not intersect with the beginning of the next DTR,
                    //      in this case insert new DTR before the next one.
                    //    * new DTR does intersect with the beginning of the next DTR,
                    //      in this case merge these 2 DTRs
                    if (startIndexOld < _dtrs[i].StartIndex)
                    {
                        if (startIndexOld + dtr.PositionsRemoved > _dtrs[i].StartIndex)
                        {
                            merge = true;
                        }
                        // else new dtr has to be inserted at position 'i'
                        break;
                    }
                    // b) New DTR starts in the range of the previous DTR. In this case
                    //    merge these 2 DTRs
                    else if (startIndexOld <= _dtrs[i].StartIndex + _dtrs[i].PositionsAdded)
                    {
                        // merge with existing dtr at position 'i'
                        merge = true;
                        break;
                    }
                    // c) No intersection has been found, go to the next DTR in the list.
                    startIndexOld -= _dtrs[i].PositionsAdded - _dtrs[i].PositionsRemoved;
                    ++i;
                }
                // Update dcp of the new DTR, to reflect position before any tree changes.
                dtr.StartIndex = startIndexOld;
            }

            // 2) Insert new DTR into the list, merge if necessary
            if (i < _count)
            {
                if (merge)
                {
                    // The simplest way to merge these two DTRs is to add together 
                    // cchAdded/cchDeleted form both DTRs, but it will invalidate more
                    // than required. Formula used below is more accurate.

                    // a) New DTR does intersect with the beginning of the next DTR,
                    //    in this case merge these 2 DTRs.
                    // * dcp = dcpN (since it starts before dcpO)
                    // * add = addN + addO - min(addO, delN - (dcpO - dcpN))
                    // * del = delN + delO - min(addO, delN - (dcpO - dcpN))
                    // NOTE: dcpO - dcpN is always <= delN
                    if (dtr.StartIndex < _dtrs[i].StartIndex)
                    {
                        int delta  = _dtrs[i].StartIndex - dtr.StartIndex;
                        int adjust = Math.Min(_dtrs[i].PositionsAdded, dtr.PositionsRemoved - delta);
                        _dtrs[i].StartIndex        = dtr.StartIndex;
                        _dtrs[i].PositionsAdded   += dtr.PositionsAdded   - adjust;
                        _dtrs[i].PositionsRemoved += dtr.PositionsRemoved - adjust;
                    }
                    // b) New DTR starts in the range of the previous DTR. In this case
                    //    merge these 2 DTRs.
                    // * dcp = dcpO (since it starts before dcpN)
                    // * add = addN + addO - min(delN, addO - (dcpN - dcpO))
                    // * del = delN + delO - min(delN, addO - (dcpN - dcpO))
                    // NOTE: dcpN - dcpO is always <= addO
                    else
                    {
                        int delta  = dtr.StartIndex - _dtrs[i].StartIndex;
                        int adjust = Math.Min(dtr.PositionsRemoved, _dtrs[i].PositionsAdded - delta);
                        //_dtrs[i].dcp: no need to change it
                        _dtrs[i].PositionsAdded   += dtr.PositionsAdded   - adjust;
                        _dtrs[i].PositionsRemoved += dtr.PositionsRemoved - adjust;
                    }
                }
                else
                {
                    // The new DTR has to be inserted before DTR at position 'i'.
                    if (_count == _dtrs.Length) { Resize(); }
                    Array.Copy(_dtrs, i, _dtrs, i+1, _count-i);
                    _dtrs[i] = dtr;
                    ++_count;
                }
                MergeWithNext(i);
            }
            else
            {
                // The new DTR has to be appended to the end of the list.
                if (_count == _dtrs.Length) { Resize(); }
                _dtrs[_count] = dtr;
                ++_count;
            }

#if TEXTPANELLAYOUTDEBUG
            System.Text.StringBuilder msg = new System.Text.StringBuilder();
            msg.Append("Merge DTR (" + dtr.StartIndex + "," + dtr.PositionsAdded + "," + dtr.PositionsRemoved + ") ->");
            for (i = 0; i < _count; i++)
            {
                msg.Append(" (" + _dtrs[i].StartIndex + "," + _dtrs[i].PositionsAdded + "," + _dtrs[i].PositionsRemoved + ")");
            }
            TextPanelDebug.Log(msg.ToString(), TextPanelDebug.Category.ContentChange);
#endif
        }
        // ------------------------------------------------------------------
        // Build UpdateRecord from DTR.
        // ------------------------------------------------------------------
        private UpdateRecord UpdateRecordFromDtr(
            DtrList dtrs,
            DirtyTextRange dtr,
            int dcpContent)
        {
            UpdateRecord ur = new UpdateRecord();

            // (1) Initialize DTR
            ur.Dtr = dtr;

            // (2) Find first paragraph affected by DTR
            BaseParagraph para = _firstChild;
            BaseParagraph paraPrev = null;
            // There might be gaps between paragraphs (example: content of List element, only 
            // nested Lists or ListItems are valid paragraphs, all other content is skipped).
            // For this reason always use para.ParagraphStartCharacterPosition to get the first
            // character position of the current paragraph.
            int dcpPara = dcpContent;
            if (dcpPara < ur.Dtr.StartIndex)
            {
                while (para != null)
                {
                    // We're looking for first affected para - We start with dco content. For
                    // all paras but TextParagraph, StartPosition/EndPosition is 
                    // |<Section></Section>|, so insertion at edge points is adding new paragraphs,
                    // not affecting current. For textpara, <Paragraph>|abcde|</Paragraph>, 
                    // insertion at edge points is a change inside for that text paragraph.
                    if (
                        dcpPara + para.LastFormatCch > ur.Dtr.StartIndex ||
                        (dcpPara + para.LastFormatCch == ur.Dtr.StartIndex && para is TextParagraph))
                    {
                        break; // the first paragraph is found
                    }

                    dcpPara += para.LastFormatCch;
                    paraPrev = para;
                    para = para.Next;
                }
            }
            // else the change is before the first paragraph
            ur.FirstPara = para;

            // (3) Determine change type for the fist affected paragraph
            if (para == null)
            {
                ur.ChangeType = PTS.FSKCHANGE.fskchNew;
            }
            else if (dcpPara < ur.Dtr.StartIndex)
            {
                ur.ChangeType = PTS.FSKCHANGE.fskchInside;
            }
            else
            {
                ur.ChangeType = PTS.FSKCHANGE.fskchNew;
            }

            // (4) Find synchronization point, the first paragraph after DTR
            ur.SyncPara = null;
            while (para != null)
            {
                if (   (dcpPara + para.LastFormatCch > ur.Dtr.StartIndex + ur.Dtr.PositionsRemoved)
                    || (dcpPara + para.LastFormatCch == ur.Dtr.StartIndex + ur.Dtr.PositionsRemoved && ur.ChangeType != PTS.FSKCHANGE.fskchNew))
                {
                    ur.SyncPara = para.Next;
                    break;
                }
                dcpPara += para.LastFormatCch;
                para = para.Next;
            }
            return ur;
        }
예제 #31
0
        // Callback from the TextContainer on a document edit.
        private void OnTextContainerChange(object sender, TextContainerChangeEventArgs args)
        {
            if (args.Count == 0)
            {
                // A no-op for this control.  Happens when IMECharCount updates happen
                // without corresponding SymbolCount changes.
                return;
            }

            //
            // Add the change to our dirty list.
            //

            if (_dirtyList == null)
            {
                _dirtyList = new DtrList();
            }

            DirtyTextRange dirtyTextRange = new DirtyTextRange(args);
            _dirtyList.Merge(dirtyTextRange);

            //
            // Force a re-measure.
            //
            InvalidateMeasure();
        }
예제 #32
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);
            }
        }
예제 #33
0
        // Token: 0x060067B2 RID: 26546 RVA: 0x001D0EDC File Offset: 0x001CF0DC
        internal void Merge(DirtyTextRange dtr)
        {
            bool flag = false;
            int  i    = 0;
            int  num  = dtr.StartIndex;

            if (this._count > 0)
            {
                while (i < this._count)
                {
                    if (num < this._dtrs[i].StartIndex)
                    {
                        if (num + dtr.PositionsRemoved > this._dtrs[i].StartIndex)
                        {
                            flag = true;
                            break;
                        }
                        break;
                    }
                    else
                    {
                        if (num <= this._dtrs[i].StartIndex + this._dtrs[i].PositionsAdded)
                        {
                            flag = true;
                            break;
                        }
                        num -= this._dtrs[i].PositionsAdded - this._dtrs[i].PositionsRemoved;
                        i++;
                    }
                }
                dtr.StartIndex = num;
            }
            if (i < this._count)
            {
                if (flag)
                {
                    if (dtr.StartIndex < this._dtrs[i].StartIndex)
                    {
                        int num2 = this._dtrs[i].StartIndex - dtr.StartIndex;
                        int num3 = Math.Min(this._dtrs[i].PositionsAdded, dtr.PositionsRemoved - num2);
                        this._dtrs[i].StartIndex = dtr.StartIndex;
                        DirtyTextRange[] dtrs = this._dtrs;
                        int num4 = i;
                        dtrs[num4].PositionsAdded = dtrs[num4].PositionsAdded + (dtr.PositionsAdded - num3);
                        DirtyTextRange[] dtrs2 = this._dtrs;
                        int num5 = i;
                        dtrs2[num5].PositionsRemoved = dtrs2[num5].PositionsRemoved + (dtr.PositionsRemoved - num3);
                    }
                    else
                    {
                        int num6 = dtr.StartIndex - this._dtrs[i].StartIndex;
                        int num7 = Math.Min(dtr.PositionsRemoved, this._dtrs[i].PositionsAdded - num6);
                        DirtyTextRange[] dtrs3 = this._dtrs;
                        int num8 = i;
                        dtrs3[num8].PositionsAdded = dtrs3[num8].PositionsAdded + (dtr.PositionsAdded - num7);
                        DirtyTextRange[] dtrs4 = this._dtrs;
                        int num9 = i;
                        dtrs4[num9].PositionsRemoved = dtrs4[num9].PositionsRemoved + (dtr.PositionsRemoved - num7);
                    }
                    DirtyTextRange[] dtrs5 = this._dtrs;
                    int num10 = i;
                    dtrs5[num10].FromHighlightLayer = (dtrs5[num10].FromHighlightLayer & dtr.FromHighlightLayer);
                }
                else
                {
                    if (this._count == this._dtrs.Length)
                    {
                        this.Resize();
                    }
                    Array.Copy(this._dtrs, i, this._dtrs, i + 1, this._count - i);
                    this._dtrs[i] = dtr;
                    this._count++;
                }
                this.MergeWithNext(i);
                return;
            }
            if (this._count == this._dtrs.Length)
            {
                this.Resize();
            }
            this._dtrs[this._count] = dtr;
            this._count++;
        }
예제 #34
0
파일: DtrList.cs 프로젝트: JianwenSun/cc
 // ------------------------------------------------------------------
 // Construct a DtrList. The array of DTRs initially can store up to
 // 4 entries. Upon adding elements the capacity increased in multiples 
 // of two as required.
 // ------------------------------------------------------------------
 internal DtrList()
 {
     _dtrs = new DirtyTextRange[_defaultCapacity];
     _count = 0;
 }
예제 #35
0
 // ------------------------------------------------------------------
 // Construct a DtrList. The array of DTRs initially can store up to
 // 4 entries. Upon adding elements the capacity increased in multiples
 // of two as required.
 // ------------------------------------------------------------------
 internal DtrList()
 {
     _dtrs  = new DirtyTextRange[_defaultCapacity];
     _count = 0;
 }
예제 #36
0
        /// <summary>
        /// Invalidates a portion of text affected by a highlight change.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnHighlightChanged(object sender, HighlightChangedEventArgs args)
        {
            TextSegment textSegment;
            int i;

            Invariant.Assert(args != null);
            Invariant.Assert(args.Ranges != null);
            Invariant.Assert(_structuralCache != null && _structuralCache.IsFormattedOnce, "Unexpected Highlights.Changed callback before first format!");

            // Detect invalid content change operations.
            if (_structuralCache.IsFormattingInProgress)
            {
                _structuralCache.OnInvalidOperationDetected();
                throw new InvalidOperationException(SR.Get(SRID.FlowDocumentInvalidContnetChange));
            }

            // The only supported highlight type for FlowDocument is SpellerHightlight.
            // TextSelection and HighlightComponent are ignored, because they are handled by
            // separate layer.
            if (args.OwnerType != typeof(SpellerHighlightLayer))
            {
                return;
            }

            if (args.Ranges.Count > 0)
            {

                // Invalidate affected pages and break records.
                // We DTR invalidate if we're using a formatter as well for incremental update.
                if (_formatter == null || !(_formatter is FlowDocumentFormatter))
                {
                    _structuralCache.InvalidateFormatCache(/*Clear structure*/ false);
                }

                // Notify formatter about content invalidation.
                if (_formatter != null)
                {
                    for (i = 0; i < args.Ranges.Count; i++)
                    {
                        textSegment = (TextSegment)args.Ranges[i];
                        _formatter.OnContentInvalidated(false, textSegment.Start, textSegment.End);

                        if (_formatter is FlowDocumentFormatter)
                        {
                            DirtyTextRange dtr = new DirtyTextRange(textSegment.Start.Offset,
                                                                    textSegment.Start.GetOffsetToPosition(textSegment.End),
                                                                    textSegment.Start.GetOffsetToPosition(textSegment.End)
                                                                    );
                            _structuralCache.AddDirtyTextRange(dtr);
                        }
                    }
                }
            }
        }
예제 #37
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();
        }
예제 #38
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;
        }
예제 #39
0
        //-------------------------------------------------------------------
        // Defers remaining text formatting to background - treated as if new text
        //-------------------------------------------------------------------
        private void DeferFormattingToBackground()
        {
            int cpLast = _section.StructuralCache.BackgroundFormatInfo.CPInterrupted;
            int cpTextContainer = _section.StructuralCache.BackgroundFormatInfo.CchAllText;
                                                                                                                          
            DirtyTextRange dtr = new DirtyTextRange(cpLast, cpTextContainer - cpLast, cpTextContainer - cpLast);
            _section.StructuralCache.AddDirtyTextRange(dtr);

            _backgroundFormatOperation = Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, BackgroundUpdateCallback, this);
        }
예제 #40
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();
        }