FloaterParaClient.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / MS / Internal / PtsHost / FloaterParaClient.cs / 1 / FloaterParaClient.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// Description: FloaterParaClient class is responsible for handling display 
//              related data of paragraphs associated with floaters.
// 
// History: 
//  05/05/2003 : grzegorz - moving from Avalon branch.
// 
//---------------------------------------------------------------------------

using System;
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.Security;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Documents;
using MS.Internal.Documents;
using MS.Internal.Text; 

using MS.Internal.PtsHost.UnsafeNativeMethods; 
 
namespace MS.Internal.PtsHost
{ 
    // ---------------------------------------------------------------------
    // FloaterParaClient class is responsible for handling display related
    // data of paragraphs associated with nested floaters.
    // --------------------------------------------------------------------- 
    internal sealed class FloaterParaClient : FloaterBaseParaClient
    { 
        //-------------------------------------------------------------------- 
        //
        //  Constructors 
        //
        //-------------------------------------------------------------------

        #region Constructors 

        // ------------------------------------------------------------------ 
        // Constructor. 
        //
        //      paragraph - Paragraph associated with this object. 
        // ------------------------------------------------------------------
        internal FloaterParaClient(FloaterParagraph paragraph)
            : base(paragraph)
        { 
        }
 
        // ----------------------------------------------------------------- 
        // IDisposable.Dispose
        // ------------------------------------------------------------------ 
        /// 
        /// Critical - as this calls the Critical function PTS.FsDestroySubpage.
        /// Safe - as the parameters passed in, PtsContext.Context and _paraHandle are
        ///        both marked Critical for set.  SubpageHandle parameter just returns 
        ///        _paraHandle.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        public override void Dispose()
        { 
            if(_pageContext != null)
            {
                _pageContext.RemoveFloatingParaClient(this);
            } 

            base.Dispose(); 
        } 

        #endregion Constructors 

        /// 
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails,
        ///            PtsHelper.ArrangeTrack and PtsHelper.TrackListFromSubpage. 
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        protected override void OnArrange()
        {
            base.OnArrange();
 
            ((FloaterParagraph)Paragraph).UpdateSegmentLastFormatPositions();
 
            // Query subpage details 
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); 

            _pageContext.AddFloatingParaClient(this);

            // Arrange subpage content. Subpage content may be simple or complex - 
            // depending of set of features used in the content of the subpage.
            // (1) simple subpage (contains only one track) 
            // (2) complex subpage (contains columns) 
            if (PTS.ToBoolean(subpageDetails.fSimple))
            { 
                _pageContextOfThisPage.PageRect = new PTS.FSRECT(subpageDetails.u.simple.trackdescr.fsrc);

                // (1) simple subpage (contains only one track)
                // Exceptions don't need to pop, as the top level arrange context will be nulled out if thrown. 
                Paragraph.StructuralCache.CurrentArrangeContext.PushNewPageData(_pageContextOfThisPage, subpageDetails.u.simple.trackdescr.fsrc,
                                                                                Paragraph.StructuralCache.CurrentArrangeContext.FinitePage); 
 
                PtsHelper.ArrangeTrack(PtsContext, ref subpageDetails.u.simple.trackdescr, subpageDetails.u.simple.fswdir);
 
                Paragraph.StructuralCache.CurrentArrangeContext.PopPageData();
            }
            else
            { 
                _pageContextOfThisPage.PageRect = new PTS.FSRECT(subpageDetails.u.complex.fsrc);
 
                // (2) complex page (contains columns) 
                // cBasicColumns == 0, means that subpage content is empty
                if (subpageDetails.u.complex.cBasicColumns != 0) 
                {
                    // Retrieve description for each column.
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 

                    // Arrange each track 
                    for (int index = 0; index < arrayColumnDesc.Length; index++) 
                    {
                        // Exceptions don't need to pop, as the top level arrange context will be nulled out if thrown. 
                        Paragraph.StructuralCache.CurrentArrangeContext.PushNewPageData(_pageContextOfThisPage, arrayColumnDesc[index].fsrc,
                                                                                        Paragraph.StructuralCache.CurrentArrangeContext.FinitePage);

                        PtsHelper.ArrangeTrack(PtsContext, ref arrayColumnDesc[index], subpageDetails.u.complex.fswdir); 

                        Paragraph.StructuralCache.CurrentArrangeContext.PopPageData(); 
                    } 
                }
            } 
        }

        // -----------------------------------------------------------------
        // Updates viewport 
        // -----------------------------------------------------------------
        ///  
        /// Critical - as this calls Critical functions PTS.FsQuerySubpageDetails, 
        ///            PtsHelper.TrackListFromSubpage and PtsHelper.UpdateViewportTrack
        /// Safe - The IntPtr parameters passed to PTS.FsQuerySubpageDetails, PtsHelper.TrackListFromSubpage and PtsHelper.UpdateViewportTrack 
        ///        are SecurityCriticalDataForSet which ensures that partial trust code won't be able to set it to a random value.
        ///        The subpageDetails parameter passed to other methods is generated securely in this function.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void UpdateViewport(ref PTS.FSRECT viewport)
        { 
            // Query subpage details 
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); 

            PTS.FSRECT viewportSubpage = new PTS.FSRECT();

            viewportSubpage.u = viewport.u - ContentRect.u; 
            viewportSubpage.v = viewport.v - ContentRect.v;
            viewportSubpage.du = viewport.du; 
            viewportSubpage.dv = viewport.dv; 

            // Subpage content may be simple or complex - 
            // depending of set of features used in the content of the subpage.
            // (1) simple subpage (contains only one track)
            // (2) complex subpage (contains columns)
            if (PTS.ToBoolean(subpageDetails.fSimple)) 
            {
                PtsHelper.UpdateViewportTrack(PtsContext, ref subpageDetails.u.simple.trackdescr, ref viewportSubpage); 
            } 
            else
            { 
                // (2) complex page (contains columns)
                // cBasicColumns == 0, means that subpage content is empty
                bool emptySubpage = (subpageDetails.u.complex.cBasicColumns == 0);
                if (!emptySubpage) 
                {
                    // Retrieve description for each column. 
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; 
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc);
 
                    emptySubpage = (arrayColumnDesc.Length == 0);
                    if (!emptySubpage)
                    {
                        for (int index = 0; index < arrayColumnDesc.Length; index++) 
                        {
                            PtsHelper.UpdateViewportTrack(PtsContext, ref arrayColumnDesc[index], ref viewportSubpage); 
                        } 
                    }
                } 
            }
        }

 
        // -----------------------------------------------------------------
        // Arrange floater 
        // 
        //      rcFloater - rectangle of the floater
        //      rcHostPara - rectangle of the host text paragraph. 
        // ------------------------------------------------------------------
        internal override void ArrangeFloater(PTS.FSRECT rcFloater, PTS.FSRECT rcHostPara, uint fswdirParent, PageContext pageContext)
        {
            // If alignment is set to Stretch and floater width is less than para width, center it 
            if (IsFloaterHorizontallyCentered(rcFloater, rcHostPara))
            { 
                rcFloater.u = rcHostPara.u + (rcHostPara.du - rcFloater.du) / 2; 
            }
 
            // Set paragraph rectangle (relative to the page)
            _rect = rcFloater;

            // Adjust rect to account for margins 
            // Add margin values to rect offsets and subtract them from rect widths
            MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element); 
            _rect.v += mbp.MarginTop; 
            _rect.dv -= mbp.MarginTop + mbp.MarginBottom;
            _rect.u += mbp.MarginLeft; 
            _rect.du -= mbp.MarginLeft + mbp.MarginRight;

            _flowDirectionParent = PTS.FswdirToFlowDirection(fswdirParent);
            _flowDirection = (FlowDirection)Paragraph.Element.GetValue(FrameworkElement.FlowDirectionProperty); 
            _pageContext = pageContext;
 
            if(ThisFlowDirection != PageFlowDirection) 
            {
                mbp.MirrorBP(); 
            }

            _contentRect.u = _rect.u + mbp.BPLeft;
            _contentRect.du = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.du - mbp.BPRight - mbp.BPLeft); 
            _contentRect.v = _rect.v + mbp.BPTop;
            _contentRect.dv = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.dv - mbp.BPBottom - mbp.BPTop); 
 
            _paddingRect.u = _rect.u + mbp.BorderLeft;
            _paddingRect.du = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.du - mbp.BorderRight - mbp.BorderLeft); 
            _paddingRect.v = _rect.v + mbp.BorderTop;
            _paddingRect.dv = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.dv - mbp.BorderBottom - mbp.BorderTop);

            // Do paragraph specifc arrange 
            OnArrange();
        } 
 
        // -----------------------------------------------------------------
        // Hit tests to the correct IInputElement within the paragraph 
        // that the mouse is over.
        // ------------------------------------------------------------------
        /// 
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails 
        ///            and some PtsHelper functions.
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context 
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal override IInputElement InputHitTest(PTS.FSPOINT pt)
        {
            IInputElement ie = null; 

 
            if(_pageContextOfThisPage.FloatingElementList != null) 
            {
                for(int index = 0; index < _pageContextOfThisPage.FloatingElementList.Count && ie == null; index++) 
                {
                    BaseParaClient floatingElement = _pageContextOfThisPage.FloatingElementList[index];

                    ie = floatingElement.InputHitTest(pt); 
                }
            } 
 
            if(ie == null)
            { 
                // Query subpage details
                PTS.FSSUBPAGEDETAILS subpageDetails;
                PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
                if(Rect.Contains(pt))
                { 
                    if(ContentRect.Contains(pt)) 
                    {
                        pt = new PTS.FSPOINT(pt.u - ContentRect.u, pt.v - ContentRect.v); 

                        // Hittest subpage content. Subpage content may be simple or complex -
                        // depending of set of features used in the content of the page.
                        // (1) simple subpage (contains only one track) 
                        // (2) complex subpage (contains columns)
                        if (PTS.ToBoolean(subpageDetails.fSimple)) 
                        { 
                            ie = PtsHelper.InputHitTestTrack(PtsContext, pt, ref subpageDetails.u.simple.trackdescr);
                        } 
                        else
                        {
                            // (2) complex page (contains columns)
                            // cBasicColumns == 0, means that subpage content is empty 
                            if (subpageDetails.u.complex.cBasicColumns != 0)
                            { 
                                // Retrieve description for each column. 
                                PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
                                PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 

                                // Arrange each track
                                for (int index = 0; index < arrayColumnDesc.Length && ie == null; index++)
                                { 
                                    ie = PtsHelper.InputHitTestTrack(PtsContext, pt, ref arrayColumnDesc[index]);
                                } 
                            } 
                        }
                    } 

                    if(ie == null)
                    {
                        ie = Paragraph.Element as IInputElement; 
                    }
                } 
            } 

            return ie; 
        }

        // ------------------------------------------------------------------
        // Returns ArrayList of rectangles for the given ContentElement 
        // if it is found. Returns null otherwise.
        // start: int representing start offset of e. 
        // length: int representing number of positions occupied by e. 
        // -----------------------------------------------------------------
        ///  
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails
        ///            and some PtsHelper functions.
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override List GetRectangles(ContentElement e, int start, int length)
        { 
            List rectangles = new List();

            if (Paragraph.Element as ContentElement == e)
            { 
                // We have found the element. Return rectangles for this paragraph.
                GetRectanglesForParagraphElement(out rectangles); 
            } 
            else
            { 
                // Query subpage details
                PTS.FSSUBPAGEDETAILS subpageDetails;
                PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
                // Check subpage content for element. Subpage content may be simple or complex -
                // depending of set of features used in the content of the page. 
                // (1) simple subpage (contains only one track) 
                // (2) complex subpage (contains columns)
                if (PTS.ToBoolean(subpageDetails.fSimple)) 
                {
                    // (1) simple subpage (contains only one track)
                    rectangles = PtsHelper.GetRectanglesInTrack(PtsContext, e, start, length, ref subpageDetails.u.simple.trackdescr);
                } 
                else
                { 
                    // (2) complex page (contains columns) 
                    // cBasicColumns == 0, means that subpage content is empty
                    if (subpageDetails.u.complex.cBasicColumns != 0) 
                    {
                        // Retrieve description for each column.
                        PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
                        PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 

                        // Arrange each track 
                        for (int index = 0; index < arrayColumnDesc.Length; index++) 
                        {
                            List trackRectangles = PtsHelper.GetRectanglesInTrack(PtsContext, e, start, length, ref arrayColumnDesc[index]); 
                            Invariant.Assert(trackRectangles != null);
                            if (trackRectangles.Count != 0)
                            {
                                // Add rectangles found in this track to all rectangles 
                                rectangles.AddRange(trackRectangles);
                            } 
                        } 
                    }
                } 

                rectangles = PtsHelper.OffsetRectangleList(rectangles, TextDpi.FromTextDpi(ContentRect.u), TextDpi.FromTextDpi(ContentRect.v));
            }
 
            Invariant.Assert(rectangles != null);
            return rectangles; 
        } 

 
        // ------------------------------------------------------------------
        // Validate visual node associated with paragraph.
        //
        //      fskupdInherited - inherited update info 
        //      fswdir - inherited flow direction
        // ----------------------------------------------------------------- 
        ///  
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails and
        ///            some PtsHelper functions. 
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal override void ValidateVisual(PTS.FSKUPDATE fskupdInherited) 
        { 
            // Floater is always reported as NEW. Override PTS inherited value.
            fskupdInherited = PTS.FSKUPDATE.fskupdNew; 

            // Query subpage details
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); 

            // Obtain all mbd info 
            MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element); 

            if(ThisFlowDirection != PageFlowDirection) 
            {
                mbp.MirrorBP();
            }
 
            Brush backgroundBrush = (Brush)Paragraph.Element.GetValue(TextElement.BackgroundProperty);
            Visual.DrawBackgroundAndBorder(backgroundBrush, mbp.BorderBrush, mbp.Border, _rect.FromTextDpi(), IsFirstChunk, IsLastChunk); 
 

            ContainerVisual pageContentVisual; 
            ContainerVisual floatingElementsVisual;

            if(_visual.Children.Count != 2)
            { 
                _visual.Children.Clear();
                _visual.Children.Add(new ContainerVisual()); 
                _visual.Children.Add(new ContainerVisual()); 
            }
 
            pageContentVisual = (ContainerVisual)_visual.Children[0];
            floatingElementsVisual = (ContainerVisual)_visual.Children[1];

            // Subpage content may be simple or complex - 
            // depending of set of features used in the content of the subpage.
            // (1) simple subpage (contains only one track) 
            // (2) complex subpage (contains columns) 
            if (PTS.ToBoolean(subpageDetails.fSimple))
            { 
                // (1) simple subpage (contains only one track)
                PTS.FSKUPDATE fskupd = subpageDetails.u.simple.trackdescr.fsupdinf.fskupd;
                if (fskupd == PTS.FSKUPDATE.fskupdInherited)
                { 
                    fskupd = fskupdInherited;
                } 
                VisualCollection visualChildren = pageContentVisual.Children; 
                if (fskupd == PTS.FSKUPDATE.fskupdNew)
                { 
                    visualChildren.Clear();
                    visualChildren.Add(new ContainerVisual());
                }
                // For complex subpage SectionVisual is added. So, when morphing 
                // complex subpage to simple one, remove SectionVisual.
                else if (visualChildren.Count == 1 && !(visualChildren[0] is ContainerVisual)) 
                { 
                    visualChildren.Clear();
                    visualChildren.Add(new ContainerVisual()); 
                }
                Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is ContainerVisual);
                ContainerVisual trackVisual = (ContainerVisual)visualChildren[0];
 
                PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref subpageDetails.u.simple.trackdescr);
            } 
            else 
            {
                // (2) complex page (contains columns) 
                // cBasicColumns == 0, means that subpage content is empty
                bool emptySubpage = (subpageDetails.u.complex.cBasicColumns == 0);
                if (!emptySubpage)
                { 
                    // Retrieve description for each column.
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; 
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 

                    emptySubpage = (arrayColumnDesc.Length == 0); 
                    if (!emptySubpage)
                    {
                        PTS.FSKUPDATE fskupd = fskupdInherited;
                        ErrorHandler.Assert(fskupd != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); 
                        Debug.Assert(fskupd != PTS.FSKUPDATE.fskupdNoChange);
 
                        // For complex subpage SectionVisual is added. So, when morphing 
                        // simple subpage to complex one, remove ParagraphVisual.
                        VisualCollection visualChildren = pageContentVisual.Children; 
                        if (visualChildren.Count == 0)
                        {
                            visualChildren.Add(new SectionVisual());
                        } 
                        else if (!(visualChildren[0] is SectionVisual))
                        { 
                            visualChildren.Clear(); 
                            visualChildren.Add(new SectionVisual());
                        } 
                        Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is SectionVisual);
                        SectionVisual sectionVisual = (SectionVisual)visualChildren[0];

                        // Draw column rules. 
                        ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(Paragraph.Element);
                        sectionVisual.DrawColumnRules(ref arrayColumnDesc, TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.v), TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.dv), columnProperties); 
 
                        visualChildren = sectionVisual.Children;
                        if (fskupd == PTS.FSKUPDATE.fskupdNew) 
                        {
                            visualChildren.Clear();
                            for (int index = 0; index < arrayColumnDesc.Length; index++)
                            { 
                                visualChildren.Add(new ContainerVisual());
                            } 
                        } 
                        ErrorHandler.Assert(visualChildren.Count == arrayColumnDesc.Length, ErrorHandler.ColumnVisualCountMismatch);
 
                        for (int index = 0; index < arrayColumnDesc.Length; index++)
                        {
                            ContainerVisual trackVisual = (ContainerVisual)visualChildren[index];
 
                            PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref arrayColumnDesc[index]);
                        } 
                    } 
                }
                if (emptySubpage) 
                {
                    // There is no content, remove all existing visuals.
                    _visual.Children.Clear();
                } 
            }
 
            pageContentVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi(); 
            floatingElementsVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi();
 
            PTS.FSRECT clipRect = new PTS.FSRECT(_paddingRect.u - _contentRect.u, _paddingRect.v - _contentRect.v, _paddingRect.du, _paddingRect.dv);
            PtsHelper.ClipChildrenToRect(_visual, clipRect.FromTextDpi());

            PtsHelper.UpdateFloatingElementVisuals(floatingElementsVisual, _pageContextOfThisPage.FloatingElementList); 
        }
 
        // ----------------------------------------------------------------- 
        // Create paragraph result representing this paragraph.
        // ----------------------------------------------------------------- 
        internal override ParagraphResult CreateParagraphResult()
        {
            return new FloaterParagraphResult(this);
        } 

        // ------------------------------------------------------------------ 
        // Return TextContentRange for the content of the paragraph. 
        // -----------------------------------------------------------------
        ///  
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails
        ///            and some PtsHelper functions.
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override TextContentRange GetTextContentRange()
        { 
            TextContentRange textContentRange;

            // Query subpage details
            PTS.FSSUBPAGEDETAILS subpageDetails; 
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
            // Subpage content may be simple or complex - 
            // depending of set of features used in the content of the page.
            // (1) simple subpage (contains only one track) 
            // (2) complex subpage (contains columns)
            if (PTS.ToBoolean(subpageDetails.fSimple))
            {
                // (1) simple subpage (contains only one track) 
                textContentRange = PtsHelper.TextContentRangeFromTrack(PtsContext, subpageDetails.u.simple.trackdescr.pfstrack);
            } 
            else 
            {
                textContentRange = new TextContentRange(); 

                // (2) complex page (contains columns)
                // cBasicColumns == 0, means that subpage content is empty
                if (subpageDetails.u.complex.cBasicColumns != 0) 
                {
                    // Retrieve description for each column. 
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; 
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc);
 
                    // Arrange each track
                    for (int index = 0; index < arrayColumnDesc.Length; index++)
                    {
                        // Merge TextContentRanges for all columns 
                        textContentRange.Merge(PtsHelper.TextContentRangeFromTrack(PtsContext, arrayColumnDesc[index].pfstrack));
                    } 
                } 
            }
 
            // Beginning and end tags should be consumed by host para.

            // If the first paragraph is the first paragraph in the paraclient and it is the first chunk,
            // include start position of this element. 
            if (IsFirstChunk)
            { 
                textContentRange.Merge(TextContainerHelper.GetTextContentRangeForTextElementEdge( 
                    Paragraph.Element as TextElement, ElementEdge.BeforeStart));
            } 

            // If the last paragraph is the last paragraph in the paraclient and it is the last chunk,
            // include end position of this element.
            if (IsLastChunk) 
            {
                textContentRange.Merge(TextContainerHelper.GetTextContentRangeForTextElementEdge( 
                    Paragraph.Element as TextElement, ElementEdge.AfterEnd)); 
            }
 
            return textContentRange;
        }

        // ------------------------------------------------------------------ 
        // Returns a new colleciton of ParagraphResults for the contained paragraphs.
        // ------------------------------------------------------------------ 
        ///  
        /// Critical - as this calls the Critical functions PTS.FsQuerySubpageDetails,
        ///            PTS.FsQueryTrackDetails and some PtsHelper functions. 
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private ReadOnlyCollection GetChildrenParagraphResults(out bool hasTextContent) 
        { 
            List paragraphResults;
 
            // Query subpage details
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
            // hasTextContent is set to true if any of the children paragraphs has text content, not just attached objects
            hasTextContent = false; 
 
            // Subpage content may be simple or complex -
            // depending of set of features used in the content of the page. 
            // (1) simple subpage (contains only one track)
            // (2) complex subpage (contains columns)
            if (PTS.ToBoolean(subpageDetails.fSimple))
            { 
                // (1) simple subpage (contains only one track)
                // Get track details 
                PTS.FSTRACKDETAILS trackDetails; 
                PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, subpageDetails.u.simple.trackdescr.pfstrack, out trackDetails));
                hasTextContent = true; 

                if (trackDetails.cParas == 0)
                {
                    return new ReadOnlyCollection(new List(0)); 
                }
 
                // Get list of paragraphs 
                PTS.FSPARADESCRIPTION[] arrayParaDesc;
                PtsHelper.ParaListFromTrack(PtsContext, subpageDetails.u.simple.trackdescr.pfstrack, ref trackDetails, out arrayParaDesc); 

                paragraphResults = new List(arrayParaDesc.Length);
                for (int i = 0; i < arrayParaDesc.Length; i++)
                { 
                    BaseParaClient paraClient = PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient;
                    PTS.ValidateHandle(paraClient); 
                    ParagraphResult paragraphResult = paraClient.CreateParagraphResult(); 
                    if (paragraphResult.HasTextContent)
                    { 
                        hasTextContent = true;
                    }
                    paragraphResults.Add(paragraphResult);
                } 
            }
            else 
            { 
                // (2) complex page (contains columns)
                // cBasicColumns == 0, means that subpage content is empty 
                if (subpageDetails.u.complex.cBasicColumns == 0)
                {
                    return new ReadOnlyCollection(new List(0));
                } 

                // Retrieve description for each column. 
                PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; 
                PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc);
                Debug.Assert(arrayColumnDesc.Length == 1); 

                // Get track details
                PTS.FSTRACKDETAILS trackDetails;
                PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, arrayColumnDesc[0].pfstrack, out trackDetails)); 

                if (trackDetails.cParas == 0) 
                { 
                    return new ReadOnlyCollection(new List(0));
                } 

                // Get list of paragraphs
                PTS.FSPARADESCRIPTION[] arrayParaDesc;
                PtsHelper.ParaListFromTrack(PtsContext, arrayColumnDesc[0].pfstrack, ref trackDetails, out arrayParaDesc); 

                paragraphResults = new List(arrayParaDesc.Length); 
                for (int i = 0; i < arrayParaDesc.Length; i++) 
                {
                    BaseParaClient paraClient = PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient; 
                    PTS.ValidateHandle(paraClient);
                    ParagraphResult paragraphResult = paraClient.CreateParagraphResult();
                    if (paragraphResult.HasTextContent)
                    { 
                        hasTextContent = true;
                    } 
                    paragraphResults.Add(paragraphResult); 
                }
            } 
            return new ReadOnlyCollection(paragraphResults);
        }

        ///  
        /// Returns a new collection of ColumnResults for the subpage. Will always
        /// have at least one column. 
        ///  
        /// 
        /// True if any column in the floater has text content, i.e. does not contain only figures/floaters 
        /// 
        /// 
        /// Critical - as this calls the Critical functions PTS.FsQuerySubpageDetails
        ///            and PTS.FsQueryTrackDetails. 
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal ReadOnlyCollection GetColumnResults(out bool hasTextContent)
        {
            List columnResults = new List(0);
            Vector contentOffset = new Vector(); 

            // hasTextContent is set to true if any of the columns has text content, not just attached objects. A column has text content if any of 
            // it's paragraph results has text content 
            hasTextContent = false;
 
            // Query subpage details
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
            // Subpage content may be simple or complex -
            // depending of set of features used in the content of the page. 
            // (1) simple subpage (contains only one track) 
            // (2) complex subpage (contains columns)
            if (PTS.ToBoolean(subpageDetails.fSimple)) 
            {
                // (1) simple subpage (contains only one track)
                PTS.FSTRACKDETAILS trackDetails;
                PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, subpageDetails.u.simple.trackdescr.pfstrack, out trackDetails)); 
                if (trackDetails.cParas > 0)
                { 
                    columnResults = new List(1); 
                    ColumnResult columnResult = new ColumnResult(this, ref subpageDetails.u.simple.trackdescr, contentOffset);
                    columnResults.Add(columnResult); 
                    if (columnResult.HasTextContent)
                    {
                        hasTextContent = true;
                    } 
                }
            } 
            else 
            {
                // (2) complex page (contains columns) 
                // cBasicColumns == 0, means that subpage content is empty
                if (subpageDetails.u.complex.cBasicColumns != 0)
                {
                    // Retrieve description for each column. 
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 
 
                    // Floaters are held at one column; just add the first one
                    columnResults = new List(1); 
                    PTS.FSTRACKDETAILS trackDetails;
                    PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, arrayColumnDesc[0].pfstrack, out trackDetails));
                    if (trackDetails.cParas > 0)
                    { 
                        ColumnResult columnResult = new ColumnResult(this, ref arrayColumnDesc[0], contentOffset);
                        columnResults.Add(columnResult); 
                        if (columnResult.HasTextContent) 
                        {
                            hasTextContent = true; 
                        }
                    }
                }
            } 

            return new ReadOnlyCollection(columnResults); 
        } 

        // ----------------------------------------------------------------- 
        // Returns a collection of ParagraphResults for the column's paragraphs.
        //
        //      pfstrack - Pointer to PTS track representing a column.
        //      parentOffset - Parent offset from the top of the page. 
        //      hasTextContent - true if any paragraph has text content
        // ------------------------------------------------------------------ 
        internal ReadOnlyCollection GetParagraphResultsFromColumn(IntPtr pfstrack, Vector parentOffset, out bool hasTextContent) 
        {
            // Floater has only one column. This is the same as getting children paragraphs. 
            return GetChildrenParagraphResults(out hasTextContent);
        }

        // ----------------------------------------------------------------- 
        // Retrieves text range for contents of the column represented by
        // 'pfstrack'. 
        // 
        //      pfstrack - Pointer to PTS track representing a column.
        // ----------------------------------------------------------------- 
        internal TextContentRange GetTextContentRangeFromColumn(IntPtr pfstrack)
        {
            // Floater has only one column.
            return GetTextContentRange(); 
        }
 
        ///  
        /// Returns tight bounding path geometry.
        ///  
        internal Geometry GetTightBoundingGeometryFromTextPositions(ReadOnlyCollection columns, ReadOnlyCollection floatingElements, ITextPointer startPosition, ITextPointer endPosition, Rect visibleRect)
        {
            Geometry geometry = null;
 
            // Floater always has one column, so we can skip getting a column from the text position range
            Invariant.Assert(columns != null && columns.Count <= 1, "Columns collection is null."); 
            Invariant.Assert(floatingElements != null, "Floating element collection is null."); 
            ReadOnlyCollection paragraphs = (columns.Count > 0) ? columns[0].Paragraphs : new ReadOnlyCollection(new List(0));
 
            if (paragraphs.Count > 0 || floatingElements.Count > 0)
            {
                geometry = TextDocumentView.GetTightBoundingGeometryFromTextPositionsHelper(paragraphs, floatingElements, startPosition, endPosition, TextDpi.FromTextDpi(_dvrTopSpace), visibleRect);
 
                //  restrict geometry to the floater's content rect boundary.
                //  because of end-of-line / end-of-para simulation calculated geometry could be larger. 
                Rect viewport = new Rect(0, 0, TextDpi.FromTextDpi(_contentRect.du), TextDpi.FromTextDpi(_contentRect.dv)); 
                CaretElement.ClipGeometryByViewport(ref geometry, viewport);
            } 
            return (geometry);
        }

        // ----------------------------------------------------------------- 
        // Handle to PTS subpage object.
        // ------------------------------------------------------------------ 
        ///  
        /// Critical - setter is Critical as _paraHandle.Value is Critical for set.
        ///  
        internal IntPtr SubpageHandle
        {
            // getter removed (unused internal API).  If needed, recall from history.
 
            [SecurityCritical]
            set { _paraHandle.Value = value; } 
        } 

        // ----------------------------------------------------------------- 
        // Rect of content in page coordinate system
        // ------------------------------------------------------------------
        internal PTS.FSRECT ContentRect { get { return _contentRect; } }
 
        // Floating element list
        internal ReadOnlyCollection FloatingElementResults 
        { 
            get
            { 
                List floatingElements = new List(0);
                List floatingElementList = _pageContextOfThisPage.FloatingElementList;
                if (floatingElementList != null)
                { 
                    for (int i = 0; i < floatingElementList.Count; i++)
                    { 
                        ParagraphResult paragraphResult = floatingElementList[i].CreateParagraphResult(); 
                        floatingElements.Add(paragraphResult);
                    } 
                }
                return new ReadOnlyCollection(floatingElements);
            }
        } 

 
        // ------------------------------------------------------------------ 
        // Returns whether a floater should be horizontally centered
        // ----------------------------------------------------------------- 
        private bool IsFloaterHorizontallyCentered(PTS.FSRECT rcFloater, PTS.FSRECT rcHostPara)
        {
            Floater floater = Paragraph.Element as Floater;
 
            if(floater == null)
            { 
                return false; 
            }
 
            if(floater.HorizontalAlignment != HorizontalAlignment.Stretch)
            {
                return false;
            } 

            if(rcFloater.du >= rcHostPara.du) 
            { 
                return false;
            } 

            return true;

        } 

        private PTS.FSRECT _contentRect; 
        private PTS.FSRECT _paddingRect; 

        // Page context this para client provides. 
        private PageContext _pageContextOfThisPage = new PageContext();
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// Description: FloaterParaClient class is responsible for handling display 
//              related data of paragraphs associated with floaters.
// 
// History: 
//  05/05/2003 : grzegorz - moving from Avalon branch.
// 
//---------------------------------------------------------------------------

using System;
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.Security;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Documents;
using MS.Internal.Documents;
using MS.Internal.Text; 

using MS.Internal.PtsHost.UnsafeNativeMethods; 
 
namespace MS.Internal.PtsHost
{ 
    // ---------------------------------------------------------------------
    // FloaterParaClient class is responsible for handling display related
    // data of paragraphs associated with nested floaters.
    // --------------------------------------------------------------------- 
    internal sealed class FloaterParaClient : FloaterBaseParaClient
    { 
        //-------------------------------------------------------------------- 
        //
        //  Constructors 
        //
        //-------------------------------------------------------------------

        #region Constructors 

        // ------------------------------------------------------------------ 
        // Constructor. 
        //
        //      paragraph - Paragraph associated with this object. 
        // ------------------------------------------------------------------
        internal FloaterParaClient(FloaterParagraph paragraph)
            : base(paragraph)
        { 
        }
 
        // ----------------------------------------------------------------- 
        // IDisposable.Dispose
        // ------------------------------------------------------------------ 
        /// 
        /// Critical - as this calls the Critical function PTS.FsDestroySubpage.
        /// Safe - as the parameters passed in, PtsContext.Context and _paraHandle are
        ///        both marked Critical for set.  SubpageHandle parameter just returns 
        ///        _paraHandle.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        public override void Dispose()
        { 
            if(_pageContext != null)
            {
                _pageContext.RemoveFloatingParaClient(this);
            } 

            base.Dispose(); 
        } 

        #endregion Constructors 

        /// 
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails,
        ///            PtsHelper.ArrangeTrack and PtsHelper.TrackListFromSubpage. 
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        protected override void OnArrange()
        {
            base.OnArrange();
 
            ((FloaterParagraph)Paragraph).UpdateSegmentLastFormatPositions();
 
            // Query subpage details 
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); 

            _pageContext.AddFloatingParaClient(this);

            // Arrange subpage content. Subpage content may be simple or complex - 
            // depending of set of features used in the content of the subpage.
            // (1) simple subpage (contains only one track) 
            // (2) complex subpage (contains columns) 
            if (PTS.ToBoolean(subpageDetails.fSimple))
            { 
                _pageContextOfThisPage.PageRect = new PTS.FSRECT(subpageDetails.u.simple.trackdescr.fsrc);

                // (1) simple subpage (contains only one track)
                // Exceptions don't need to pop, as the top level arrange context will be nulled out if thrown. 
                Paragraph.StructuralCache.CurrentArrangeContext.PushNewPageData(_pageContextOfThisPage, subpageDetails.u.simple.trackdescr.fsrc,
                                                                                Paragraph.StructuralCache.CurrentArrangeContext.FinitePage); 
 
                PtsHelper.ArrangeTrack(PtsContext, ref subpageDetails.u.simple.trackdescr, subpageDetails.u.simple.fswdir);
 
                Paragraph.StructuralCache.CurrentArrangeContext.PopPageData();
            }
            else
            { 
                _pageContextOfThisPage.PageRect = new PTS.FSRECT(subpageDetails.u.complex.fsrc);
 
                // (2) complex page (contains columns) 
                // cBasicColumns == 0, means that subpage content is empty
                if (subpageDetails.u.complex.cBasicColumns != 0) 
                {
                    // Retrieve description for each column.
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 

                    // Arrange each track 
                    for (int index = 0; index < arrayColumnDesc.Length; index++) 
                    {
                        // Exceptions don't need to pop, as the top level arrange context will be nulled out if thrown. 
                        Paragraph.StructuralCache.CurrentArrangeContext.PushNewPageData(_pageContextOfThisPage, arrayColumnDesc[index].fsrc,
                                                                                        Paragraph.StructuralCache.CurrentArrangeContext.FinitePage);

                        PtsHelper.ArrangeTrack(PtsContext, ref arrayColumnDesc[index], subpageDetails.u.complex.fswdir); 

                        Paragraph.StructuralCache.CurrentArrangeContext.PopPageData(); 
                    } 
                }
            } 
        }

        // -----------------------------------------------------------------
        // Updates viewport 
        // -----------------------------------------------------------------
        ///  
        /// Critical - as this calls Critical functions PTS.FsQuerySubpageDetails, 
        ///            PtsHelper.TrackListFromSubpage and PtsHelper.UpdateViewportTrack
        /// Safe - The IntPtr parameters passed to PTS.FsQuerySubpageDetails, PtsHelper.TrackListFromSubpage and PtsHelper.UpdateViewportTrack 
        ///        are SecurityCriticalDataForSet which ensures that partial trust code won't be able to set it to a random value.
        ///        The subpageDetails parameter passed to other methods is generated securely in this function.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void UpdateViewport(ref PTS.FSRECT viewport)
        { 
            // Query subpage details 
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); 

            PTS.FSRECT viewportSubpage = new PTS.FSRECT();

            viewportSubpage.u = viewport.u - ContentRect.u; 
            viewportSubpage.v = viewport.v - ContentRect.v;
            viewportSubpage.du = viewport.du; 
            viewportSubpage.dv = viewport.dv; 

            // Subpage content may be simple or complex - 
            // depending of set of features used in the content of the subpage.
            // (1) simple subpage (contains only one track)
            // (2) complex subpage (contains columns)
            if (PTS.ToBoolean(subpageDetails.fSimple)) 
            {
                PtsHelper.UpdateViewportTrack(PtsContext, ref subpageDetails.u.simple.trackdescr, ref viewportSubpage); 
            } 
            else
            { 
                // (2) complex page (contains columns)
                // cBasicColumns == 0, means that subpage content is empty
                bool emptySubpage = (subpageDetails.u.complex.cBasicColumns == 0);
                if (!emptySubpage) 
                {
                    // Retrieve description for each column. 
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; 
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc);
 
                    emptySubpage = (arrayColumnDesc.Length == 0);
                    if (!emptySubpage)
                    {
                        for (int index = 0; index < arrayColumnDesc.Length; index++) 
                        {
                            PtsHelper.UpdateViewportTrack(PtsContext, ref arrayColumnDesc[index], ref viewportSubpage); 
                        } 
                    }
                } 
            }
        }

 
        // -----------------------------------------------------------------
        // Arrange floater 
        // 
        //      rcFloater - rectangle of the floater
        //      rcHostPara - rectangle of the host text paragraph. 
        // ------------------------------------------------------------------
        internal override void ArrangeFloater(PTS.FSRECT rcFloater, PTS.FSRECT rcHostPara, uint fswdirParent, PageContext pageContext)
        {
            // If alignment is set to Stretch and floater width is less than para width, center it 
            if (IsFloaterHorizontallyCentered(rcFloater, rcHostPara))
            { 
                rcFloater.u = rcHostPara.u + (rcHostPara.du - rcFloater.du) / 2; 
            }
 
            // Set paragraph rectangle (relative to the page)
            _rect = rcFloater;

            // Adjust rect to account for margins 
            // Add margin values to rect offsets and subtract them from rect widths
            MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element); 
            _rect.v += mbp.MarginTop; 
            _rect.dv -= mbp.MarginTop + mbp.MarginBottom;
            _rect.u += mbp.MarginLeft; 
            _rect.du -= mbp.MarginLeft + mbp.MarginRight;

            _flowDirectionParent = PTS.FswdirToFlowDirection(fswdirParent);
            _flowDirection = (FlowDirection)Paragraph.Element.GetValue(FrameworkElement.FlowDirectionProperty); 
            _pageContext = pageContext;
 
            if(ThisFlowDirection != PageFlowDirection) 
            {
                mbp.MirrorBP(); 
            }

            _contentRect.u = _rect.u + mbp.BPLeft;
            _contentRect.du = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.du - mbp.BPRight - mbp.BPLeft); 
            _contentRect.v = _rect.v + mbp.BPTop;
            _contentRect.dv = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.dv - mbp.BPBottom - mbp.BPTop); 
 
            _paddingRect.u = _rect.u + mbp.BorderLeft;
            _paddingRect.du = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.du - mbp.BorderRight - mbp.BorderLeft); 
            _paddingRect.v = _rect.v + mbp.BorderTop;
            _paddingRect.dv = Math.Max(TextDpi.ToTextDpi(TextDpi.MinWidth), _rect.dv - mbp.BorderBottom - mbp.BorderTop);

            // Do paragraph specifc arrange 
            OnArrange();
        } 
 
        // -----------------------------------------------------------------
        // Hit tests to the correct IInputElement within the paragraph 
        // that the mouse is over.
        // ------------------------------------------------------------------
        /// 
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails 
        ///            and some PtsHelper functions.
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context 
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal override IInputElement InputHitTest(PTS.FSPOINT pt)
        {
            IInputElement ie = null; 

 
            if(_pageContextOfThisPage.FloatingElementList != null) 
            {
                for(int index = 0; index < _pageContextOfThisPage.FloatingElementList.Count && ie == null; index++) 
                {
                    BaseParaClient floatingElement = _pageContextOfThisPage.FloatingElementList[index];

                    ie = floatingElement.InputHitTest(pt); 
                }
            } 
 
            if(ie == null)
            { 
                // Query subpage details
                PTS.FSSUBPAGEDETAILS subpageDetails;
                PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
                if(Rect.Contains(pt))
                { 
                    if(ContentRect.Contains(pt)) 
                    {
                        pt = new PTS.FSPOINT(pt.u - ContentRect.u, pt.v - ContentRect.v); 

                        // Hittest subpage content. Subpage content may be simple or complex -
                        // depending of set of features used in the content of the page.
                        // (1) simple subpage (contains only one track) 
                        // (2) complex subpage (contains columns)
                        if (PTS.ToBoolean(subpageDetails.fSimple)) 
                        { 
                            ie = PtsHelper.InputHitTestTrack(PtsContext, pt, ref subpageDetails.u.simple.trackdescr);
                        } 
                        else
                        {
                            // (2) complex page (contains columns)
                            // cBasicColumns == 0, means that subpage content is empty 
                            if (subpageDetails.u.complex.cBasicColumns != 0)
                            { 
                                // Retrieve description for each column. 
                                PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
                                PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 

                                // Arrange each track
                                for (int index = 0; index < arrayColumnDesc.Length && ie == null; index++)
                                { 
                                    ie = PtsHelper.InputHitTestTrack(PtsContext, pt, ref arrayColumnDesc[index]);
                                } 
                            } 
                        }
                    } 

                    if(ie == null)
                    {
                        ie = Paragraph.Element as IInputElement; 
                    }
                } 
            } 

            return ie; 
        }

        // ------------------------------------------------------------------
        // Returns ArrayList of rectangles for the given ContentElement 
        // if it is found. Returns null otherwise.
        // start: int representing start offset of e. 
        // length: int representing number of positions occupied by e. 
        // -----------------------------------------------------------------
        ///  
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails
        ///            and some PtsHelper functions.
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override List GetRectangles(ContentElement e, int start, int length)
        { 
            List rectangles = new List();

            if (Paragraph.Element as ContentElement == e)
            { 
                // We have found the element. Return rectangles for this paragraph.
                GetRectanglesForParagraphElement(out rectangles); 
            } 
            else
            { 
                // Query subpage details
                PTS.FSSUBPAGEDETAILS subpageDetails;
                PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
                // Check subpage content for element. Subpage content may be simple or complex -
                // depending of set of features used in the content of the page. 
                // (1) simple subpage (contains only one track) 
                // (2) complex subpage (contains columns)
                if (PTS.ToBoolean(subpageDetails.fSimple)) 
                {
                    // (1) simple subpage (contains only one track)
                    rectangles = PtsHelper.GetRectanglesInTrack(PtsContext, e, start, length, ref subpageDetails.u.simple.trackdescr);
                } 
                else
                { 
                    // (2) complex page (contains columns) 
                    // cBasicColumns == 0, means that subpage content is empty
                    if (subpageDetails.u.complex.cBasicColumns != 0) 
                    {
                        // Retrieve description for each column.
                        PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
                        PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 

                        // Arrange each track 
                        for (int index = 0; index < arrayColumnDesc.Length; index++) 
                        {
                            List trackRectangles = PtsHelper.GetRectanglesInTrack(PtsContext, e, start, length, ref arrayColumnDesc[index]); 
                            Invariant.Assert(trackRectangles != null);
                            if (trackRectangles.Count != 0)
                            {
                                // Add rectangles found in this track to all rectangles 
                                rectangles.AddRange(trackRectangles);
                            } 
                        } 
                    }
                } 

                rectangles = PtsHelper.OffsetRectangleList(rectangles, TextDpi.FromTextDpi(ContentRect.u), TextDpi.FromTextDpi(ContentRect.v));
            }
 
            Invariant.Assert(rectangles != null);
            return rectangles; 
        } 

 
        // ------------------------------------------------------------------
        // Validate visual node associated with paragraph.
        //
        //      fskupdInherited - inherited update info 
        //      fswdir - inherited flow direction
        // ----------------------------------------------------------------- 
        ///  
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails and
        ///            some PtsHelper functions. 
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal override void ValidateVisual(PTS.FSKUPDATE fskupdInherited) 
        { 
            // Floater is always reported as NEW. Override PTS inherited value.
            fskupdInherited = PTS.FSKUPDATE.fskupdNew; 

            // Query subpage details
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); 

            // Obtain all mbd info 
            MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element); 

            if(ThisFlowDirection != PageFlowDirection) 
            {
                mbp.MirrorBP();
            }
 
            Brush backgroundBrush = (Brush)Paragraph.Element.GetValue(TextElement.BackgroundProperty);
            Visual.DrawBackgroundAndBorder(backgroundBrush, mbp.BorderBrush, mbp.Border, _rect.FromTextDpi(), IsFirstChunk, IsLastChunk); 
 

            ContainerVisual pageContentVisual; 
            ContainerVisual floatingElementsVisual;

            if(_visual.Children.Count != 2)
            { 
                _visual.Children.Clear();
                _visual.Children.Add(new ContainerVisual()); 
                _visual.Children.Add(new ContainerVisual()); 
            }
 
            pageContentVisual = (ContainerVisual)_visual.Children[0];
            floatingElementsVisual = (ContainerVisual)_visual.Children[1];

            // Subpage content may be simple or complex - 
            // depending of set of features used in the content of the subpage.
            // (1) simple subpage (contains only one track) 
            // (2) complex subpage (contains columns) 
            if (PTS.ToBoolean(subpageDetails.fSimple))
            { 
                // (1) simple subpage (contains only one track)
                PTS.FSKUPDATE fskupd = subpageDetails.u.simple.trackdescr.fsupdinf.fskupd;
                if (fskupd == PTS.FSKUPDATE.fskupdInherited)
                { 
                    fskupd = fskupdInherited;
                } 
                VisualCollection visualChildren = pageContentVisual.Children; 
                if (fskupd == PTS.FSKUPDATE.fskupdNew)
                { 
                    visualChildren.Clear();
                    visualChildren.Add(new ContainerVisual());
                }
                // For complex subpage SectionVisual is added. So, when morphing 
                // complex subpage to simple one, remove SectionVisual.
                else if (visualChildren.Count == 1 && !(visualChildren[0] is ContainerVisual)) 
                { 
                    visualChildren.Clear();
                    visualChildren.Add(new ContainerVisual()); 
                }
                Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is ContainerVisual);
                ContainerVisual trackVisual = (ContainerVisual)visualChildren[0];
 
                PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref subpageDetails.u.simple.trackdescr);
            } 
            else 
            {
                // (2) complex page (contains columns) 
                // cBasicColumns == 0, means that subpage content is empty
                bool emptySubpage = (subpageDetails.u.complex.cBasicColumns == 0);
                if (!emptySubpage)
                { 
                    // Retrieve description for each column.
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; 
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 

                    emptySubpage = (arrayColumnDesc.Length == 0); 
                    if (!emptySubpage)
                    {
                        PTS.FSKUPDATE fskupd = fskupdInherited;
                        ErrorHandler.Assert(fskupd != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); 
                        Debug.Assert(fskupd != PTS.FSKUPDATE.fskupdNoChange);
 
                        // For complex subpage SectionVisual is added. So, when morphing 
                        // simple subpage to complex one, remove ParagraphVisual.
                        VisualCollection visualChildren = pageContentVisual.Children; 
                        if (visualChildren.Count == 0)
                        {
                            visualChildren.Add(new SectionVisual());
                        } 
                        else if (!(visualChildren[0] is SectionVisual))
                        { 
                            visualChildren.Clear(); 
                            visualChildren.Add(new SectionVisual());
                        } 
                        Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is SectionVisual);
                        SectionVisual sectionVisual = (SectionVisual)visualChildren[0];

                        // Draw column rules. 
                        ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(Paragraph.Element);
                        sectionVisual.DrawColumnRules(ref arrayColumnDesc, TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.v), TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.dv), columnProperties); 
 
                        visualChildren = sectionVisual.Children;
                        if (fskupd == PTS.FSKUPDATE.fskupdNew) 
                        {
                            visualChildren.Clear();
                            for (int index = 0; index < arrayColumnDesc.Length; index++)
                            { 
                                visualChildren.Add(new ContainerVisual());
                            } 
                        } 
                        ErrorHandler.Assert(visualChildren.Count == arrayColumnDesc.Length, ErrorHandler.ColumnVisualCountMismatch);
 
                        for (int index = 0; index < arrayColumnDesc.Length; index++)
                        {
                            ContainerVisual trackVisual = (ContainerVisual)visualChildren[index];
 
                            PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref arrayColumnDesc[index]);
                        } 
                    } 
                }
                if (emptySubpage) 
                {
                    // There is no content, remove all existing visuals.
                    _visual.Children.Clear();
                } 
            }
 
            pageContentVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi(); 
            floatingElementsVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi();
 
            PTS.FSRECT clipRect = new PTS.FSRECT(_paddingRect.u - _contentRect.u, _paddingRect.v - _contentRect.v, _paddingRect.du, _paddingRect.dv);
            PtsHelper.ClipChildrenToRect(_visual, clipRect.FromTextDpi());

            PtsHelper.UpdateFloatingElementVisuals(floatingElementsVisual, _pageContextOfThisPage.FloatingElementList); 
        }
 
        // ----------------------------------------------------------------- 
        // Create paragraph result representing this paragraph.
        // ----------------------------------------------------------------- 
        internal override ParagraphResult CreateParagraphResult()
        {
            return new FloaterParagraphResult(this);
        } 

        // ------------------------------------------------------------------ 
        // Return TextContentRange for the content of the paragraph. 
        // -----------------------------------------------------------------
        ///  
        /// Critical - as this calls the Critical function PTS.FsQuerySubpageDetails
        ///            and some PtsHelper functions.
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override TextContentRange GetTextContentRange()
        { 
            TextContentRange textContentRange;

            // Query subpage details
            PTS.FSSUBPAGEDETAILS subpageDetails; 
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
            // Subpage content may be simple or complex - 
            // depending of set of features used in the content of the page.
            // (1) simple subpage (contains only one track) 
            // (2) complex subpage (contains columns)
            if (PTS.ToBoolean(subpageDetails.fSimple))
            {
                // (1) simple subpage (contains only one track) 
                textContentRange = PtsHelper.TextContentRangeFromTrack(PtsContext, subpageDetails.u.simple.trackdescr.pfstrack);
            } 
            else 
            {
                textContentRange = new TextContentRange(); 

                // (2) complex page (contains columns)
                // cBasicColumns == 0, means that subpage content is empty
                if (subpageDetails.u.complex.cBasicColumns != 0) 
                {
                    // Retrieve description for each column. 
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; 
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc);
 
                    // Arrange each track
                    for (int index = 0; index < arrayColumnDesc.Length; index++)
                    {
                        // Merge TextContentRanges for all columns 
                        textContentRange.Merge(PtsHelper.TextContentRangeFromTrack(PtsContext, arrayColumnDesc[index].pfstrack));
                    } 
                } 
            }
 
            // Beginning and end tags should be consumed by host para.

            // If the first paragraph is the first paragraph in the paraclient and it is the first chunk,
            // include start position of this element. 
            if (IsFirstChunk)
            { 
                textContentRange.Merge(TextContainerHelper.GetTextContentRangeForTextElementEdge( 
                    Paragraph.Element as TextElement, ElementEdge.BeforeStart));
            } 

            // If the last paragraph is the last paragraph in the paraclient and it is the last chunk,
            // include end position of this element.
            if (IsLastChunk) 
            {
                textContentRange.Merge(TextContainerHelper.GetTextContentRangeForTextElementEdge( 
                    Paragraph.Element as TextElement, ElementEdge.AfterEnd)); 
            }
 
            return textContentRange;
        }

        // ------------------------------------------------------------------ 
        // Returns a new colleciton of ParagraphResults for the contained paragraphs.
        // ------------------------------------------------------------------ 
        ///  
        /// Critical - as this calls the Critical functions PTS.FsQuerySubpageDetails,
        ///            PTS.FsQueryTrackDetails and some PtsHelper functions. 
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this
        ///        function.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private ReadOnlyCollection GetChildrenParagraphResults(out bool hasTextContent) 
        { 
            List paragraphResults;
 
            // Query subpage details
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
            // hasTextContent is set to true if any of the children paragraphs has text content, not just attached objects
            hasTextContent = false; 
 
            // Subpage content may be simple or complex -
            // depending of set of features used in the content of the page. 
            // (1) simple subpage (contains only one track)
            // (2) complex subpage (contains columns)
            if (PTS.ToBoolean(subpageDetails.fSimple))
            { 
                // (1) simple subpage (contains only one track)
                // Get track details 
                PTS.FSTRACKDETAILS trackDetails; 
                PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, subpageDetails.u.simple.trackdescr.pfstrack, out trackDetails));
                hasTextContent = true; 

                if (trackDetails.cParas == 0)
                {
                    return new ReadOnlyCollection(new List(0)); 
                }
 
                // Get list of paragraphs 
                PTS.FSPARADESCRIPTION[] arrayParaDesc;
                PtsHelper.ParaListFromTrack(PtsContext, subpageDetails.u.simple.trackdescr.pfstrack, ref trackDetails, out arrayParaDesc); 

                paragraphResults = new List(arrayParaDesc.Length);
                for (int i = 0; i < arrayParaDesc.Length; i++)
                { 
                    BaseParaClient paraClient = PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient;
                    PTS.ValidateHandle(paraClient); 
                    ParagraphResult paragraphResult = paraClient.CreateParagraphResult(); 
                    if (paragraphResult.HasTextContent)
                    { 
                        hasTextContent = true;
                    }
                    paragraphResults.Add(paragraphResult);
                } 
            }
            else 
            { 
                // (2) complex page (contains columns)
                // cBasicColumns == 0, means that subpage content is empty 
                if (subpageDetails.u.complex.cBasicColumns == 0)
                {
                    return new ReadOnlyCollection(new List(0));
                } 

                // Retrieve description for each column. 
                PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; 
                PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc);
                Debug.Assert(arrayColumnDesc.Length == 1); 

                // Get track details
                PTS.FSTRACKDETAILS trackDetails;
                PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, arrayColumnDesc[0].pfstrack, out trackDetails)); 

                if (trackDetails.cParas == 0) 
                { 
                    return new ReadOnlyCollection(new List(0));
                } 

                // Get list of paragraphs
                PTS.FSPARADESCRIPTION[] arrayParaDesc;
                PtsHelper.ParaListFromTrack(PtsContext, arrayColumnDesc[0].pfstrack, ref trackDetails, out arrayParaDesc); 

                paragraphResults = new List(arrayParaDesc.Length); 
                for (int i = 0; i < arrayParaDesc.Length; i++) 
                {
                    BaseParaClient paraClient = PtsContext.HandleToObject(arrayParaDesc[i].pfsparaclient) as BaseParaClient; 
                    PTS.ValidateHandle(paraClient);
                    ParagraphResult paragraphResult = paraClient.CreateParagraphResult();
                    if (paragraphResult.HasTextContent)
                    { 
                        hasTextContent = true;
                    } 
                    paragraphResults.Add(paragraphResult); 
                }
            } 
            return new ReadOnlyCollection(paragraphResults);
        }

        ///  
        /// Returns a new collection of ColumnResults for the subpage. Will always
        /// have at least one column. 
        ///  
        /// 
        /// True if any column in the floater has text content, i.e. does not contain only figures/floaters 
        /// 
        /// 
        /// Critical - as this calls the Critical functions PTS.FsQuerySubpageDetails
        ///            and PTS.FsQueryTrackDetails. 
        /// Safe - as this can't be used to pass random parameters.  PtsContext.Context
        ///        is marked Critical for set and _paraHandle is readonly data for this 
        ///        function. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal ReadOnlyCollection GetColumnResults(out bool hasTextContent)
        {
            List columnResults = new List(0);
            Vector contentOffset = new Vector(); 

            // hasTextContent is set to true if any of the columns has text content, not just attached objects. A column has text content if any of 
            // it's paragraph results has text content 
            hasTextContent = false;
 
            // Query subpage details
            PTS.FSSUBPAGEDETAILS subpageDetails;
            PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails));
 
            // Subpage content may be simple or complex -
            // depending of set of features used in the content of the page. 
            // (1) simple subpage (contains only one track) 
            // (2) complex subpage (contains columns)
            if (PTS.ToBoolean(subpageDetails.fSimple)) 
            {
                // (1) simple subpage (contains only one track)
                PTS.FSTRACKDETAILS trackDetails;
                PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, subpageDetails.u.simple.trackdescr.pfstrack, out trackDetails)); 
                if (trackDetails.cParas > 0)
                { 
                    columnResults = new List(1); 
                    ColumnResult columnResult = new ColumnResult(this, ref subpageDetails.u.simple.trackdescr, contentOffset);
                    columnResults.Add(columnResult); 
                    if (columnResult.HasTextContent)
                    {
                        hasTextContent = true;
                    } 
                }
            } 
            else 
            {
                // (2) complex page (contains columns) 
                // cBasicColumns == 0, means that subpage content is empty
                if (subpageDetails.u.complex.cBasicColumns != 0)
                {
                    // Retrieve description for each column. 
                    PTS.FSTRACKDESCRIPTION[] arrayColumnDesc;
                    PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); 
 
                    // Floaters are held at one column; just add the first one
                    columnResults = new List(1); 
                    PTS.FSTRACKDETAILS trackDetails;
                    PTS.Validate(PTS.FsQueryTrackDetails(PtsContext.Context, arrayColumnDesc[0].pfstrack, out trackDetails));
                    if (trackDetails.cParas > 0)
                    { 
                        ColumnResult columnResult = new ColumnResult(this, ref arrayColumnDesc[0], contentOffset);
                        columnResults.Add(columnResult); 
                        if (columnResult.HasTextContent) 
                        {
                            hasTextContent = true; 
                        }
                    }
                }
            } 

            return new ReadOnlyCollection(columnResults); 
        } 

        // ----------------------------------------------------------------- 
        // Returns a collection of ParagraphResults for the column's paragraphs.
        //
        //      pfstrack - Pointer to PTS track representing a column.
        //      parentOffset - Parent offset from the top of the page. 
        //      hasTextContent - true if any paragraph has text content
        // ------------------------------------------------------------------ 
        internal ReadOnlyCollection GetParagraphResultsFromColumn(IntPtr pfstrack, Vector parentOffset, out bool hasTextContent) 
        {
            // Floater has only one column. This is the same as getting children paragraphs. 
            return GetChildrenParagraphResults(out hasTextContent);
        }

        // ----------------------------------------------------------------- 
        // Retrieves text range for contents of the column represented by
        // 'pfstrack'. 
        // 
        //      pfstrack - Pointer to PTS track representing a column.
        // ----------------------------------------------------------------- 
        internal TextContentRange GetTextContentRangeFromColumn(IntPtr pfstrack)
        {
            // Floater has only one column.
            return GetTextContentRange(); 
        }
 
        ///  
        /// Returns tight bounding path geometry.
        ///  
        internal Geometry GetTightBoundingGeometryFromTextPositions(ReadOnlyCollection columns, ReadOnlyCollection floatingElements, ITextPointer startPosition, ITextPointer endPosition, Rect visibleRect)
        {
            Geometry geometry = null;
 
            // Floater always has one column, so we can skip getting a column from the text position range
            Invariant.Assert(columns != null && columns.Count <= 1, "Columns collection is null."); 
            Invariant.Assert(floatingElements != null, "Floating element collection is null."); 
            ReadOnlyCollection paragraphs = (columns.Count > 0) ? columns[0].Paragraphs : new ReadOnlyCollection(new List(0));
 
            if (paragraphs.Count > 0 || floatingElements.Count > 0)
            {
                geometry = TextDocumentView.GetTightBoundingGeometryFromTextPositionsHelper(paragraphs, floatingElements, startPosition, endPosition, TextDpi.FromTextDpi(_dvrTopSpace), visibleRect);
 
                //  restrict geometry to the floater's content rect boundary.
                //  because of end-of-line / end-of-para simulation calculated geometry could be larger. 
                Rect viewport = new Rect(0, 0, TextDpi.FromTextDpi(_contentRect.du), TextDpi.FromTextDpi(_contentRect.dv)); 
                CaretElement.ClipGeometryByViewport(ref geometry, viewport);
            } 
            return (geometry);
        }

        // ----------------------------------------------------------------- 
        // Handle to PTS subpage object.
        // ------------------------------------------------------------------ 
        ///  
        /// Critical - setter is Critical as _paraHandle.Value is Critical for set.
        ///  
        internal IntPtr SubpageHandle
        {
            // getter removed (unused internal API).  If needed, recall from history.
 
            [SecurityCritical]
            set { _paraHandle.Value = value; } 
        } 

        // ----------------------------------------------------------------- 
        // Rect of content in page coordinate system
        // ------------------------------------------------------------------
        internal PTS.FSRECT ContentRect { get { return _contentRect; } }
 
        // Floating element list
        internal ReadOnlyCollection FloatingElementResults 
        { 
            get
            { 
                List floatingElements = new List(0);
                List floatingElementList = _pageContextOfThisPage.FloatingElementList;
                if (floatingElementList != null)
                { 
                    for (int i = 0; i < floatingElementList.Count; i++)
                    { 
                        ParagraphResult paragraphResult = floatingElementList[i].CreateParagraphResult(); 
                        floatingElements.Add(paragraphResult);
                    } 
                }
                return new ReadOnlyCollection(floatingElements);
            }
        } 

 
        // ------------------------------------------------------------------ 
        // Returns whether a floater should be horizontally centered
        // ----------------------------------------------------------------- 
        private bool IsFloaterHorizontallyCentered(PTS.FSRECT rcFloater, PTS.FSRECT rcHostPara)
        {
            Floater floater = Paragraph.Element as Floater;
 
            if(floater == null)
            { 
                return false; 
            }
 
            if(floater.HorizontalAlignment != HorizontalAlignment.Stretch)
            {
                return false;
            } 

            if(rcFloater.du >= rcHostPara.du) 
            { 
                return false;
            } 

            return true;

        } 

        private PTS.FSRECT _contentRect; 
        private PTS.FSRECT _paddingRect; 

        // Page context this para client provides. 
        private PageContext _pageContextOfThisPage = new PageContext();
    }
}

// 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