FixedDocument.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Documents / FixedDocument.cs / 1305600 / FixedDocument.cs

                            //---------------------------------------------------------------------------- 
// 
//      Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
// 
// 
// Description:
//      Implements the FixedDocument element 
// 
// History:
//      06/03/2003 - Zhenbin Xu (ZhenbinX) - Created. 
//      03/02/2004 - Zhenbin Xu (ZhenbinX) - Page-Per-Stream
//
// http://edocs/payloads/Payloads%20Features/FixedPage%20changes.mht
// 
//---------------------------------------------------------------------------
namespace System.Windows.Documents 
{ 
    using MS.Internal;                  // DoubleUtil
    using MS.Internal.Documents; 
    using MS.Utility;                   // ExceptionStringTable
    using MS.Internal.Utility;
    using System.Windows.Threading;     // Dispatcher
    using System.Windows;               // DependencyID etc. 
    using System.Windows.Automation.Peers;    // AutomationPeer
    using System.Windows.Documents;     // DocumentPaginator 
    using System.Windows.Documents.DocumentStructures; 
    using System.Windows.Media;         // Visual
    using System.Windows.Markup; // IAddChild, ContentPropertyAttribute 
    using System.Windows.Shapes;        // Glyphs
    using System;
    using System.IO;
    using System.IO.Packaging; 
    using System.Net;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.ComponentModel;        // DesignerSerializationVisibility
    using System.Diagnostics; 
    using System.Globalization;
    using System.Runtime.Serialization.Formatters.Binary;
    using MS.Internal.Annotations.Component;
    using System.Windows.Navigation; 
    using System.Windows.Controls;
    using System.Text; 
    using MS.Internal.IO.Packaging; 
    using System.Security;
    using System.Security.Permissions; 

    //=====================================================================
    /// 
    /// FixedDocument is the spine of a portable, high fidelity fixed-format 
    /// document, where the pages are stitched together. The FixedDocument
    /// elements provides and formats pages as requested. It also provides 
    /// a Text OM on top of the fixed-format document to allow for read-only 
    /// editing (selection, keyboard navigation, find, etc.).
    ///  
    [ContentProperty("Pages")]
    public class FixedDocument : FrameworkContentElement, IDocumentPaginatorSource, IAddChildInternal, IServiceProvider, IFixedNavigate, IUriContext
    {
        //------------------------------------------------------------------- 
        //
        // Constructors 
        // 
        //----------------------------------------------------------------------
 
        #region Constructors

        static FixedDocument()
        { 
            FocusableProperty.OverrideMetadata(typeof(FixedDocument), new FrameworkPropertyMetadata(true));
            NavigationService.NavigationServiceProperty.OverrideMetadata( 
                        typeof(FixedDocument), 
                        new FrameworkPropertyMetadata(new PropertyChangedCallback(FixedHyperLink.OnNavigationServiceChanged)));
 
        }

        /// 
        ///     Default FixedDocument constructor 
        /// 
        ///  
        ///     Automatic determination of current UIContext. Use alternative constructor 
        ///     that accepts a UIContext for best performance.
        ///  
        public FixedDocument()
            : base()
        {
            _Init(); 
        }
        #endregion Constructors 
 
        //-------------------------------------------------------------------
        // 
        // Public Methods
        //
        //----------------------------------------------------------------------
 
        #region IServiceProvider Members
 
        ///  
        /// Returns service objects associated with this control.
        ///  
        /// 
        /// FixedDocument currently supports TextContainer.
        /// 
        /// serviceType is NULL. 
        /// 
        /// Specifies the type of service object to get. 
        ///  
        object IServiceProvider.GetService(Type serviceType)
        { 
//             Dispatcher.VerifyAccess();
            if (serviceType == null)
            {
                throw new ArgumentNullException("serviceType"); 
            }
 
            if (serviceType == typeof(ITextContainer)) 
            {
                return this.FixedContainer; 
            }

            if (serviceType == typeof(RubberbandSelector))
            { 
                // create this on demand, but not through the property, only through the
                // service, so it is only created when it's actually used 
                if (_rubberbandSelector == null) 
                {
                    _rubberbandSelector = new RubberbandSelector(); 
                }
                return _rubberbandSelector;
            }
 
            return null;
        } 
        #endregion IServiceProvider Members 

        #region IAddChild 
        ///
        /// Called to Add the object as a Child.
        ///
        /// value is NULL. 
        /// value is not of type PageContent.
        /// A PageContent cannot be added while previous partial page isn't completely Loaded. 
        /// 
        /// Object to add as a child
        /// 
        void IAddChild.AddChild(Object value)
        {
            if (value == null)
            { 
                throw new ArgumentNullException("value");
            } 
 
//             Dispatcher.VerifyAccess();
 
            PageContent fp = value as PageContent;

            if (fp == null)
            { 
                throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(PageContent)), "value");
            } 
 
            if (fp.IsInitialized)
            { 
                _pages.Add(fp);
            }
            else
            { 
                DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("Page {0} Deferred", _pages.Count));
                if (_partialPage == null) 
                { 
                    _partialPage = fp;
                    _partialPage.ChangeLogicalParent(this); 
                    _partialPage.Initialized += new EventHandler(OnPageLoaded);
                }
                else
                { 
                    throw new InvalidOperationException(SR.Get(SRID.PrevoiusPartialPageContentOutstanding));
                } 
            } 
        }
 
        ///
        /// Called when text appears under the tag in markup
        ///
        /// 
        /// Text to Add to the Object
        /// 
        ///  
        void IAddChild.AddText(string text)
        { 
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);
        }
        #endregion
 
        #region IUriContext
        ///  
        ///  
        /// 
        Uri IUriContext.BaseUri 
        {
            get { return (Uri) GetValue(BaseUriHelper.BaseUriProperty); }
            set { SetValue(BaseUriHelper.BaseUriProperty, value); }
        } 
        #endregion IUriContext
 
        #region IFixedNavigate 
        void IFixedNavigate.NavigateAsync(string elementID)
        { 
            if (IsPageCountValid == true)
            {
                FixedHyperLink.NavigateToElement(this, elementID);
            } 
            else
            { 
                _navigateAfterPagination = true; 
                _navigateFragment = elementID;
            } 
        }

        UIElement IFixedNavigate.FindElementByID(string elementID, out FixedPage rootFixedPage)
        { 
            UIElement uiElementRet = null;
            rootFixedPage = null; 
 
            if (Char.IsDigit(elementID[0]))
            { 
                //
                //We convert string to a page number here.
                //
                int pageNumber = Convert.ToInt32(elementID, CultureInfo.InvariantCulture); 

                // 
                // Metro defines all external page are 1 based. All internals are 0 based. 
                //
                pageNumber --; 

                uiElementRet = GetFixedPage(pageNumber);
                rootFixedPage = GetFixedPage(pageNumber);
            } 
            else
            { 
                // 
                // We need iterate through the PageContentCollect first.
                // 
                PageContentCollection pc = this.Pages;
                PageContent pageContent;
                FixedPage fixedPage;
 
                for (int i = 0, n = pc.Count; i < n; i++)
                { 
                    pageContent = pc[i]; 
                    //
                    // If PageStream is non null, it is not PPS. Otherwise, need to check LinkTargets collection 
                    // of PageContent
                    //
                    if (pageContent.PageStream != null)
                    { 
                        fixedPage = GetFixedPage(i);
                        if (fixedPage != null) 
                        { 
                            uiElementRet = ((IFixedNavigate)fixedPage).FindElementByID(elementID, out rootFixedPage);
                            if (uiElementRet != null) 
                            {
                                break;
                            }
                        } 
                    }
                    else 
                    { 
                        if (pageContent.ContainsID(elementID))
                        { 
                            fixedPage = GetFixedPage(i);
                            if (fixedPage != null)
                            {
                                uiElementRet = ((IFixedNavigate)fixedPage).FindElementByID(elementID, out rootFixedPage); 
                                if (uiElementRet == null)
                                { // return that page if we can't find the named fragment 
                                    uiElementRet = fixedPage; 
                                }
                                // 
                                // we always break here because pageContent include the named fragment
                                //
                                break;
                            } 
                        }
                    } 
                } 

            } 

            return uiElementRet;

        } 

        internal NavigationService NavigationService 
        { 
            get { return (NavigationService) GetValue(NavigationService.NavigationServiceProperty); }
            set { SetValue(NavigationService.NavigationServiceProperty, value); } 
        }

        #endregion
 
        #region LogicalTree
        ///  
        /// Returns enumerator to logical children 
        /// 
        protected internal override IEnumerator LogicalChildren 
        {
            get
            {
//                 this.Dispatcher.VerifyAccess(); 
                return this.Pages.GetEnumerator();
            } 
        } 
        #endregion LogicalTree
 
        #region IDocumentPaginatorSource Members

        /// 
        /// An object which paginates content. 
        /// 
        public DocumentPaginator DocumentPaginator 
        { 
            get { return _paginator; }
        } 

        #endregion IDocumentPaginatorSource Members

        #region Document Overrides 

        ///  
        ///  
        /// 
        /// pageNumber is less than zero. 
        /// 
        /// The page number.
        /// 
        internal DocumentPage GetPage(int pageNumber) 
        {
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.GetPage({0})", pageNumber)); 
 
            // Make sure that the call is in the right context.
//             Dispatcher.VerifyAccess(); 

            // Page number cannot be negative.
            if (pageNumber < 0)
            { 
                throw new ArgumentOutOfRangeException("pageNumber", SR.Get(SRID.IDPNegativePageNumber));
            } 
 
            if (pageNumber < Pages.Count)
            { 
                //
                // If we are not out of bound, try next page
                //
                FixedPage page = SyncGetPage(pageNumber, false/*forceReload*/); 

                if (page == null) 
                { 
                    return DocumentPage.Missing;
                } 

                Debug.Assert(page != null);
                Size fixedSize = ComputePageSize(page);
 
                // Always measure with fixed size instead of using constraint
                FixedDocumentPage dp = new FixedDocumentPage(this, page, fixedSize, pageNumber); 
 
                page.Measure(fixedSize);
                page.Arrange(new Rect(new Point(), fixedSize)); 

                return dp;
            }
 
            return DocumentPage.Missing;
        } 
 
        /// 
        ///  
        /// 
        /// pageNumber is less than zero.
        /// userState is NULL.
        internal void GetPageAsync(int pageNumber, object userState) 
        {
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.GetPageAsync({0}, {1})", pageNumber, userState)); 
 
            // Make sure that the call is in the right context.
//             Dispatcher.VerifyAccess(); 

            // Page number cannot be negative.
            if (pageNumber < 0)
            { 
                throw new ArgumentOutOfRangeException("pageNumber", SR.Get(SRID.IDPNegativePageNumber));
            } 
 
            if (userState == null)
            { 
                throw new ArgumentNullException("userState");
            }

            if (pageNumber < Pages.Count) 
            {
                PageContent pc = Pages[pageNumber]; 
 
                // Add to outstanding AsyncOp list
                GetPageAsyncRequest asyncRequest = new GetPageAsyncRequest(pc, pageNumber, userState); 
                _asyncOps[userState] = asyncRequest;

                DispatcherOperationCallback queueTask = new DispatcherOperationCallback(GetPageAsyncDelegate);
                Dispatcher.BeginInvoke(DispatcherPriority.Background, queueTask, asyncRequest); 
            }
            else 
            { 
                _NotifyGetPageAsyncCompleted(DocumentPage.Missing, pageNumber, null, false, userState);
            } 
        }

        /// 
        ///  
        /// 
        /// contentPosition is NULL. 
        /// ContentPosition does not exist within this element?s tree. 
        internal int GetPageNumber(ContentPosition contentPosition)
        { 
//             Dispatcher.VerifyAccess();

            if (contentPosition == null)
            { 
                throw new ArgumentNullException("contentPosition");
            } 
 
            FixedTextPointer fixedTextPointer = contentPosition as FixedTextPointer;
            if (fixedTextPointer == null) 
            {
                throw new ArgumentException(SR.Get(SRID.IDPInvalidContentPosition));
            }
 
            return fixedTextPointer.FixedTextContainer.GetPageNumber(fixedTextPointer);
        } 
 
        /// 
        ///  
        /// 
        /// userState is NULL.
        internal void CancelAsync(object userState)
        { 
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.GetPageAsyncCancel([{0}])", userState));
//             Dispatcher.VerifyAccess(); 
 
            if (userState == null)
            { 
                throw new ArgumentNullException("userState");
            }

            GetPageAsyncRequest asyncRequest; 
            if (_asyncOps.TryGetValue(userState,out asyncRequest))
            { 
                if (asyncRequest != null) 
                {
                    asyncRequest.Cancelled = true; 
                    asyncRequest.PageContent.GetPageRootAsyncCancel();
                }
            }
        } 

        ///  
        ///  
        /// 
        /// element is NULL. 
        internal ContentPosition GetObjectPosition(Object o)
        {
            if (o == null)
            { 
                throw new ArgumentNullException("o");
            } 
 
            DependencyObject element = o as DependencyObject;
 
            if (element == null)
            {
                throw new ArgumentException(SR.Get(SRID.FixedDocumentExpectsDependencyObject));
            } 
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDF.GetContentPositionForElement({0})", element));
            // Make sure that the call is in the right context. 
//             Dispatcher.VerifyAccess(); 

 
            // walk up the logical parent chain to find the containing page
            FixedPage fixedPage = null;
            int pageIndex = -1;
            if (element != this) 
            {
                DependencyObject el = element; 
                while (el != null) 
                {
                    fixedPage = el as FixedPage; 

                    if (fixedPage != null)
                    {
                        pageIndex = GetIndexOfPage(fixedPage); 
                        if (pageIndex >= 0)
                        { 
                            break; 
                        }
                        el = fixedPage.Parent; 
                    }
                    else
                    {
                        el = LogicalTreeHelper.GetParent(el); 
                    }
                } 
            } 
            else if (this.Pages.Count > 0)
            { 
                // if FixedDocument is requested, return ContentPosition for the first page.
                pageIndex = 0;
            }
 
            // get FixedTextPointer for element or page index
            FixedTextPointer fixedTextPointer = null; 
            if (pageIndex >= 0) 
            {
                FixedPosition fixedPosition; 
                FlowPosition flowPosition=null;
                System.Windows.Shapes.Path p = element as System.Windows.Shapes.Path;
                if (element is Glyphs || element is Image || (p != null &&  p.Fill is ImageBrush))
                { 
                    fixedPosition = new FixedPosition(fixedPage.CreateFixedNode(pageIndex, (UIElement)element), 0);
                    flowPosition = FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition); 
                } 
                if (flowPosition == null)
                { 
                    flowPosition = FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(pageIndex);
                }
                fixedTextPointer = new FixedTextPointer(true, LogicalDirection.Forward, flowPosition);
            } 

            return (fixedTextPointer != null) ? fixedTextPointer : ContentPosition.Missing; 
        } 

 
        /// 
        /// 
        /// 
        internal ContentPosition GetPagePosition(DocumentPage page) 
        {
            FixedDocumentPage docPage = page as FixedDocumentPage; 
            if (docPage == null) 
            {
                return ContentPosition.Missing; 
            }
            return docPage.ContentPosition;
        }
 
        /// 
        ///  
        ///  
        internal bool IsPageCountValid { get { return this.IsInitialized; } }
 
        /// 
        /// 
        /// 
        internal int PageCount { get { return Pages.Count; } } 

        ///  
        ///  
        /// 
        internal Size PageSize 
        {
            get { return new Size(_pageWidth, _pageHeight); }
            set { _pageWidth = value.Width; _pageHeight = value.Height; }
        } 

        internal bool HasExplicitStructure 
        {
 
            get
            { 
                return _hasExplicitStructure;
            }
        }
 
        #endregion Document Overrides
 
        //-------------------------------------------------------------- ------ 
        //
        // Public Properties 
        //
        //---------------------------------------------------------------------

        #region Public Properties 

        ///  
        /// Get a collection of PageContent that this FixedDocument contains. 
        /// 
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content)] 
        public PageContentCollection Pages
        {
            get
            { 
                return _pages;
            } 
        } 

        ///  
        ///
        /// 
        public static readonly DependencyProperty PrintTicketProperty
            = DependencyProperty.RegisterAttached("PrintTicket", typeof(object), typeof(FixedDocument), 
                                                  new FrameworkPropertyMetadata((object)null));
 
        ///  
        /// Get/Set PrintTicket Property
        ///  
        public object PrintTicket
        {
            get
            { 
                object printTicket = GetValue(PrintTicketProperty);
                return printTicket; 
            } 
            set
            { 
                SetValue(PrintTicketProperty,value);
            }
        }
 
        #endregion Public Properties
 
        //-------------------------------------------------------------------- 
        //
        // Protected Methods 
        //
        //---------------------------------------------------------------------

        #region Protected Methods 

        ///  
        /// Creates AutomationPeer () 
        /// 
        protected override AutomationPeer OnCreateAutomationPeer() 
        {
            return new DocumentAutomationPeer(this);
        }
 
        #endregion Protected Methods
 
        //------------------------------------------------------------------- 
        //
        // Internal Methods 
        //
        //---------------------------------------------------------------------

        #region Internal Methods 
        internal int GetIndexOfPage(FixedPage p)
        { 
            PageContentCollection pc = this.Pages; 
            for (int i = 0, n = pc.Count; i < n; i++)
            { 
                if (pc[i].IsOwnerOf(p))
                {
                    return i;
                } 
            }
            return -1; 
        } 

 
        internal bool IsValidPageIndex(int index)
        {
            return (index >= 0 && index < this.Pages.Count);
        } 

 
        // Check index before trying to load page 
        internal FixedPage SyncGetPageWithCheck(int index)
        { 
            if (IsValidPageIndex(index))
            {
                return SyncGetPage(index, false /*forceReload*/);
            } 
            DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("SyncGetPageWithCheck {0} is invalid page", index));
            return null; 
        } 

 

        // Assumes index is valid
        internal FixedPage SyncGetPage(int index, bool forceReload)
        { 
            DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("SyncGetPage {0}", index));
            Debug.Assert(IsValidPageIndex(index)); 
 
            PageContentCollection pc = this.Pages;
            FixedPage fp; 

            try
            {
                fp = (FixedPage)pc[index].GetPageRoot(forceReload); 
            }
            catch (Exception e) 
            { 
                if (e is InvalidOperationException || e is ApplicationException)
                { 
                    ApplicationException ae = new ApplicationException(string.Format(System.Globalization.CultureInfo.CurrentCulture, SR.Get(SRID.ExceptionInGetPage), index), e);
                    throw ae;
                }
                else 
                {
                    throw; 
                } 
            }
            return fp; 
        }

        /// 
        /// Callback when a new PageContent is added 
        /// 
        internal void OnPageContentAppended(int index) 
        { 
            FixedContainer.FixedTextBuilder.AddVirtualPage();
 
            _paginator.NotifyPaginationProgress(new PaginationProgressEventArgs(index, 1));

            if (this.IsInitialized)
            { 
                _paginator.NotifyPagesChanged(new PagesChangedEventArgs(index, 1));
            } 
        } 

        // 
        // Make sure page has its width and height.
        // If absoluteOnly is specified, it will overwrite relative size specified
        // on page with default page size.
        // 
        internal void EnsurePageSize(FixedPage fp)
        { 
            Debug.Assert(fp != null); 

            double width = fp.Width; 

            if (DoubleUtil.IsNaN(width))
            {
                fp.Width = _pageWidth; 
            }
 
            double height = fp.Height; 

            if (DoubleUtil.IsNaN(height)) 
            {
                fp.Height = _pageHeight;
            }
        } 

        // Note: This code is specifically written for PageViewer. 
        // Once PageViewer get away from inquring page size before 
        // displaying page, we should remove this function.
        internal bool GetPageSize(ref Size pageSize, int pageNumber) 
        {
            DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("GetPageSize {0}", pageNumber));
            if (pageNumber < Pages.Count)
            { 
                // NOTE: it is wrong to call this method when page is outstanding.
                // Unfortunately PageViewer + DocumentPaginator still is dependent on 
                // PageSize, so have to avoid throwing exception in this situation. 

                FixedPage p = null; 
                if (!_pendingPages.Contains(Pages[pageNumber]))
                {
                    p = SyncGetPage(pageNumber, false /*forceReload*/);
                } 
#if DEBUG
                else 
                { 
                    DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("====== GetPageSize {0}  Warning [....] call made while async outstanding =====", pageNumber));
                } 
#endif


                // ComputePageSize will return appropriate value for null page 
                pageSize = ComputePageSize(p);
 
                return true; 
            }
 
            return false;
        }

 
        //
        // Get absolute page size. If relative page size is specified 
        // in the page, it will be overwritten by default page size, 
        // which is absolute size.
        // 
        internal Size ComputePageSize(FixedPage fp)
        {
            if (fp == null)
            { 
                return new Size(_pageWidth, _pageHeight);
            } 
            EnsurePageSize(fp); 
            return new Size(fp.Width, fp.Height);
        } 

        #endregion Internal Methods

        //-------------------------------------------------------------------- 
        //
        // Internal Properties 
        // 
        //---------------------------------------------------------------------
 
        #region Internal Properties

        // expose the hosted FixedContainer
        internal FixedTextContainer FixedContainer 
        {
            get 
            { 
                if (_fixedTextContainer == null)
                { 
                    _fixedTextContainer = new FixedTextContainer(this);
                    _fixedTextContainer.Highlights.Changed += new HighlightChangedEventHandler(OnHighlightChanged);
                }
                return _fixedTextContainer; 
            }
        } 
 
        internal Dictionary Highlights
        { 
            get
            {
                return _highlights;
            } 
        }
 
        internal DocumentReference DocumentReference 
        {
            get 
            {
                return _documentReference;
            }
            set 
            {
                _documentReference = value; 
            } 
        }
 
        #endregion Internal Properties


        //-------------------------------------------------------------------- 
        //
        // Private Methods 
        // 
        //----------------------------------------------------------------------
 
        #region Private Methods
        //---------------------------------------
        // Initialization
        //--------------------------------------- 
        private void _Init()
        { 
            _paginator = new FixedDocumentPaginator(this); 
            _pages = new PageContentCollection(this);
            _highlights = new Dictionary(); 
            _asyncOps = new Dictionary();
            _pendingPages = new List();
            _hasExplicitStructure = false;
            this.Initialized += new EventHandler(OnInitialized); 
        }
 
 
        private void OnInitialized(object sender, EventArgs e)
        { 
            if (_navigateAfterPagination)
            {
                FixedHyperLink.NavigateToElement(this, _navigateFragment);
                _navigateAfterPagination = false; 
            }
 
            //Currently we don't load the DocumentStructure part 
            //At least we need to validate if it's there
            ValidateDocStructure(); 

            if (PageCount > 0)
            {
                DocumentPage docPage = GetPage(0); 
                if (docPage != null)
                { 
                    FixedPage page = docPage.Visual as FixedPage; 
                    if (page != null)
                    { 
                        this.Language = page.Language;
                    }
                }
            } 

            _paginator.NotifyPaginationCompleted(e); 
        } 

        internal void ValidateDocStructure() 
        {
            Uri baseUri = BaseUriHelper.GetBaseUri(this);

            if (baseUri.Scheme.Equals(PackUriHelper.UriSchemePack, StringComparison.OrdinalIgnoreCase)) 
            {
                // avoid the case of pack://application,,, 
                if (baseUri.Host.Equals(BaseUriHelper.PackAppBaseUri.Host) != true && 
                    baseUri.Host.Equals(BaseUriHelper.SiteOfOriginBaseUri.Host) != true)
                { 
                    Uri structureUri = GetStructureUriFromRelationship(baseUri, _structureRelationshipName);
                    if (structureUri != null)
                    {
                        ContentType mimeType; 
                        ValidateAndLoadPartFromAbsoluteUri(structureUri, true, "DocumentStructure", out mimeType);
                        if (!_documentStructureContentType.AreTypeAndSubTypeEqual(mimeType)) 
                        { 
                            throw new FileFormatException(SR.Get(SRID.InvalidDSContentType));
                        } 
                        _hasExplicitStructure = true;
                    }
                }
            } 
        }
 
 
        internal static StoryFragments GetStoryFragments(FixedPage fixedPage)
        { 
            object o = null;

            Uri baseUri = BaseUriHelper.GetBaseUri(fixedPage);
 
            if (baseUri.Scheme.Equals(PackUriHelper.UriSchemePack, StringComparison.OrdinalIgnoreCase))
            { 
                // avoid the case of pack://application,,, 
                if (baseUri.Host.Equals(BaseUriHelper.PackAppBaseUri.Host) != true &&
                    baseUri.Host.Equals(BaseUriHelper.SiteOfOriginBaseUri.Host) != true) 
                {
                    Uri structureUri = GetStructureUriFromRelationship(baseUri, _storyFragmentsRelationshipName);

                    if (structureUri != null) 
                    {
                        ContentType mimeType; 
                        o = ValidateAndLoadPartFromAbsoluteUri(structureUri, false, null, out mimeType); 
                        if (!_storyFragmentsContentType.AreTypeAndSubTypeEqual(mimeType))
                        { 
                            throw new FileFormatException(SR.Get(SRID.InvalidSFContentType));
                        }
                        if (!(o is StoryFragments))
                        { 
                            throw new FileFormatException(SR.Get(SRID.InvalidStoryFragmentsMarkup));
                        } 
                    } 
                }
            } 

            return o as StoryFragments;
        }
 

        private static object ValidateAndLoadPartFromAbsoluteUri(Uri AbsoluteUriDoc, bool validateOnly, string rootElement, out ContentType mimeType) 
        { 
            mimeType = null;
            Stream pageStream = null; 
            object o = null;

            try
            { 
                pageStream = WpfWebRequestHelper.CreateRequestAndGetResponseStream(AbsoluteUriDoc, out mimeType);
 
                ParserContext pc = new ParserContext(); 
                pc.BaseUri = AbsoluteUriDoc;
 
                XpsValidatingLoader loader = new XpsValidatingLoader();
                if (validateOnly)
                {
                    loader.Validate(pageStream, null, pc, mimeType, rootElement); 
                }
                else 
                { 
                    o = loader.Load(pageStream, null, pc, mimeType);
                } 
            }
            catch (Exception e)
            {
                //System.Net.WebException will be thrown when the document structure does not exist in a non-container 
                //and System.InvalidOperation will be thrown when calling Package.GetPart() in a container.
                //We ignore these but all others need to be rethrown 
                if (!(e is System.Net.WebException || e is System.InvalidOperationException)) 
                {
                    throw; 
                }
            }
            return o;
        } 

         ///  
        /// Retrieves the Uri for the DocumentStructure from the container's relationship 
        /// 
        ///  
        /// Critical: Accesses a package from PreloadedPackages
        /// SecurityTreatAsSafe: No package instance or package related objects being handed out
        ///             from this method
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        static private Uri GetStructureUriFromRelationship(Uri contentUri, string relationshipName) 
        { 
            Uri absTargetUri = null;
            if (contentUri != null && relationshipName != null) 
            {
                Uri partUri = PackUriHelper.GetPartUri(contentUri);
                if (partUri != null)
                { 
                    Uri packageUri = PackUriHelper.GetPackageUri(contentUri);
                    Package package = PreloadedPackages.GetPackage(packageUri); 
 
                    if (package == null)
                    { 
                        if (SecurityHelper.CheckEnvironmentPermission())
                        {
                            package = PackageStore.GetPackage(packageUri);
                        } 
                    }
 
                    if (package != null) 
                    {
                        PackagePart part = package.GetPart(partUri); 
                        PackageRelationshipCollection resources = part.GetRelationshipsByType(relationshipName);

                        Uri targetUri = null;
                        foreach (PackageRelationship relationShip in resources) 
                        {
                            targetUri = PackUriHelper.ResolvePartUri(partUri, relationShip.TargetUri); 
                        } 

                        if (targetUri != null) 
                        {
                            absTargetUri = PackUriHelper.Create(packageUri, targetUri);
                        }
                    } 
                }
            } 
            return absTargetUri; 
        }
 
        private void OnPageLoaded(object sender, EventArgs e)
        {
            PageContent pc = (PageContent)sender;
            if (pc == _partialPage) 
            {
                DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("Loaded Page {0}", _pages.Count)); 
                _partialPage.Initialized -= new EventHandler(OnPageLoaded); 
                _pages.Add(_partialPage);
                _partialPage = null; 
            }
        }

        internal FixedPage GetFixedPage(int pageNumber) 
        {
            FixedPage fp = null; 
            FixedDocumentPage fdp = GetPage(pageNumber) as FixedDocumentPage; 
            if (fdp != null && fdp != DocumentPage.Missing)
            { 
                fp = fdp.FixedPage;
            }
            return fp;
        } 

        //--------------------------------------- 
        // Text Editing 
        //---------------------------------------
        private void OnHighlightChanged(object sender, HighlightChangedEventArgs args) 
        {
            Debug.Assert(sender != null);
            Debug.Assert(args != null);
            Debug.Assert(args.Ranges != null); 

            DocumentsTrace.FixedTextOM.Highlight.Trace(string.Format("HightlightMoved From {0}-{1} To {2}-{3}",0, 0, 0, 0)); 
            Debug.Assert(args.Ranges.Count > 0 && ((TextSegment)args.Ranges[0]).Start.CompareTo(((TextSegment)args.Ranges[0]).End) < 0); 

            // 



            // Add new highlights, if any 
            ITextContainer tc = this.FixedContainer;
            Highlights highlights = null; 
 
            // If this document is part of a FixedDocumentSequence, we should use
            // the highlights that have been set on the sequence. 
            FixedDocumentSequence parent = this.Parent as FixedDocumentSequence;
            if (parent != null)
                highlights = parent.TextContainer.Highlights;
            else 
                highlights = this.FixedContainer.Highlights;
 
            StaticTextPointer highlightTransitionPosition; 
            StaticTextPointer highlightRangeStart;
            object selected; 

            //Find out if any highlights have been removed. We need to invalidate those pages
            List oldHighlightPages = new List();
            foreach (FixedPage page in _highlights.Keys) 
            {
                oldHighlightPages.Add(page); 
            } 

            _highlights.Clear(); 

            highlightTransitionPosition = tc.CreateStaticPointerAtOffset(0);

            while (true) 
            {
                // Move to the next highlight start. 
                if (!highlights.IsContentHighlighted(highlightTransitionPosition, LogicalDirection.Forward)) 
                {
                    highlightTransitionPosition = highlights.GetNextHighlightChangePosition(highlightTransitionPosition, LogicalDirection.Forward); 

                    // No more highlights?
                    if (highlightTransitionPosition.IsNull)
                        break; 
                }
 
                // highlightTransitionPosition is at the start of a new highlight run. 
                // Get the highlight data.
                // NB: this code only recognizes typeof(TextSelection) + AnnotationHighlight. 
                // We should add code here to handle other properties: foreground/background/etc.
                selected = highlights.GetHighlightValue(highlightTransitionPosition, LogicalDirection.Forward, typeof(TextSelection));

                // Save the start position and find the end. 
                highlightRangeStart = highlightTransitionPosition;
 
                //placeholder for highlight type 
                FixedHighlightType fixedHighlightType = FixedHighlightType.None;
                Brush foreground = null; 
                Brush background = null;

                // Store the highlight.
                if (selected != DependencyProperty.UnsetValue) 
                {
                    //find next TextSelection change. 
                    //This is to skip AnnotationHighlight 
                    //change positions, since Annotation Highlight is invisible under TextSelection
                    do 
                    {
                        highlightTransitionPosition = highlights.GetNextHighlightChangePosition(highlightTransitionPosition, LogicalDirection.Forward);
                        Debug.Assert(!highlightTransitionPosition.IsNull, "Highlight start not followed by highlight end!");
                    } 
                    while (highlights.GetHighlightValue(highlightTransitionPosition, LogicalDirection.Forward, typeof(TextSelection)) != DependencyProperty.UnsetValue);
                    fixedHighlightType = FixedHighlightType.TextSelection; 
                    foreground = null; 
                    background = null;
                } 
                else
                {
                    //look for annotation highlight
                    AnnotationHighlightLayer.HighlightSegment highlightSegment = highlights.GetHighlightValue(highlightRangeStart, 
                        LogicalDirection.Forward, typeof(HighlightComponent)) as AnnotationHighlightLayer.HighlightSegment;
                    if (highlightSegment != null) 
                    { 
                        //this is a visible annotation highlight
                        highlightTransitionPosition = highlights.GetNextHighlightChangePosition(highlightTransitionPosition, LogicalDirection.Forward); 
                        Debug.Assert(!highlightTransitionPosition.IsNull, "Highlight start not followed by highlight end!");
                        fixedHighlightType = FixedHighlightType.AnnotationHighlight;
                        background = highlightSegment.Fill;
 
                    }
                } 
 
                //generate fixed highlight if a highlight was has been found
                if (fixedHighlightType != FixedHighlightType.None) 
                {
                    this.FixedContainer.GetMultiHighlights((FixedTextPointer)highlightRangeStart.CreateDynamicTextPointer(LogicalDirection.Forward),
                                                            (FixedTextPointer)highlightTransitionPosition.CreateDynamicTextPointer(LogicalDirection.Forward),
                                                           _highlights, fixedHighlightType, foreground, background); 

                } 
            } 

            ArrayList dirtyPages = new ArrayList(); 
            IList ranges = args.Ranges;

            // Find the dirty page
            for (int i = 0; i < ranges.Count; i++) 
            {
                TextSegment textSegment = (TextSegment)ranges[i]; 
                int startPage = this.FixedContainer.GetPageNumber(textSegment.Start); 
                int endPage =  this.FixedContainer.GetPageNumber(textSegment.End);
 
                for (int count = startPage; count <= endPage; count ++)
                {
                    if (dirtyPages.IndexOf(count) < 0)
                    { 
                        dirtyPages.Add(count);
                    } 
                } 
            }
 
            ICollection newHighlightPages = _highlights.Keys as ICollection;

            //Also dirty the pages that had highlights before but not anymore
            foreach (FixedPage page in oldHighlightPages) 
            {
                if (!newHighlightPages.Contains(page)) 
                { 
                    int pageNo = GetIndexOfPage(page);
                    Debug.Assert(pageNo >= 0 && pageNo=0 && pageNo < PageCount && dirtyPages.IndexOf(pageNo) < 0)
                    {
                        dirtyPages.Add(pageNo);
                    } 
                }
 
            } 
            dirtyPages.Sort();
 
            foreach (int i in dirtyPages)
            {
                HighlightVisual hv = HighlightVisual.GetHighlightVisual(SyncGetPage(i, false /*forceReload*/));
 
                if (hv != null)
                { 
                    hv.InvalidateHighlights(); 
                }
            } 
        }


        //--------------------------------------- 
        // IDP
        //--------------------------------------- 
 
        private object GetPageAsyncDelegate(object arg)
        { 
            GetPageAsyncRequest asyncRequest = (GetPageAsyncRequest)arg;
            PageContent pc = asyncRequest.PageContent;
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.GetPageAsyncDelegate {0}", Pages.IndexOf(pc)));
            // Initiate request for page if necessary 
            if (!_pendingPages.Contains(pc))
            { 
                _pendingPages.Add(pc); 
                // Initiate an async loading of the page
                pc.GetPageRootCompleted += new GetPageRootCompletedEventHandler(OnGetPageRootCompleted); 
                pc.GetPageRootAsync(false /*forceReload*/);
                if (asyncRequest.Cancelled)
                {
                    pc.GetPageRootAsyncCancel(); 
                }
            } 
            return null; 
        }
 

        private void OnGetPageRootCompleted(object sender, GetPageRootCompletedEventArgs args)
        {
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.OnGetPageRootCompleted {0}", Pages.IndexOf((PageContent)sender))); 
            // Mark this page as no longer pending
            PageContent pc = (PageContent)sender; 
            pc.GetPageRootCompleted -= new GetPageRootCompletedEventHandler(OnGetPageRootCompleted); 
            _pendingPages.Remove(pc);
 
            // Notify all outstanding request for this particular page
            ArrayList completedRequests = new ArrayList();
            IEnumerator> ienum = _asyncOps.GetEnumerator();
            try 
            {
                while (ienum.MoveNext()) 
                { 
                    GetPageAsyncRequest asyncRequest = ienum.Current.Value;
                    // Process any outstanding request for this PageContent 
                    if (asyncRequest.PageContent == pc)
                    {
                        completedRequests.Add(ienum.Current.Key);
                        DocumentPage result = DocumentPage.Missing; 
                        if (!asyncRequest.Cancelled)
                        { 
                            // Do synchronous measure since we have obtained the page 
                            if (!args.Cancelled && (args.Error == null))
                            { 
                                FixedPage c = (FixedPage)args.Result;
                                Size fixedSize = ComputePageSize(c);

//                              Measure / Arrange in GetVisual override of FixedDocumentPage, not here 
                                result = new FixedDocumentPage(this, c, fixedSize, Pages.IndexOf(pc));
                            } 
                        } 
                        // this could throw
                        _NotifyGetPageAsyncCompleted(result, asyncRequest.PageNumber, args.Error, asyncRequest.Cancelled, asyncRequest.UserState); 
                    }
                }
            }
            finally 
            {
                // Remove completed requests from current async ops list 
                foreach (Object userState in completedRequests) 
                {
                    _asyncOps.Remove(userState); 
                }
            }
        }
 

        // Notify the caller of IDFAsync.MeasurePageAsync 
        private void _NotifyGetPageAsyncCompleted(DocumentPage page, int pageNumber, Exception error, bool cancelled, object userState) 
        {
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP._NotifyGetPageAsyncCompleted {0} {1} {2} {3} {4}", page, pageNumber, error, cancelled, userState)); 
            _paginator.NotifyGetPageCompleted(new GetPageCompletedEventArgs(
                                               page,
                                               pageNumber,
                                               error, 
                                               cancelled,
                                               userState 
                                               )); 
        }
 

        #endregion Private Methods

        //------------------------------------------------------------------- 
        //
        // Private Properties 
        // 
        //----------------------------------------------------------------------
 

        //-------------------------------------------------------------------
        //
        // Private Fields 
        //
        //--------------------------------------------------------------------- 
 
        #region Private Fields
 
        private IDictionary _asyncOps;
        private IList _pendingPages;
        private PageContentCollection _pages;
        private PageContent _partialPage;       // the current partially loaded page. 
        private Dictionary _highlights;
        private double _pageWidth = 8.5 * 96.0d; 
        private double _pageHeight = 11 * 96.0d;     // default page size 
        private FixedTextContainer _fixedTextContainer;
        private RubberbandSelector _rubberbandSelector; 
        private bool _navigateAfterPagination = false ;
        private string _navigateFragment;
        private FixedDocumentPaginator _paginator;
        private DocumentReference _documentReference; 
        private bool _hasExplicitStructure;
 
        private const string _structureRelationshipName       = "http://schemas.microsoft.com/xps/2005/06/documentstructure"; 
        private const string _storyFragmentsRelationshipName  = "http://schemas.microsoft.com/xps/2005/06/storyfragments";
        private static readonly ContentType _storyFragmentsContentType = new ContentType("application/vnd.ms-package.xps-storyfragments+xml"); 
        private static readonly ContentType _documentStructureContentType = new ContentType("application/vnd.ms-package.xps-documentstructure+xml");

        // Caches the UIElement's DependencyObjectType
        private static DependencyObjectType UIElementType = DependencyObjectType.FromSystemTypeInternal(typeof(UIElement)); 
        #endregion Private Fields
 
 
        //-------------------------------------------------------------------
        // 
        // Nested Class
        //
        //----------------------------------------------------------------------
 
        #region Nested Class
        private class GetPageAsyncRequest 
        { 
            internal GetPageAsyncRequest(PageContent pageContent, int pageNumber, object userState)
            { 
                PageContent = pageContent;
                PageNumber = pageNumber;
                UserState = userState;
                Cancelled = false; 
            }
 
            internal PageContent PageContent; 
            internal int PageNumber;
            internal object UserState; 
            internal bool Cancelled;
        }
        #endregion Nested Class
    } 

    //===================================================================== 
    // 
    // FixedDocument's implemenation of DocumentPage
    // 
    internal sealed class FixedDocumentPage : DocumentPage, IServiceProvider
    {
        //--------------------------------------------------------------------
        // 
        // Ctors
        // 
        //---------------------------------------------------------------------- 

        #region Ctors 
        internal FixedDocumentPage(FixedDocument panel, FixedPage page, Size fixedSize, int index) :
            base(page, fixedSize, new Rect(fixedSize), new Rect(fixedSize))
        {
            Debug.Assert(panel != null && page != null); 
            _panel = panel;
            _page = page; 
            _index = index; 
        }
        #endregion Ctors; 


        //-------------------------------------------------------------------
        // 
        // Public  Methods
        // 
        //---------------------------------------------------------------------- 

        #region IServiceProvider 
        /// 
        /// Returns service objects associated with this control.
        /// 
        ///  
        /// FixedDocument currently supports TextView.
        ///  
        ///  
        /// Specifies the type of service object to get.
        ///  
        object IServiceProvider.GetService(Type serviceType)
        {
            if (serviceType == null)
            { 
                throw new ArgumentNullException("serviceType");
            } 
 
            if (serviceType == typeof(ITextView))
            { 
                return this.TextView;
            }

            return null; 
        }
        #endregion IServiceProvider 
 
        //-------------------------------------------------------------------
        // 
        // Public  Methods
        //
        //---------------------------------------------------------------------
 

        //------------------------------------------------------------------- 
        // 
        // Public  Properties
        // 
        //----------------------------------------------------------------------

        public override Visual Visual
        { 
            get
            { 
                if (!_layedOut) 
                {
                    _layedOut = true; 

                    UIElement e;
                    if ((e = ((object)base.Visual) as UIElement)!=null)
                    { 
                        e.Measure(base.Size);
                        e.Arrange(new Rect(base.Size)); 
                    } 
                }
                return base.Visual; 
            }
        }

        //------------------------------------------------------------------- 
        //
        // Internal Properties 
        // 
        //----------------------------------------------------------------------
        #region Internal Properties 

        internal ContentPosition ContentPosition
        {
            get 
            {
                FlowPosition flowPosition = _panel.FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(_index); 
                return new FixedTextPointer(true, LogicalDirection.Forward, flowPosition); 
            }
        } 

        internal FixedPage FixedPage
        {
            get 
            {
                return this._page; 
            } 
        }
 
        internal int PageIndex
        {
            get
            { 
                return this._panel.GetIndexOfPage(this._page);
            } 
        } 

        internal FixedTextView TextView 
        {
            get
            {
                if (_textView == null) 
                {
                    _textView = new FixedTextView(this); 
                } 
                return _textView;
            } 
        }

        internal FixedDocument Owner
        { 
            get
            { 
                return _panel; 
            }
        } 

        internal FixedTextContainer TextContainer
        {
            get 
            {
                return this._panel.FixedContainer; 
            } 
        }
 
        #endregion Internal Properties
        //--------------------------------------------------------------------
        //
        // Internal Event 
        //
        //--------------------------------------------------------------------- 
        //-------------------------------------------------------------------- 
        //
        // Private Fields 
        //
        //---------------------------------------------------------------------

        #region Private Fields 
        private readonly FixedDocument _panel;
        private readonly FixedPage _page; 
        private readonly int _index; 
        private bool _layedOut;
        // Text OM 
        private FixedTextView _textView;
        #endregion Private Fields
    }
 

 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
// 
//      Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
// 
// 
// Description:
//      Implements the FixedDocument element 
// 
// History:
//      06/03/2003 - Zhenbin Xu (ZhenbinX) - Created. 
//      03/02/2004 - Zhenbin Xu (ZhenbinX) - Page-Per-Stream
//
// http://edocs/payloads/Payloads%20Features/FixedPage%20changes.mht
// 
//---------------------------------------------------------------------------
namespace System.Windows.Documents 
{ 
    using MS.Internal;                  // DoubleUtil
    using MS.Internal.Documents; 
    using MS.Utility;                   // ExceptionStringTable
    using MS.Internal.Utility;
    using System.Windows.Threading;     // Dispatcher
    using System.Windows;               // DependencyID etc. 
    using System.Windows.Automation.Peers;    // AutomationPeer
    using System.Windows.Documents;     // DocumentPaginator 
    using System.Windows.Documents.DocumentStructures; 
    using System.Windows.Media;         // Visual
    using System.Windows.Markup; // IAddChild, ContentPropertyAttribute 
    using System.Windows.Shapes;        // Glyphs
    using System;
    using System.IO;
    using System.IO.Packaging; 
    using System.Net;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.ComponentModel;        // DesignerSerializationVisibility
    using System.Diagnostics; 
    using System.Globalization;
    using System.Runtime.Serialization.Formatters.Binary;
    using MS.Internal.Annotations.Component;
    using System.Windows.Navigation; 
    using System.Windows.Controls;
    using System.Text; 
    using MS.Internal.IO.Packaging; 
    using System.Security;
    using System.Security.Permissions; 

    //=====================================================================
    /// 
    /// FixedDocument is the spine of a portable, high fidelity fixed-format 
    /// document, where the pages are stitched together. The FixedDocument
    /// elements provides and formats pages as requested. It also provides 
    /// a Text OM on top of the fixed-format document to allow for read-only 
    /// editing (selection, keyboard navigation, find, etc.).
    ///  
    [ContentProperty("Pages")]
    public class FixedDocument : FrameworkContentElement, IDocumentPaginatorSource, IAddChildInternal, IServiceProvider, IFixedNavigate, IUriContext
    {
        //------------------------------------------------------------------- 
        //
        // Constructors 
        // 
        //----------------------------------------------------------------------
 
        #region Constructors

        static FixedDocument()
        { 
            FocusableProperty.OverrideMetadata(typeof(FixedDocument), new FrameworkPropertyMetadata(true));
            NavigationService.NavigationServiceProperty.OverrideMetadata( 
                        typeof(FixedDocument), 
                        new FrameworkPropertyMetadata(new PropertyChangedCallback(FixedHyperLink.OnNavigationServiceChanged)));
 
        }

        /// 
        ///     Default FixedDocument constructor 
        /// 
        ///  
        ///     Automatic determination of current UIContext. Use alternative constructor 
        ///     that accepts a UIContext for best performance.
        ///  
        public FixedDocument()
            : base()
        {
            _Init(); 
        }
        #endregion Constructors 
 
        //-------------------------------------------------------------------
        // 
        // Public Methods
        //
        //----------------------------------------------------------------------
 
        #region IServiceProvider Members
 
        ///  
        /// Returns service objects associated with this control.
        ///  
        /// 
        /// FixedDocument currently supports TextContainer.
        /// 
        /// serviceType is NULL. 
        /// 
        /// Specifies the type of service object to get. 
        ///  
        object IServiceProvider.GetService(Type serviceType)
        { 
//             Dispatcher.VerifyAccess();
            if (serviceType == null)
            {
                throw new ArgumentNullException("serviceType"); 
            }
 
            if (serviceType == typeof(ITextContainer)) 
            {
                return this.FixedContainer; 
            }

            if (serviceType == typeof(RubberbandSelector))
            { 
                // create this on demand, but not through the property, only through the
                // service, so it is only created when it's actually used 
                if (_rubberbandSelector == null) 
                {
                    _rubberbandSelector = new RubberbandSelector(); 
                }
                return _rubberbandSelector;
            }
 
            return null;
        } 
        #endregion IServiceProvider Members 

        #region IAddChild 
        ///
        /// Called to Add the object as a Child.
        ///
        /// value is NULL. 
        /// value is not of type PageContent.
        /// A PageContent cannot be added while previous partial page isn't completely Loaded. 
        /// 
        /// Object to add as a child
        /// 
        void IAddChild.AddChild(Object value)
        {
            if (value == null)
            { 
                throw new ArgumentNullException("value");
            } 
 
//             Dispatcher.VerifyAccess();
 
            PageContent fp = value as PageContent;

            if (fp == null)
            { 
                throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(PageContent)), "value");
            } 
 
            if (fp.IsInitialized)
            { 
                _pages.Add(fp);
            }
            else
            { 
                DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("Page {0} Deferred", _pages.Count));
                if (_partialPage == null) 
                { 
                    _partialPage = fp;
                    _partialPage.ChangeLogicalParent(this); 
                    _partialPage.Initialized += new EventHandler(OnPageLoaded);
                }
                else
                { 
                    throw new InvalidOperationException(SR.Get(SRID.PrevoiusPartialPageContentOutstanding));
                } 
            } 
        }
 
        ///
        /// Called when text appears under the tag in markup
        ///
        /// 
        /// Text to Add to the Object
        /// 
        ///  
        void IAddChild.AddText(string text)
        { 
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);
        }
        #endregion
 
        #region IUriContext
        ///  
        ///  
        /// 
        Uri IUriContext.BaseUri 
        {
            get { return (Uri) GetValue(BaseUriHelper.BaseUriProperty); }
            set { SetValue(BaseUriHelper.BaseUriProperty, value); }
        } 
        #endregion IUriContext
 
        #region IFixedNavigate 
        void IFixedNavigate.NavigateAsync(string elementID)
        { 
            if (IsPageCountValid == true)
            {
                FixedHyperLink.NavigateToElement(this, elementID);
            } 
            else
            { 
                _navigateAfterPagination = true; 
                _navigateFragment = elementID;
            } 
        }

        UIElement IFixedNavigate.FindElementByID(string elementID, out FixedPage rootFixedPage)
        { 
            UIElement uiElementRet = null;
            rootFixedPage = null; 
 
            if (Char.IsDigit(elementID[0]))
            { 
                //
                //We convert string to a page number here.
                //
                int pageNumber = Convert.ToInt32(elementID, CultureInfo.InvariantCulture); 

                // 
                // Metro defines all external page are 1 based. All internals are 0 based. 
                //
                pageNumber --; 

                uiElementRet = GetFixedPage(pageNumber);
                rootFixedPage = GetFixedPage(pageNumber);
            } 
            else
            { 
                // 
                // We need iterate through the PageContentCollect first.
                // 
                PageContentCollection pc = this.Pages;
                PageContent pageContent;
                FixedPage fixedPage;
 
                for (int i = 0, n = pc.Count; i < n; i++)
                { 
                    pageContent = pc[i]; 
                    //
                    // If PageStream is non null, it is not PPS. Otherwise, need to check LinkTargets collection 
                    // of PageContent
                    //
                    if (pageContent.PageStream != null)
                    { 
                        fixedPage = GetFixedPage(i);
                        if (fixedPage != null) 
                        { 
                            uiElementRet = ((IFixedNavigate)fixedPage).FindElementByID(elementID, out rootFixedPage);
                            if (uiElementRet != null) 
                            {
                                break;
                            }
                        } 
                    }
                    else 
                    { 
                        if (pageContent.ContainsID(elementID))
                        { 
                            fixedPage = GetFixedPage(i);
                            if (fixedPage != null)
                            {
                                uiElementRet = ((IFixedNavigate)fixedPage).FindElementByID(elementID, out rootFixedPage); 
                                if (uiElementRet == null)
                                { // return that page if we can't find the named fragment 
                                    uiElementRet = fixedPage; 
                                }
                                // 
                                // we always break here because pageContent include the named fragment
                                //
                                break;
                            } 
                        }
                    } 
                } 

            } 

            return uiElementRet;

        } 

        internal NavigationService NavigationService 
        { 
            get { return (NavigationService) GetValue(NavigationService.NavigationServiceProperty); }
            set { SetValue(NavigationService.NavigationServiceProperty, value); } 
        }

        #endregion
 
        #region LogicalTree
        ///  
        /// Returns enumerator to logical children 
        /// 
        protected internal override IEnumerator LogicalChildren 
        {
            get
            {
//                 this.Dispatcher.VerifyAccess(); 
                return this.Pages.GetEnumerator();
            } 
        } 
        #endregion LogicalTree
 
        #region IDocumentPaginatorSource Members

        /// 
        /// An object which paginates content. 
        /// 
        public DocumentPaginator DocumentPaginator 
        { 
            get { return _paginator; }
        } 

        #endregion IDocumentPaginatorSource Members

        #region Document Overrides 

        ///  
        ///  
        /// 
        /// pageNumber is less than zero. 
        /// 
        /// The page number.
        /// 
        internal DocumentPage GetPage(int pageNumber) 
        {
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.GetPage({0})", pageNumber)); 
 
            // Make sure that the call is in the right context.
//             Dispatcher.VerifyAccess(); 

            // Page number cannot be negative.
            if (pageNumber < 0)
            { 
                throw new ArgumentOutOfRangeException("pageNumber", SR.Get(SRID.IDPNegativePageNumber));
            } 
 
            if (pageNumber < Pages.Count)
            { 
                //
                // If we are not out of bound, try next page
                //
                FixedPage page = SyncGetPage(pageNumber, false/*forceReload*/); 

                if (page == null) 
                { 
                    return DocumentPage.Missing;
                } 

                Debug.Assert(page != null);
                Size fixedSize = ComputePageSize(page);
 
                // Always measure with fixed size instead of using constraint
                FixedDocumentPage dp = new FixedDocumentPage(this, page, fixedSize, pageNumber); 
 
                page.Measure(fixedSize);
                page.Arrange(new Rect(new Point(), fixedSize)); 

                return dp;
            }
 
            return DocumentPage.Missing;
        } 
 
        /// 
        ///  
        /// 
        /// pageNumber is less than zero.
        /// userState is NULL.
        internal void GetPageAsync(int pageNumber, object userState) 
        {
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.GetPageAsync({0}, {1})", pageNumber, userState)); 
 
            // Make sure that the call is in the right context.
//             Dispatcher.VerifyAccess(); 

            // Page number cannot be negative.
            if (pageNumber < 0)
            { 
                throw new ArgumentOutOfRangeException("pageNumber", SR.Get(SRID.IDPNegativePageNumber));
            } 
 
            if (userState == null)
            { 
                throw new ArgumentNullException("userState");
            }

            if (pageNumber < Pages.Count) 
            {
                PageContent pc = Pages[pageNumber]; 
 
                // Add to outstanding AsyncOp list
                GetPageAsyncRequest asyncRequest = new GetPageAsyncRequest(pc, pageNumber, userState); 
                _asyncOps[userState] = asyncRequest;

                DispatcherOperationCallback queueTask = new DispatcherOperationCallback(GetPageAsyncDelegate);
                Dispatcher.BeginInvoke(DispatcherPriority.Background, queueTask, asyncRequest); 
            }
            else 
            { 
                _NotifyGetPageAsyncCompleted(DocumentPage.Missing, pageNumber, null, false, userState);
            } 
        }

        /// 
        ///  
        /// 
        /// contentPosition is NULL. 
        /// ContentPosition does not exist within this element?s tree. 
        internal int GetPageNumber(ContentPosition contentPosition)
        { 
//             Dispatcher.VerifyAccess();

            if (contentPosition == null)
            { 
                throw new ArgumentNullException("contentPosition");
            } 
 
            FixedTextPointer fixedTextPointer = contentPosition as FixedTextPointer;
            if (fixedTextPointer == null) 
            {
                throw new ArgumentException(SR.Get(SRID.IDPInvalidContentPosition));
            }
 
            return fixedTextPointer.FixedTextContainer.GetPageNumber(fixedTextPointer);
        } 
 
        /// 
        ///  
        /// 
        /// userState is NULL.
        internal void CancelAsync(object userState)
        { 
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.GetPageAsyncCancel([{0}])", userState));
//             Dispatcher.VerifyAccess(); 
 
            if (userState == null)
            { 
                throw new ArgumentNullException("userState");
            }

            GetPageAsyncRequest asyncRequest; 
            if (_asyncOps.TryGetValue(userState,out asyncRequest))
            { 
                if (asyncRequest != null) 
                {
                    asyncRequest.Cancelled = true; 
                    asyncRequest.PageContent.GetPageRootAsyncCancel();
                }
            }
        } 

        ///  
        ///  
        /// 
        /// element is NULL. 
        internal ContentPosition GetObjectPosition(Object o)
        {
            if (o == null)
            { 
                throw new ArgumentNullException("o");
            } 
 
            DependencyObject element = o as DependencyObject;
 
            if (element == null)
            {
                throw new ArgumentException(SR.Get(SRID.FixedDocumentExpectsDependencyObject));
            } 
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDF.GetContentPositionForElement({0})", element));
            // Make sure that the call is in the right context. 
//             Dispatcher.VerifyAccess(); 

 
            // walk up the logical parent chain to find the containing page
            FixedPage fixedPage = null;
            int pageIndex = -1;
            if (element != this) 
            {
                DependencyObject el = element; 
                while (el != null) 
                {
                    fixedPage = el as FixedPage; 

                    if (fixedPage != null)
                    {
                        pageIndex = GetIndexOfPage(fixedPage); 
                        if (pageIndex >= 0)
                        { 
                            break; 
                        }
                        el = fixedPage.Parent; 
                    }
                    else
                    {
                        el = LogicalTreeHelper.GetParent(el); 
                    }
                } 
            } 
            else if (this.Pages.Count > 0)
            { 
                // if FixedDocument is requested, return ContentPosition for the first page.
                pageIndex = 0;
            }
 
            // get FixedTextPointer for element or page index
            FixedTextPointer fixedTextPointer = null; 
            if (pageIndex >= 0) 
            {
                FixedPosition fixedPosition; 
                FlowPosition flowPosition=null;
                System.Windows.Shapes.Path p = element as System.Windows.Shapes.Path;
                if (element is Glyphs || element is Image || (p != null &&  p.Fill is ImageBrush))
                { 
                    fixedPosition = new FixedPosition(fixedPage.CreateFixedNode(pageIndex, (UIElement)element), 0);
                    flowPosition = FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition); 
                } 
                if (flowPosition == null)
                { 
                    flowPosition = FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(pageIndex);
                }
                fixedTextPointer = new FixedTextPointer(true, LogicalDirection.Forward, flowPosition);
            } 

            return (fixedTextPointer != null) ? fixedTextPointer : ContentPosition.Missing; 
        } 

 
        /// 
        /// 
        /// 
        internal ContentPosition GetPagePosition(DocumentPage page) 
        {
            FixedDocumentPage docPage = page as FixedDocumentPage; 
            if (docPage == null) 
            {
                return ContentPosition.Missing; 
            }
            return docPage.ContentPosition;
        }
 
        /// 
        ///  
        ///  
        internal bool IsPageCountValid { get { return this.IsInitialized; } }
 
        /// 
        /// 
        /// 
        internal int PageCount { get { return Pages.Count; } } 

        ///  
        ///  
        /// 
        internal Size PageSize 
        {
            get { return new Size(_pageWidth, _pageHeight); }
            set { _pageWidth = value.Width; _pageHeight = value.Height; }
        } 

        internal bool HasExplicitStructure 
        {
 
            get
            { 
                return _hasExplicitStructure;
            }
        }
 
        #endregion Document Overrides
 
        //-------------------------------------------------------------- ------ 
        //
        // Public Properties 
        //
        //---------------------------------------------------------------------

        #region Public Properties 

        ///  
        /// Get a collection of PageContent that this FixedDocument contains. 
        /// 
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content)] 
        public PageContentCollection Pages
        {
            get
            { 
                return _pages;
            } 
        } 

        ///  
        ///
        /// 
        public static readonly DependencyProperty PrintTicketProperty
            = DependencyProperty.RegisterAttached("PrintTicket", typeof(object), typeof(FixedDocument), 
                                                  new FrameworkPropertyMetadata((object)null));
 
        ///  
        /// Get/Set PrintTicket Property
        ///  
        public object PrintTicket
        {
            get
            { 
                object printTicket = GetValue(PrintTicketProperty);
                return printTicket; 
            } 
            set
            { 
                SetValue(PrintTicketProperty,value);
            }
        }
 
        #endregion Public Properties
 
        //-------------------------------------------------------------------- 
        //
        // Protected Methods 
        //
        //---------------------------------------------------------------------

        #region Protected Methods 

        ///  
        /// Creates AutomationPeer () 
        /// 
        protected override AutomationPeer OnCreateAutomationPeer() 
        {
            return new DocumentAutomationPeer(this);
        }
 
        #endregion Protected Methods
 
        //------------------------------------------------------------------- 
        //
        // Internal Methods 
        //
        //---------------------------------------------------------------------

        #region Internal Methods 
        internal int GetIndexOfPage(FixedPage p)
        { 
            PageContentCollection pc = this.Pages; 
            for (int i = 0, n = pc.Count; i < n; i++)
            { 
                if (pc[i].IsOwnerOf(p))
                {
                    return i;
                } 
            }
            return -1; 
        } 

 
        internal bool IsValidPageIndex(int index)
        {
            return (index >= 0 && index < this.Pages.Count);
        } 

 
        // Check index before trying to load page 
        internal FixedPage SyncGetPageWithCheck(int index)
        { 
            if (IsValidPageIndex(index))
            {
                return SyncGetPage(index, false /*forceReload*/);
            } 
            DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("SyncGetPageWithCheck {0} is invalid page", index));
            return null; 
        } 

 

        // Assumes index is valid
        internal FixedPage SyncGetPage(int index, bool forceReload)
        { 
            DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("SyncGetPage {0}", index));
            Debug.Assert(IsValidPageIndex(index)); 
 
            PageContentCollection pc = this.Pages;
            FixedPage fp; 

            try
            {
                fp = (FixedPage)pc[index].GetPageRoot(forceReload); 
            }
            catch (Exception e) 
            { 
                if (e is InvalidOperationException || e is ApplicationException)
                { 
                    ApplicationException ae = new ApplicationException(string.Format(System.Globalization.CultureInfo.CurrentCulture, SR.Get(SRID.ExceptionInGetPage), index), e);
                    throw ae;
                }
                else 
                {
                    throw; 
                } 
            }
            return fp; 
        }

        /// 
        /// Callback when a new PageContent is added 
        /// 
        internal void OnPageContentAppended(int index) 
        { 
            FixedContainer.FixedTextBuilder.AddVirtualPage();
 
            _paginator.NotifyPaginationProgress(new PaginationProgressEventArgs(index, 1));

            if (this.IsInitialized)
            { 
                _paginator.NotifyPagesChanged(new PagesChangedEventArgs(index, 1));
            } 
        } 

        // 
        // Make sure page has its width and height.
        // If absoluteOnly is specified, it will overwrite relative size specified
        // on page with default page size.
        // 
        internal void EnsurePageSize(FixedPage fp)
        { 
            Debug.Assert(fp != null); 

            double width = fp.Width; 

            if (DoubleUtil.IsNaN(width))
            {
                fp.Width = _pageWidth; 
            }
 
            double height = fp.Height; 

            if (DoubleUtil.IsNaN(height)) 
            {
                fp.Height = _pageHeight;
            }
        } 

        // Note: This code is specifically written for PageViewer. 
        // Once PageViewer get away from inquring page size before 
        // displaying page, we should remove this function.
        internal bool GetPageSize(ref Size pageSize, int pageNumber) 
        {
            DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("GetPageSize {0}", pageNumber));
            if (pageNumber < Pages.Count)
            { 
                // NOTE: it is wrong to call this method when page is outstanding.
                // Unfortunately PageViewer + DocumentPaginator still is dependent on 
                // PageSize, so have to avoid throwing exception in this situation. 

                FixedPage p = null; 
                if (!_pendingPages.Contains(Pages[pageNumber]))
                {
                    p = SyncGetPage(pageNumber, false /*forceReload*/);
                } 
#if DEBUG
                else 
                { 
                    DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("====== GetPageSize {0}  Warning [....] call made while async outstanding =====", pageNumber));
                } 
#endif


                // ComputePageSize will return appropriate value for null page 
                pageSize = ComputePageSize(p);
 
                return true; 
            }
 
            return false;
        }

 
        //
        // Get absolute page size. If relative page size is specified 
        // in the page, it will be overwritten by default page size, 
        // which is absolute size.
        // 
        internal Size ComputePageSize(FixedPage fp)
        {
            if (fp == null)
            { 
                return new Size(_pageWidth, _pageHeight);
            } 
            EnsurePageSize(fp); 
            return new Size(fp.Width, fp.Height);
        } 

        #endregion Internal Methods

        //-------------------------------------------------------------------- 
        //
        // Internal Properties 
        // 
        //---------------------------------------------------------------------
 
        #region Internal Properties

        // expose the hosted FixedContainer
        internal FixedTextContainer FixedContainer 
        {
            get 
            { 
                if (_fixedTextContainer == null)
                { 
                    _fixedTextContainer = new FixedTextContainer(this);
                    _fixedTextContainer.Highlights.Changed += new HighlightChangedEventHandler(OnHighlightChanged);
                }
                return _fixedTextContainer; 
            }
        } 
 
        internal Dictionary Highlights
        { 
            get
            {
                return _highlights;
            } 
        }
 
        internal DocumentReference DocumentReference 
        {
            get 
            {
                return _documentReference;
            }
            set 
            {
                _documentReference = value; 
            } 
        }
 
        #endregion Internal Properties


        //-------------------------------------------------------------------- 
        //
        // Private Methods 
        // 
        //----------------------------------------------------------------------
 
        #region Private Methods
        //---------------------------------------
        // Initialization
        //--------------------------------------- 
        private void _Init()
        { 
            _paginator = new FixedDocumentPaginator(this); 
            _pages = new PageContentCollection(this);
            _highlights = new Dictionary(); 
            _asyncOps = new Dictionary();
            _pendingPages = new List();
            _hasExplicitStructure = false;
            this.Initialized += new EventHandler(OnInitialized); 
        }
 
 
        private void OnInitialized(object sender, EventArgs e)
        { 
            if (_navigateAfterPagination)
            {
                FixedHyperLink.NavigateToElement(this, _navigateFragment);
                _navigateAfterPagination = false; 
            }
 
            //Currently we don't load the DocumentStructure part 
            //At least we need to validate if it's there
            ValidateDocStructure(); 

            if (PageCount > 0)
            {
                DocumentPage docPage = GetPage(0); 
                if (docPage != null)
                { 
                    FixedPage page = docPage.Visual as FixedPage; 
                    if (page != null)
                    { 
                        this.Language = page.Language;
                    }
                }
            } 

            _paginator.NotifyPaginationCompleted(e); 
        } 

        internal void ValidateDocStructure() 
        {
            Uri baseUri = BaseUriHelper.GetBaseUri(this);

            if (baseUri.Scheme.Equals(PackUriHelper.UriSchemePack, StringComparison.OrdinalIgnoreCase)) 
            {
                // avoid the case of pack://application,,, 
                if (baseUri.Host.Equals(BaseUriHelper.PackAppBaseUri.Host) != true && 
                    baseUri.Host.Equals(BaseUriHelper.SiteOfOriginBaseUri.Host) != true)
                { 
                    Uri structureUri = GetStructureUriFromRelationship(baseUri, _structureRelationshipName);
                    if (structureUri != null)
                    {
                        ContentType mimeType; 
                        ValidateAndLoadPartFromAbsoluteUri(structureUri, true, "DocumentStructure", out mimeType);
                        if (!_documentStructureContentType.AreTypeAndSubTypeEqual(mimeType)) 
                        { 
                            throw new FileFormatException(SR.Get(SRID.InvalidDSContentType));
                        } 
                        _hasExplicitStructure = true;
                    }
                }
            } 
        }
 
 
        internal static StoryFragments GetStoryFragments(FixedPage fixedPage)
        { 
            object o = null;

            Uri baseUri = BaseUriHelper.GetBaseUri(fixedPage);
 
            if (baseUri.Scheme.Equals(PackUriHelper.UriSchemePack, StringComparison.OrdinalIgnoreCase))
            { 
                // avoid the case of pack://application,,, 
                if (baseUri.Host.Equals(BaseUriHelper.PackAppBaseUri.Host) != true &&
                    baseUri.Host.Equals(BaseUriHelper.SiteOfOriginBaseUri.Host) != true) 
                {
                    Uri structureUri = GetStructureUriFromRelationship(baseUri, _storyFragmentsRelationshipName);

                    if (structureUri != null) 
                    {
                        ContentType mimeType; 
                        o = ValidateAndLoadPartFromAbsoluteUri(structureUri, false, null, out mimeType); 
                        if (!_storyFragmentsContentType.AreTypeAndSubTypeEqual(mimeType))
                        { 
                            throw new FileFormatException(SR.Get(SRID.InvalidSFContentType));
                        }
                        if (!(o is StoryFragments))
                        { 
                            throw new FileFormatException(SR.Get(SRID.InvalidStoryFragmentsMarkup));
                        } 
                    } 
                }
            } 

            return o as StoryFragments;
        }
 

        private static object ValidateAndLoadPartFromAbsoluteUri(Uri AbsoluteUriDoc, bool validateOnly, string rootElement, out ContentType mimeType) 
        { 
            mimeType = null;
            Stream pageStream = null; 
            object o = null;

            try
            { 
                pageStream = WpfWebRequestHelper.CreateRequestAndGetResponseStream(AbsoluteUriDoc, out mimeType);
 
                ParserContext pc = new ParserContext(); 
                pc.BaseUri = AbsoluteUriDoc;
 
                XpsValidatingLoader loader = new XpsValidatingLoader();
                if (validateOnly)
                {
                    loader.Validate(pageStream, null, pc, mimeType, rootElement); 
                }
                else 
                { 
                    o = loader.Load(pageStream, null, pc, mimeType);
                } 
            }
            catch (Exception e)
            {
                //System.Net.WebException will be thrown when the document structure does not exist in a non-container 
                //and System.InvalidOperation will be thrown when calling Package.GetPart() in a container.
                //We ignore these but all others need to be rethrown 
                if (!(e is System.Net.WebException || e is System.InvalidOperationException)) 
                {
                    throw; 
                }
            }
            return o;
        } 

         ///  
        /// Retrieves the Uri for the DocumentStructure from the container's relationship 
        /// 
        ///  
        /// Critical: Accesses a package from PreloadedPackages
        /// SecurityTreatAsSafe: No package instance or package related objects being handed out
        ///             from this method
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        static private Uri GetStructureUriFromRelationship(Uri contentUri, string relationshipName) 
        { 
            Uri absTargetUri = null;
            if (contentUri != null && relationshipName != null) 
            {
                Uri partUri = PackUriHelper.GetPartUri(contentUri);
                if (partUri != null)
                { 
                    Uri packageUri = PackUriHelper.GetPackageUri(contentUri);
                    Package package = PreloadedPackages.GetPackage(packageUri); 
 
                    if (package == null)
                    { 
                        if (SecurityHelper.CheckEnvironmentPermission())
                        {
                            package = PackageStore.GetPackage(packageUri);
                        } 
                    }
 
                    if (package != null) 
                    {
                        PackagePart part = package.GetPart(partUri); 
                        PackageRelationshipCollection resources = part.GetRelationshipsByType(relationshipName);

                        Uri targetUri = null;
                        foreach (PackageRelationship relationShip in resources) 
                        {
                            targetUri = PackUriHelper.ResolvePartUri(partUri, relationShip.TargetUri); 
                        } 

                        if (targetUri != null) 
                        {
                            absTargetUri = PackUriHelper.Create(packageUri, targetUri);
                        }
                    } 
                }
            } 
            return absTargetUri; 
        }
 
        private void OnPageLoaded(object sender, EventArgs e)
        {
            PageContent pc = (PageContent)sender;
            if (pc == _partialPage) 
            {
                DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("Loaded Page {0}", _pages.Count)); 
                _partialPage.Initialized -= new EventHandler(OnPageLoaded); 
                _pages.Add(_partialPage);
                _partialPage = null; 
            }
        }

        internal FixedPage GetFixedPage(int pageNumber) 
        {
            FixedPage fp = null; 
            FixedDocumentPage fdp = GetPage(pageNumber) as FixedDocumentPage; 
            if (fdp != null && fdp != DocumentPage.Missing)
            { 
                fp = fdp.FixedPage;
            }
            return fp;
        } 

        //--------------------------------------- 
        // Text Editing 
        //---------------------------------------
        private void OnHighlightChanged(object sender, HighlightChangedEventArgs args) 
        {
            Debug.Assert(sender != null);
            Debug.Assert(args != null);
            Debug.Assert(args.Ranges != null); 

            DocumentsTrace.FixedTextOM.Highlight.Trace(string.Format("HightlightMoved From {0}-{1} To {2}-{3}",0, 0, 0, 0)); 
            Debug.Assert(args.Ranges.Count > 0 && ((TextSegment)args.Ranges[0]).Start.CompareTo(((TextSegment)args.Ranges[0]).End) < 0); 

            // 



            // Add new highlights, if any 
            ITextContainer tc = this.FixedContainer;
            Highlights highlights = null; 
 
            // If this document is part of a FixedDocumentSequence, we should use
            // the highlights that have been set on the sequence. 
            FixedDocumentSequence parent = this.Parent as FixedDocumentSequence;
            if (parent != null)
                highlights = parent.TextContainer.Highlights;
            else 
                highlights = this.FixedContainer.Highlights;
 
            StaticTextPointer highlightTransitionPosition; 
            StaticTextPointer highlightRangeStart;
            object selected; 

            //Find out if any highlights have been removed. We need to invalidate those pages
            List oldHighlightPages = new List();
            foreach (FixedPage page in _highlights.Keys) 
            {
                oldHighlightPages.Add(page); 
            } 

            _highlights.Clear(); 

            highlightTransitionPosition = tc.CreateStaticPointerAtOffset(0);

            while (true) 
            {
                // Move to the next highlight start. 
                if (!highlights.IsContentHighlighted(highlightTransitionPosition, LogicalDirection.Forward)) 
                {
                    highlightTransitionPosition = highlights.GetNextHighlightChangePosition(highlightTransitionPosition, LogicalDirection.Forward); 

                    // No more highlights?
                    if (highlightTransitionPosition.IsNull)
                        break; 
                }
 
                // highlightTransitionPosition is at the start of a new highlight run. 
                // Get the highlight data.
                // NB: this code only recognizes typeof(TextSelection) + AnnotationHighlight. 
                // We should add code here to handle other properties: foreground/background/etc.
                selected = highlights.GetHighlightValue(highlightTransitionPosition, LogicalDirection.Forward, typeof(TextSelection));

                // Save the start position and find the end. 
                highlightRangeStart = highlightTransitionPosition;
 
                //placeholder for highlight type 
                FixedHighlightType fixedHighlightType = FixedHighlightType.None;
                Brush foreground = null; 
                Brush background = null;

                // Store the highlight.
                if (selected != DependencyProperty.UnsetValue) 
                {
                    //find next TextSelection change. 
                    //This is to skip AnnotationHighlight 
                    //change positions, since Annotation Highlight is invisible under TextSelection
                    do 
                    {
                        highlightTransitionPosition = highlights.GetNextHighlightChangePosition(highlightTransitionPosition, LogicalDirection.Forward);
                        Debug.Assert(!highlightTransitionPosition.IsNull, "Highlight start not followed by highlight end!");
                    } 
                    while (highlights.GetHighlightValue(highlightTransitionPosition, LogicalDirection.Forward, typeof(TextSelection)) != DependencyProperty.UnsetValue);
                    fixedHighlightType = FixedHighlightType.TextSelection; 
                    foreground = null; 
                    background = null;
                } 
                else
                {
                    //look for annotation highlight
                    AnnotationHighlightLayer.HighlightSegment highlightSegment = highlights.GetHighlightValue(highlightRangeStart, 
                        LogicalDirection.Forward, typeof(HighlightComponent)) as AnnotationHighlightLayer.HighlightSegment;
                    if (highlightSegment != null) 
                    { 
                        //this is a visible annotation highlight
                        highlightTransitionPosition = highlights.GetNextHighlightChangePosition(highlightTransitionPosition, LogicalDirection.Forward); 
                        Debug.Assert(!highlightTransitionPosition.IsNull, "Highlight start not followed by highlight end!");
                        fixedHighlightType = FixedHighlightType.AnnotationHighlight;
                        background = highlightSegment.Fill;
 
                    }
                } 
 
                //generate fixed highlight if a highlight was has been found
                if (fixedHighlightType != FixedHighlightType.None) 
                {
                    this.FixedContainer.GetMultiHighlights((FixedTextPointer)highlightRangeStart.CreateDynamicTextPointer(LogicalDirection.Forward),
                                                            (FixedTextPointer)highlightTransitionPosition.CreateDynamicTextPointer(LogicalDirection.Forward),
                                                           _highlights, fixedHighlightType, foreground, background); 

                } 
            } 

            ArrayList dirtyPages = new ArrayList(); 
            IList ranges = args.Ranges;

            // Find the dirty page
            for (int i = 0; i < ranges.Count; i++) 
            {
                TextSegment textSegment = (TextSegment)ranges[i]; 
                int startPage = this.FixedContainer.GetPageNumber(textSegment.Start); 
                int endPage =  this.FixedContainer.GetPageNumber(textSegment.End);
 
                for (int count = startPage; count <= endPage; count ++)
                {
                    if (dirtyPages.IndexOf(count) < 0)
                    { 
                        dirtyPages.Add(count);
                    } 
                } 
            }
 
            ICollection newHighlightPages = _highlights.Keys as ICollection;

            //Also dirty the pages that had highlights before but not anymore
            foreach (FixedPage page in oldHighlightPages) 
            {
                if (!newHighlightPages.Contains(page)) 
                { 
                    int pageNo = GetIndexOfPage(page);
                    Debug.Assert(pageNo >= 0 && pageNo=0 && pageNo < PageCount && dirtyPages.IndexOf(pageNo) < 0)
                    {
                        dirtyPages.Add(pageNo);
                    } 
                }
 
            } 
            dirtyPages.Sort();
 
            foreach (int i in dirtyPages)
            {
                HighlightVisual hv = HighlightVisual.GetHighlightVisual(SyncGetPage(i, false /*forceReload*/));
 
                if (hv != null)
                { 
                    hv.InvalidateHighlights(); 
                }
            } 
        }


        //--------------------------------------- 
        // IDP
        //--------------------------------------- 
 
        private object GetPageAsyncDelegate(object arg)
        { 
            GetPageAsyncRequest asyncRequest = (GetPageAsyncRequest)arg;
            PageContent pc = asyncRequest.PageContent;
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.GetPageAsyncDelegate {0}", Pages.IndexOf(pc)));
            // Initiate request for page if necessary 
            if (!_pendingPages.Contains(pc))
            { 
                _pendingPages.Add(pc); 
                // Initiate an async loading of the page
                pc.GetPageRootCompleted += new GetPageRootCompletedEventHandler(OnGetPageRootCompleted); 
                pc.GetPageRootAsync(false /*forceReload*/);
                if (asyncRequest.Cancelled)
                {
                    pc.GetPageRootAsyncCancel(); 
                }
            } 
            return null; 
        }
 

        private void OnGetPageRootCompleted(object sender, GetPageRootCompletedEventArgs args)
        {
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP.OnGetPageRootCompleted {0}", Pages.IndexOf((PageContent)sender))); 
            // Mark this page as no longer pending
            PageContent pc = (PageContent)sender; 
            pc.GetPageRootCompleted -= new GetPageRootCompletedEventHandler(OnGetPageRootCompleted); 
            _pendingPages.Remove(pc);
 
            // Notify all outstanding request for this particular page
            ArrayList completedRequests = new ArrayList();
            IEnumerator> ienum = _asyncOps.GetEnumerator();
            try 
            {
                while (ienum.MoveNext()) 
                { 
                    GetPageAsyncRequest asyncRequest = ienum.Current.Value;
                    // Process any outstanding request for this PageContent 
                    if (asyncRequest.PageContent == pc)
                    {
                        completedRequests.Add(ienum.Current.Key);
                        DocumentPage result = DocumentPage.Missing; 
                        if (!asyncRequest.Cancelled)
                        { 
                            // Do synchronous measure since we have obtained the page 
                            if (!args.Cancelled && (args.Error == null))
                            { 
                                FixedPage c = (FixedPage)args.Result;
                                Size fixedSize = ComputePageSize(c);

//                              Measure / Arrange in GetVisual override of FixedDocumentPage, not here 
                                result = new FixedDocumentPage(this, c, fixedSize, Pages.IndexOf(pc));
                            } 
                        } 
                        // this could throw
                        _NotifyGetPageAsyncCompleted(result, asyncRequest.PageNumber, args.Error, asyncRequest.Cancelled, asyncRequest.UserState); 
                    }
                }
            }
            finally 
            {
                // Remove completed requests from current async ops list 
                foreach (Object userState in completedRequests) 
                {
                    _asyncOps.Remove(userState); 
                }
            }
        }
 

        // Notify the caller of IDFAsync.MeasurePageAsync 
        private void _NotifyGetPageAsyncCompleted(DocumentPage page, int pageNumber, Exception error, bool cancelled, object userState) 
        {
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDP._NotifyGetPageAsyncCompleted {0} {1} {2} {3} {4}", page, pageNumber, error, cancelled, userState)); 
            _paginator.NotifyGetPageCompleted(new GetPageCompletedEventArgs(
                                               page,
                                               pageNumber,
                                               error, 
                                               cancelled,
                                               userState 
                                               )); 
        }
 

        #endregion Private Methods

        //------------------------------------------------------------------- 
        //
        // Private Properties 
        // 
        //----------------------------------------------------------------------
 

        //-------------------------------------------------------------------
        //
        // Private Fields 
        //
        //--------------------------------------------------------------------- 
 
        #region Private Fields
 
        private IDictionary _asyncOps;
        private IList _pendingPages;
        private PageContentCollection _pages;
        private PageContent _partialPage;       // the current partially loaded page. 
        private Dictionary _highlights;
        private double _pageWidth = 8.5 * 96.0d; 
        private double _pageHeight = 11 * 96.0d;     // default page size 
        private FixedTextContainer _fixedTextContainer;
        private RubberbandSelector _rubberbandSelector; 
        private bool _navigateAfterPagination = false ;
        private string _navigateFragment;
        private FixedDocumentPaginator _paginator;
        private DocumentReference _documentReference; 
        private bool _hasExplicitStructure;
 
        private const string _structureRelationshipName       = "http://schemas.microsoft.com/xps/2005/06/documentstructure"; 
        private const string _storyFragmentsRelationshipName  = "http://schemas.microsoft.com/xps/2005/06/storyfragments";
        private static readonly ContentType _storyFragmentsContentType = new ContentType("application/vnd.ms-package.xps-storyfragments+xml"); 
        private static readonly ContentType _documentStructureContentType = new ContentType("application/vnd.ms-package.xps-documentstructure+xml");

        // Caches the UIElement's DependencyObjectType
        private static DependencyObjectType UIElementType = DependencyObjectType.FromSystemTypeInternal(typeof(UIElement)); 
        #endregion Private Fields
 
 
        //-------------------------------------------------------------------
        // 
        // Nested Class
        //
        //----------------------------------------------------------------------
 
        #region Nested Class
        private class GetPageAsyncRequest 
        { 
            internal GetPageAsyncRequest(PageContent pageContent, int pageNumber, object userState)
            { 
                PageContent = pageContent;
                PageNumber = pageNumber;
                UserState = userState;
                Cancelled = false; 
            }
 
            internal PageContent PageContent; 
            internal int PageNumber;
            internal object UserState; 
            internal bool Cancelled;
        }
        #endregion Nested Class
    } 

    //===================================================================== 
    // 
    // FixedDocument's implemenation of DocumentPage
    // 
    internal sealed class FixedDocumentPage : DocumentPage, IServiceProvider
    {
        //--------------------------------------------------------------------
        // 
        // Ctors
        // 
        //---------------------------------------------------------------------- 

        #region Ctors 
        internal FixedDocumentPage(FixedDocument panel, FixedPage page, Size fixedSize, int index) :
            base(page, fixedSize, new Rect(fixedSize), new Rect(fixedSize))
        {
            Debug.Assert(panel != null && page != null); 
            _panel = panel;
            _page = page; 
            _index = index; 
        }
        #endregion Ctors; 


        //-------------------------------------------------------------------
        // 
        // Public  Methods
        // 
        //---------------------------------------------------------------------- 

        #region IServiceProvider 
        /// 
        /// Returns service objects associated with this control.
        /// 
        ///  
        /// FixedDocument currently supports TextView.
        ///  
        ///  
        /// Specifies the type of service object to get.
        ///  
        object IServiceProvider.GetService(Type serviceType)
        {
            if (serviceType == null)
            { 
                throw new ArgumentNullException("serviceType");
            } 
 
            if (serviceType == typeof(ITextView))
            { 
                return this.TextView;
            }

            return null; 
        }
        #endregion IServiceProvider 
 
        //-------------------------------------------------------------------
        // 
        // Public  Methods
        //
        //---------------------------------------------------------------------
 

        //------------------------------------------------------------------- 
        // 
        // Public  Properties
        // 
        //----------------------------------------------------------------------

        public override Visual Visual
        { 
            get
            { 
                if (!_layedOut) 
                {
                    _layedOut = true; 

                    UIElement e;
                    if ((e = ((object)base.Visual) as UIElement)!=null)
                    { 
                        e.Measure(base.Size);
                        e.Arrange(new Rect(base.Size)); 
                    } 
                }
                return base.Visual; 
            }
        }

        //------------------------------------------------------------------- 
        //
        // Internal Properties 
        // 
        //----------------------------------------------------------------------
        #region Internal Properties 

        internal ContentPosition ContentPosition
        {
            get 
            {
                FlowPosition flowPosition = _panel.FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(_index); 
                return new FixedTextPointer(true, LogicalDirection.Forward, flowPosition); 
            }
        } 

        internal FixedPage FixedPage
        {
            get 
            {
                return this._page; 
            } 
        }
 
        internal int PageIndex
        {
            get
            { 
                return this._panel.GetIndexOfPage(this._page);
            } 
        } 

        internal FixedTextView TextView 
        {
            get
            {
                if (_textView == null) 
                {
                    _textView = new FixedTextView(this); 
                } 
                return _textView;
            } 
        }

        internal FixedDocument Owner
        { 
            get
            { 
                return _panel; 
            }
        } 

        internal FixedTextContainer TextContainer
        {
            get 
            {
                return this._panel.FixedContainer; 
            } 
        }
 
        #endregion Internal Properties
        //--------------------------------------------------------------------
        //
        // Internal Event 
        //
        //--------------------------------------------------------------------- 
        //-------------------------------------------------------------------- 
        //
        // Private Fields 
        //
        //---------------------------------------------------------------------

        #region Private Fields 
        private readonly FixedDocument _panel;
        private readonly FixedPage _page; 
        private readonly int _index; 
        private bool _layedOut;
        // Text OM 
        private FixedTextView _textView;
        #endregion Private Fields
    }
 

 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK