Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / MS / Internal / PtsHost / BreakRecordTable.cs / 1 / BreakRecordTable.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: BreakRecordTable manages cached informaion bout pages and // break records of FlowDocument contnet. // // History: // 01/24/2004 : grzegorz - Created // //--------------------------------------------------------------------------- using System; // WeakReference, ... using System.Collections.Generic; // Listusing System.Collections.ObjectModel; // ReadOnlyCollection using System.Windows.Documents; // FlowDocument, TextPointer using MS.Internal.Documents; // TextDocumentView namespace MS.Internal.PtsHost { /// /// BreakRecordTable manages cached informaion bout pages and break /// records of FlowDocument contnet. /// internal sealed class BreakRecordTable { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors ////// Constructor. /// /// Ownder of the BreakRecordTable. internal BreakRecordTable(FlowDocumentPaginator owner) { _owner = owner; _breakRecords = new List(); } #endregion Constructors //-------------------------------------------------------------------- // // Internal Methods // //------------------------------------------------------------------- #region Internal Methods /// /// Retrieves input BreakRecord for given PageNumber. /// /// /// Page index indicating which input BreakRecord should be retrieved. ///Input BreakRecord for given PageNumber. internal PageBreakRecord GetPageBreakRecord(int pageNumber) { PageBreakRecord breakRecord = null; Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "Invalid PageNumber."); // Input BreakRecord for the first page is always NULL. // For the rest of pages, go to the entry preceding requested index and // return the output BreakRecord. if (pageNumber > 0) { Invariant.Assert(_breakRecords[pageNumber - 1] != null, "Invalid BreakRecordTable entry."); breakRecord = _breakRecords[pageNumber - 1].BreakRecord; Invariant.Assert(breakRecord != null, "BreakRecord can be null only for the first page."); } return breakRecord; } ////// Retrieves cached DocumentPage for given PageNumber. /// /// /// Page index indicating which cached DocumentPage should be retrieved. /// ///Cached DocumentPage for given PageNumber. internal FlowDocumentPage GetCachedDocumentPage(int pageNumber) { WeakReference pageRef; FlowDocumentPage documentPage = null; if (pageNumber < _breakRecords.Count) { Invariant.Assert(_breakRecords[pageNumber] != null, "Invalid BreakRecordTable entry."); pageRef = _breakRecords[pageNumber].DocumentPage; if (pageRef != null) { documentPage = pageRef.Target as FlowDocumentPage; if (documentPage != null && documentPage.IsDisposed) { documentPage = null; } } } return documentPage; } ////// Retrieves PageNumber for specified ContentPosition. /// /// /// Represents content position for which PageNumber is requested. /// Starting index for search process. ////// Returns true, if successfull. 'pageNumber' is updated with actual /// page number that contains specified ContentPosition. /// Returns false, if BreakRecordTable is missing information about /// page that contains specified ContentPosition. 'pageNumber' /// is updated with the last investigated page number. /// internal bool GetPageNumberForContentPosition(TextPointer contentPosition, ref int pageNumber) { bool foundPageNumber = false; ReadOnlyCollectiontextSegments; Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "Invalid PageNumber."); // Iterate through entries in the BreakRecordTable (starting from specified index) // and look for page that contains specified ContentPosition. // NOTE: For each cached page collection of TextSegments is stored to // optimize this search. while (pageNumber < _breakRecords.Count) { Invariant.Assert(_breakRecords[pageNumber] != null, "Invalid BreakRecordTable entry."); textSegments = _breakRecords[pageNumber].TextSegments; if (textSegments != null) { if (TextDocumentView.Contains(contentPosition, textSegments)) { foundPageNumber = true; break; } } else { // There is no information about this page. break; } ++pageNumber; } return foundPageNumber; } /// /// Layout of entire content has been affected. /// internal void OnInvalidateLayout() { if (_breakRecords.Count > 0) { // Destroy all affected BreakRecords. InvalidateBreakRecords(0, _breakRecords.Count); // Initiate the next async operation. _owner.InitiateNextAsyncOperation(); // Raise PagesChanged event. Start with the first page and set // count to Int.Max/2, because somebody might want to display a page // that wasn't available before, but will be right now. _owner.OnPagesChanged(0, int.MaxValue/2); } } ////// Layout for specified range has been affected. /// /// Start of the affected content range. /// End of the affected content range. internal void OnInvalidateLayout(ITextPointer start, ITextPointer end) { int pageStart, pageCount; if (_breakRecords.Count > 0) { // Get range of affected pages and dispose them GetAffectedPages(start, end, out pageStart, out pageCount); // Currently there is no possibility to do partial invalidation // of BreakRecordTable, so always extend pageCount to the end // of BreakRecordTable. pageCount = _breakRecords.Count - pageStart; if (pageCount > 0) { // Destroy all affected BreakRecords. InvalidateBreakRecords(pageStart, pageCount); // Initiate the next async operation. _owner.InitiateNextAsyncOperation(); // Raise PagesChanged event. Start with the first affected page and set // count to Int.Max/2, because somebody might want to display a page // that wasn't available before, but will be right now. _owner.OnPagesChanged(pageStart, int.MaxValue/2); } } } ////// Rendering of entire content has been affected. /// internal void OnInvalidateRender() { if (_breakRecords.Count > 0) { // Dispose all existing pages. DisposePages(0, _breakRecords.Count); // Raise PagesChanged event. Start with the first page and set // count to this.Count (number of pages have not been changed). _owner.OnPagesChanged(0, _breakRecords.Count); } } ////// Rendering for specified range has been affected. /// /// Start of the affected content range. /// End of the affected content range. internal void OnInvalidateRender(ITextPointer start, ITextPointer end) { int pageStart, pageCount; if (_breakRecords.Count > 0) { // Get range of affected pages and dispose them. GetAffectedPages(start, end, out pageStart, out pageCount); if (pageCount > 0) { // Dispose all affected pages. DisposePages(pageStart, pageCount); // Raise PagesChanged event. _owner.OnPagesChanged(pageStart, pageCount); } } } ////// Updates entry of BreakRecordTable with new data. /// /// Index of the entry to update. /// DocumentPage object that has been just created. /// Output BreakRecord for created page. /// Last content position that can affect the output break record. internal void UpdateEntry(int pageNumber, FlowDocumentPage page, PageBreakRecord brOut, TextPointer dependentMax) { ITextView textView; BreakRecordTableEntry entry; bool isClean; Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "The previous BreakRecord does not exist."); Invariant.Assert(page != null && page != DocumentPage.Missing, "Cannot update BRT with an invalid document page."); // Get TextView for DocumentPage. This TextView is used to access list of // content ranges. Those serve as optimalization in finding affeceted pages. textView = (ITextView)((IServiceProvider)page).GetService(typeof(ITextView)); Invariant.Assert(textView != null, "Cannot access ITextView for FlowDocumentPage."); // Get current state of BreakRecordTable isClean = this.IsClean; // Add new entry into BreakRecordTable entry = new BreakRecordTableEntry(); entry.BreakRecord = brOut; entry.DocumentPage = new WeakReference(page); entry.TextSegments = textView.TextSegments; entry.DependentMax = dependentMax; if (pageNumber == _breakRecords.Count) { _breakRecords.Add(entry); // Raise PaginationProgress event only if we did not have valid // entry for specified page number. _owner.OnPaginationProgress(pageNumber, 1); } else { // If old Page and/or BreakRecord are not changing, do not dispose them. if (_breakRecords[pageNumber].BreakRecord != null && _breakRecords[pageNumber].BreakRecord != entry.BreakRecord) { _breakRecords[pageNumber].BreakRecord.Dispose(); } if (_breakRecords[pageNumber].DocumentPage != null && _breakRecords[pageNumber].DocumentPage.Target != null && _breakRecords[pageNumber].DocumentPage.Target != entry.DocumentPage.Target) { ((FlowDocumentPage)_breakRecords[pageNumber].DocumentPage.Target).Dispose(); } _breakRecords[pageNumber] = entry; } // Raise PaginationCompleted event only if the BreakRecordTable just // become clean. if (!isClean && this.IsClean) { _owner.OnPaginationCompleted(); } } ////// Determines whenever input BreakRecord for given page number exists. /// /// Page index. ///true, if BreakRecord for given page number exists. internal bool HasPageBreakRecord(int pageNumber) { Invariant.Assert(pageNumber >= 0, "Page number cannot be negative."); // For the first page, the input break record is always NULL. // For the rest of pages, it exists if the preceding entry has // non-NULL output BreakRecord. if (pageNumber == 0) return true; if (pageNumber > _breakRecords.Count) return false; Invariant.Assert(_breakRecords[pageNumber - 1] != null, "Invalid BreakRecordTable entry."); return (_breakRecords[pageNumber - 1].BreakRecord != null); } #endregion Internal Methods //-------------------------------------------------------------------- // // Internal Properties // //-------------------------------------------------------------------- #region Internal Properties ////// Current count reflecting number of known pages. /// internal int Count { get { return _breakRecords.Count; } } ////// Whether BreakRecordTable is clean. /// internal bool IsClean { get { if (_breakRecords.Count == 0) return false; Invariant.Assert(_breakRecords[_breakRecords.Count - 1] != null, "Invalid BreakRecordTable entry."); return (_breakRecords[_breakRecords.Count - 1].BreakRecord == null); } } #endregion Internal Properties //------------------------------------------------------------------- // // Private Methods // //-------------------------------------------------------------------- #region Private Methods ////// Dispose all alive pages for specified range. /// /// Index of the first page to dispose. /// Number of pages to dispose. private void DisposePages(int start, int count) { WeakReference pageRef; int index = start + count - 1; // Start from the end of BreakRecordTable Invariant.Assert(start >= 0 && start < _breakRecords.Count, "Invalid starting index for BreakRecordTable invalidation."); Invariant.Assert(start + count <= _breakRecords.Count, "Partial invalidation of BreakRecordTable is not allowed."); while (index >= start) { Invariant.Assert(_breakRecords[index] != null, "Invalid BreakRecordTable entry."); pageRef = _breakRecords[index].DocumentPage; if (pageRef != null && pageRef.Target != null) { ((FlowDocumentPage)pageRef.Target).Dispose(); } _breakRecords[index].DocumentPage = null; index--; } } ////// Destroy BreakRecordsTable entries for specified range. /// /// Index of the first entry to destroy. /// Nmber of entries to destroy. private void InvalidateBreakRecords(int start, int count) { WeakReference pageRef; int index = start + count - 1; // Start from the end of BreakRecordTable Invariant.Assert(start >= 0 && start < _breakRecords.Count, "Invalid starting index for BreakRecordTable invalidation."); Invariant.Assert(start + count == _breakRecords.Count, "Partial invalidation of BreakRecordTable is not allowed."); while (index >= start) { Invariant.Assert(_breakRecords[index] != null, "Invalid BreakRecordTable entry."); // Dispose Page and BreakRecord before removing the entry. pageRef = _breakRecords[index].DocumentPage; if (pageRef != null && pageRef.Target != null) { ((FlowDocumentPage)pageRef.Target).Dispose(); } if (_breakRecords[start].BreakRecord != null) { _breakRecords[start].BreakRecord.Dispose(); } // Remov the entry. _breakRecords.RemoveAt(index); index--; } } ////// Retrieves indices of affected pages by specified content range. /// /// Content change start position. /// Content change end position. /// The first affected page. /// Number of affected pages. private void GetAffectedPages(ITextPointer start, ITextPointer end, out int pageStart, out int pageCount) { bool affects; ReadOnlyCollectiontextSegments; TextPointer dependentMax; // Find the first affected page. pageStart = 0; while (pageStart < _breakRecords.Count) { Invariant.Assert(_breakRecords[pageStart] != null, "Invalid BreakRecordTable entry."); // If the start position is before last position affecting the output break record, // this page is affected. dependentMax = _breakRecords[pageStart].DependentMax; if (dependentMax != null) { if (start.CompareTo(dependentMax) <= 0) break; } textSegments = _breakRecords[pageStart].TextSegments; if (textSegments != null) { affects = false; foreach (TextSegment textSegment in textSegments) { if (start.CompareTo(textSegment.End) <= 0) { affects = true; break; } } if (affects) break; } else { // There is no information about this page, so assume that it is // affected. break; } ++pageStart; } // Find the last affected page // For now assume that all following pages are affected. pageCount = _breakRecords.Count - pageStart; } #endregion Private Methods //------------------------------------------------------------------- // // Private Fields // //------------------------------------------------------------------- #region Private Fields /// /// Owner of the BreakRecordTable. /// private FlowDocumentPaginator _owner; ////// Array of entries in the BreakRecordTable. /// private List_breakRecords; /// /// BreakRecordTableEntry /// private class BreakRecordTableEntry { public PageBreakRecord BreakRecord; public ReadOnlyCollectionTextSegments; public WeakReference DocumentPage; public TextPointer DependentMax; } #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: BreakRecordTable manages cached informaion bout pages and // break records of FlowDocument contnet. // // History: // 01/24/2004 : grzegorz - Created // //--------------------------------------------------------------------------- using System; // WeakReference, ... using System.Collections.Generic; // List using System.Collections.ObjectModel; // ReadOnlyCollection using System.Windows.Documents; // FlowDocument, TextPointer using MS.Internal.Documents; // TextDocumentView namespace MS.Internal.PtsHost { /// /// BreakRecordTable manages cached informaion bout pages and break /// records of FlowDocument contnet. /// internal sealed class BreakRecordTable { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors ////// Constructor. /// /// Ownder of the BreakRecordTable. internal BreakRecordTable(FlowDocumentPaginator owner) { _owner = owner; _breakRecords = new List(); } #endregion Constructors //-------------------------------------------------------------------- // // Internal Methods // //------------------------------------------------------------------- #region Internal Methods /// /// Retrieves input BreakRecord for given PageNumber. /// /// /// Page index indicating which input BreakRecord should be retrieved. ///Input BreakRecord for given PageNumber. internal PageBreakRecord GetPageBreakRecord(int pageNumber) { PageBreakRecord breakRecord = null; Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "Invalid PageNumber."); // Input BreakRecord for the first page is always NULL. // For the rest of pages, go to the entry preceding requested index and // return the output BreakRecord. if (pageNumber > 0) { Invariant.Assert(_breakRecords[pageNumber - 1] != null, "Invalid BreakRecordTable entry."); breakRecord = _breakRecords[pageNumber - 1].BreakRecord; Invariant.Assert(breakRecord != null, "BreakRecord can be null only for the first page."); } return breakRecord; } ////// Retrieves cached DocumentPage for given PageNumber. /// /// /// Page index indicating which cached DocumentPage should be retrieved. /// ///Cached DocumentPage for given PageNumber. internal FlowDocumentPage GetCachedDocumentPage(int pageNumber) { WeakReference pageRef; FlowDocumentPage documentPage = null; if (pageNumber < _breakRecords.Count) { Invariant.Assert(_breakRecords[pageNumber] != null, "Invalid BreakRecordTable entry."); pageRef = _breakRecords[pageNumber].DocumentPage; if (pageRef != null) { documentPage = pageRef.Target as FlowDocumentPage; if (documentPage != null && documentPage.IsDisposed) { documentPage = null; } } } return documentPage; } ////// Retrieves PageNumber for specified ContentPosition. /// /// /// Represents content position for which PageNumber is requested. /// Starting index for search process. ////// Returns true, if successfull. 'pageNumber' is updated with actual /// page number that contains specified ContentPosition. /// Returns false, if BreakRecordTable is missing information about /// page that contains specified ContentPosition. 'pageNumber' /// is updated with the last investigated page number. /// internal bool GetPageNumberForContentPosition(TextPointer contentPosition, ref int pageNumber) { bool foundPageNumber = false; ReadOnlyCollectiontextSegments; Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "Invalid PageNumber."); // Iterate through entries in the BreakRecordTable (starting from specified index) // and look for page that contains specified ContentPosition. // NOTE: For each cached page collection of TextSegments is stored to // optimize this search. while (pageNumber < _breakRecords.Count) { Invariant.Assert(_breakRecords[pageNumber] != null, "Invalid BreakRecordTable entry."); textSegments = _breakRecords[pageNumber].TextSegments; if (textSegments != null) { if (TextDocumentView.Contains(contentPosition, textSegments)) { foundPageNumber = true; break; } } else { // There is no information about this page. break; } ++pageNumber; } return foundPageNumber; } /// /// Layout of entire content has been affected. /// internal void OnInvalidateLayout() { if (_breakRecords.Count > 0) { // Destroy all affected BreakRecords. InvalidateBreakRecords(0, _breakRecords.Count); // Initiate the next async operation. _owner.InitiateNextAsyncOperation(); // Raise PagesChanged event. Start with the first page and set // count to Int.Max/2, because somebody might want to display a page // that wasn't available before, but will be right now. _owner.OnPagesChanged(0, int.MaxValue/2); } } ////// Layout for specified range has been affected. /// /// Start of the affected content range. /// End of the affected content range. internal void OnInvalidateLayout(ITextPointer start, ITextPointer end) { int pageStart, pageCount; if (_breakRecords.Count > 0) { // Get range of affected pages and dispose them GetAffectedPages(start, end, out pageStart, out pageCount); // Currently there is no possibility to do partial invalidation // of BreakRecordTable, so always extend pageCount to the end // of BreakRecordTable. pageCount = _breakRecords.Count - pageStart; if (pageCount > 0) { // Destroy all affected BreakRecords. InvalidateBreakRecords(pageStart, pageCount); // Initiate the next async operation. _owner.InitiateNextAsyncOperation(); // Raise PagesChanged event. Start with the first affected page and set // count to Int.Max/2, because somebody might want to display a page // that wasn't available before, but will be right now. _owner.OnPagesChanged(pageStart, int.MaxValue/2); } } } ////// Rendering of entire content has been affected. /// internal void OnInvalidateRender() { if (_breakRecords.Count > 0) { // Dispose all existing pages. DisposePages(0, _breakRecords.Count); // Raise PagesChanged event. Start with the first page and set // count to this.Count (number of pages have not been changed). _owner.OnPagesChanged(0, _breakRecords.Count); } } ////// Rendering for specified range has been affected. /// /// Start of the affected content range. /// End of the affected content range. internal void OnInvalidateRender(ITextPointer start, ITextPointer end) { int pageStart, pageCount; if (_breakRecords.Count > 0) { // Get range of affected pages and dispose them. GetAffectedPages(start, end, out pageStart, out pageCount); if (pageCount > 0) { // Dispose all affected pages. DisposePages(pageStart, pageCount); // Raise PagesChanged event. _owner.OnPagesChanged(pageStart, pageCount); } } } ////// Updates entry of BreakRecordTable with new data. /// /// Index of the entry to update. /// DocumentPage object that has been just created. /// Output BreakRecord for created page. /// Last content position that can affect the output break record. internal void UpdateEntry(int pageNumber, FlowDocumentPage page, PageBreakRecord brOut, TextPointer dependentMax) { ITextView textView; BreakRecordTableEntry entry; bool isClean; Invariant.Assert(pageNumber >= 0 && pageNumber <= _breakRecords.Count, "The previous BreakRecord does not exist."); Invariant.Assert(page != null && page != DocumentPage.Missing, "Cannot update BRT with an invalid document page."); // Get TextView for DocumentPage. This TextView is used to access list of // content ranges. Those serve as optimalization in finding affeceted pages. textView = (ITextView)((IServiceProvider)page).GetService(typeof(ITextView)); Invariant.Assert(textView != null, "Cannot access ITextView for FlowDocumentPage."); // Get current state of BreakRecordTable isClean = this.IsClean; // Add new entry into BreakRecordTable entry = new BreakRecordTableEntry(); entry.BreakRecord = brOut; entry.DocumentPage = new WeakReference(page); entry.TextSegments = textView.TextSegments; entry.DependentMax = dependentMax; if (pageNumber == _breakRecords.Count) { _breakRecords.Add(entry); // Raise PaginationProgress event only if we did not have valid // entry for specified page number. _owner.OnPaginationProgress(pageNumber, 1); } else { // If old Page and/or BreakRecord are not changing, do not dispose them. if (_breakRecords[pageNumber].BreakRecord != null && _breakRecords[pageNumber].BreakRecord != entry.BreakRecord) { _breakRecords[pageNumber].BreakRecord.Dispose(); } if (_breakRecords[pageNumber].DocumentPage != null && _breakRecords[pageNumber].DocumentPage.Target != null && _breakRecords[pageNumber].DocumentPage.Target != entry.DocumentPage.Target) { ((FlowDocumentPage)_breakRecords[pageNumber].DocumentPage.Target).Dispose(); } _breakRecords[pageNumber] = entry; } // Raise PaginationCompleted event only if the BreakRecordTable just // become clean. if (!isClean && this.IsClean) { _owner.OnPaginationCompleted(); } } ////// Determines whenever input BreakRecord for given page number exists. /// /// Page index. ///true, if BreakRecord for given page number exists. internal bool HasPageBreakRecord(int pageNumber) { Invariant.Assert(pageNumber >= 0, "Page number cannot be negative."); // For the first page, the input break record is always NULL. // For the rest of pages, it exists if the preceding entry has // non-NULL output BreakRecord. if (pageNumber == 0) return true; if (pageNumber > _breakRecords.Count) return false; Invariant.Assert(_breakRecords[pageNumber - 1] != null, "Invalid BreakRecordTable entry."); return (_breakRecords[pageNumber - 1].BreakRecord != null); } #endregion Internal Methods //-------------------------------------------------------------------- // // Internal Properties // //-------------------------------------------------------------------- #region Internal Properties ////// Current count reflecting number of known pages. /// internal int Count { get { return _breakRecords.Count; } } ////// Whether BreakRecordTable is clean. /// internal bool IsClean { get { if (_breakRecords.Count == 0) return false; Invariant.Assert(_breakRecords[_breakRecords.Count - 1] != null, "Invalid BreakRecordTable entry."); return (_breakRecords[_breakRecords.Count - 1].BreakRecord == null); } } #endregion Internal Properties //------------------------------------------------------------------- // // Private Methods // //-------------------------------------------------------------------- #region Private Methods ////// Dispose all alive pages for specified range. /// /// Index of the first page to dispose. /// Number of pages to dispose. private void DisposePages(int start, int count) { WeakReference pageRef; int index = start + count - 1; // Start from the end of BreakRecordTable Invariant.Assert(start >= 0 && start < _breakRecords.Count, "Invalid starting index for BreakRecordTable invalidation."); Invariant.Assert(start + count <= _breakRecords.Count, "Partial invalidation of BreakRecordTable is not allowed."); while (index >= start) { Invariant.Assert(_breakRecords[index] != null, "Invalid BreakRecordTable entry."); pageRef = _breakRecords[index].DocumentPage; if (pageRef != null && pageRef.Target != null) { ((FlowDocumentPage)pageRef.Target).Dispose(); } _breakRecords[index].DocumentPage = null; index--; } } ////// Destroy BreakRecordsTable entries for specified range. /// /// Index of the first entry to destroy. /// Nmber of entries to destroy. private void InvalidateBreakRecords(int start, int count) { WeakReference pageRef; int index = start + count - 1; // Start from the end of BreakRecordTable Invariant.Assert(start >= 0 && start < _breakRecords.Count, "Invalid starting index for BreakRecordTable invalidation."); Invariant.Assert(start + count == _breakRecords.Count, "Partial invalidation of BreakRecordTable is not allowed."); while (index >= start) { Invariant.Assert(_breakRecords[index] != null, "Invalid BreakRecordTable entry."); // Dispose Page and BreakRecord before removing the entry. pageRef = _breakRecords[index].DocumentPage; if (pageRef != null && pageRef.Target != null) { ((FlowDocumentPage)pageRef.Target).Dispose(); } if (_breakRecords[start].BreakRecord != null) { _breakRecords[start].BreakRecord.Dispose(); } // Remov the entry. _breakRecords.RemoveAt(index); index--; } } ////// Retrieves indices of affected pages by specified content range. /// /// Content change start position. /// Content change end position. /// The first affected page. /// Number of affected pages. private void GetAffectedPages(ITextPointer start, ITextPointer end, out int pageStart, out int pageCount) { bool affects; ReadOnlyCollectiontextSegments; TextPointer dependentMax; // Find the first affected page. pageStart = 0; while (pageStart < _breakRecords.Count) { Invariant.Assert(_breakRecords[pageStart] != null, "Invalid BreakRecordTable entry."); // If the start position is before last position affecting the output break record, // this page is affected. dependentMax = _breakRecords[pageStart].DependentMax; if (dependentMax != null) { if (start.CompareTo(dependentMax) <= 0) break; } textSegments = _breakRecords[pageStart].TextSegments; if (textSegments != null) { affects = false; foreach (TextSegment textSegment in textSegments) { if (start.CompareTo(textSegment.End) <= 0) { affects = true; break; } } if (affects) break; } else { // There is no information about this page, so assume that it is // affected. break; } ++pageStart; } // Find the last affected page // For now assume that all following pages are affected. pageCount = _breakRecords.Count - pageStart; } #endregion Private Methods //------------------------------------------------------------------- // // Private Fields // //------------------------------------------------------------------- #region Private Fields /// /// Owner of the BreakRecordTable. /// private FlowDocumentPaginator _owner; ////// Array of entries in the BreakRecordTable. /// private List_breakRecords; /// /// BreakRecordTableEntry /// private class BreakRecordTableEntry { public PageBreakRecord BreakRecord; public ReadOnlyCollectionTextSegments; public WeakReference DocumentPage; public TextPointer DependentMax; } #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EmbossBitmapEffect.cs
- invalidudtexception.cs
- QilChoice.cs
- EditorZoneBase.cs
- PenThreadPool.cs
- DetailsViewRow.cs
- ActivationArguments.cs
- PathParser.cs
- AdPostCacheSubstitution.cs
- TextProperties.cs
- MetafileHeaderWmf.cs
- Matrix.cs
- DocumentXPathNavigator.cs
- ImageSource.cs
- MachineKeyConverter.cs
- BufferedGraphicsManager.cs
- SafeSecurityHelper.cs
- NullReferenceException.cs
- DrawingDrawingContext.cs
- WebPartDisplayModeCollection.cs
- NumericUpDown.cs
- WindowsEditBox.cs
- CodeTypeMember.cs
- HtmlSelectionListAdapter.cs
- UnsafeNativeMethods.cs
- BaseAddressPrefixFilterElementCollection.cs
- XmlNamespaceDeclarationsAttribute.cs
- CultureInfoConverter.cs
- TimeSpanFormat.cs
- KnownBoxes.cs
- ProgressBar.cs
- RegexFCD.cs
- DuplicateWaitObjectException.cs
- ViewPort3D.cs
- XmlSortKeyAccumulator.cs
- XmlValueConverter.cs
- ObjectQueryProvider.cs
- XmlSchemaValidator.cs
- ZipIOLocalFileHeader.cs
- URIFormatException.cs
- HeaderedContentControl.cs
- SqlProviderManifest.cs
- ExtensionQuery.cs
- ProcessDesigner.cs
- ArrangedElementCollection.cs
- StrokeRenderer.cs
- FilteredDataSetHelper.cs
- Visitors.cs
- ControlParameter.cs
- Setter.cs
- PrincipalPermissionMode.cs
- BitVector32.cs
- DataViewListener.cs
- GridViewDeleteEventArgs.cs
- WebBrowser.cs
- DeviceContext2.cs
- TracingConnectionListener.cs
- SrgsToken.cs
- DoWorkEventArgs.cs
- ClientConvert.cs
- NullableFloatAverageAggregationOperator.cs
- PolicyDesigner.cs
- ToolboxItem.cs
- EdmSchemaAttribute.cs
- TabItemWrapperAutomationPeer.cs
- SqlClientWrapperSmiStreamChars.cs
- FormViewActionList.cs
- FileUtil.cs
- SignatureDescription.cs
- ContractNamespaceAttribute.cs
- ResourceManager.cs
- ByteBufferPool.cs
- JobCollate.cs
- CriticalFinalizerObject.cs
- TableCellCollection.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- RichTextBoxAutomationPeer.cs
- ObjectListShowCommandsEventArgs.cs
- FunctionParameter.cs
- BasicCommandTreeVisitor.cs
- CrossSiteScriptingValidation.cs
- RsaKeyIdentifierClause.cs
- FixedFindEngine.cs
- X509CertificateStore.cs
- CurrentChangingEventArgs.cs
- Logging.cs
- SendParametersContent.cs
- ObjectToIdCache.cs
- Color.cs
- StateItem.cs
- HttpWebResponse.cs
- XmlAnyAttributeAttribute.cs
- Preprocessor.cs
- Properties.cs
- BaseCodePageEncoding.cs
- DataSourceExpressionCollection.cs
- IDispatchConstantAttribute.cs
- validationstate.cs
- ArrayList.cs
- DataListItemEventArgs.cs