FloaterParagraph.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / PtsHost / FloaterParagraph.cs / 1 / FloaterParagraph.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// Description: FloaterParagraph class provides a wrapper floater objects. 
//
// History: 
//  11/04/2004 : [....] - created. 
//
//--------------------------------------------------------------------------- 
#pragma warning disable 1634, 1691  // avoid generating warnings about unknown
                                    // message numbers and unknown pragmas for PRESharp contol

using System; 
using System.Diagnostics;
using System.Security;              // SecurityCritical 
using System.Windows; 
using System.Windows.Documents;
using MS.Internal.Documents; 
using MS.Internal.Text;

using MS.Internal.PtsHost.UnsafeNativeMethods;
 
namespace MS.Internal.PtsHost
{ 
    // --------------------------------------------------------------------- 
    // FloaterParagraph class provides a wrapper floater objects.
    // --------------------------------------------------------------------- 
    internal sealed class FloaterParagraph : FloaterBaseParagraph
    {
        //--------------------------------------------------------------------
        // 
        //  Constructors
        // 
        //------------------------------------------------------------------- 

        #region Constructors 

        // ------------------------------------------------------------------
        // Constructor.
        // 
        //      element - Element associated with paragraph.
        //      structuralCache - Content's structural cache 
        // ------------------------------------------------------------------ 
        internal FloaterParagraph(TextElement element, StructuralCache structuralCache)
            : base(element, structuralCache) 
        {
        }

        // ----------------------------------------------------------------- 
        // UpdGetParaChange - Floater paragraph is always new
        // ------------------------------------------------------------------ 
        internal override void UpdGetParaChange( 
            out PTS.FSKCHANGE fskch,            // OUT: kind of change
            out int fNoFurtherChanges)          // OUT: no changes after? 
        {
            base.UpdGetParaChange(out fskch, out fNoFurtherChanges);

            fskch = PTS.FSKCHANGE.fskchNew; 
        }
 
 
        // -----------------------------------------------------------------
        // IDisposable.Dispose 
        // -----------------------------------------------------------------
        public override void Dispose()
        {
            base.Dispose(); 

            if (_mainTextSegment != null) 
            { 
                _mainTextSegment.Dispose();
                _mainTextSegment = null; 
            }
        }

 
        #endregion Constructors
 
        //------------------------------------------------------------------- 
        //
        //  PTS callbacks 
        //
        //--------------------------------------------------------------------

        #region PTS callbacks 

        //------------------------------------------------------------------- 
        // CreateParaclient 
        //--------------------------------------------------------------------
        internal override void CreateParaclient( 
            out IntPtr paraClientHandle)        // OUT: opaque to PTS paragraph client
        {
#pragma warning disable 6518
            // Disable PRESharp warning 6518. FloaterParaClient is an UnmamangedHandle, that adds itself 
            // to HandleMapper that holds a reference to it. PTS manages lifetime of this object, and
            // calls DestroyParaclient to get rid of it. DestroyParaclient will call Dispose() on the object 
            // and remove it from HandleMapper. 
            FloaterParaClient paraClient =  new FloaterParaClient(this);
            paraClientHandle = paraClient.Handle; 
#pragma warning restore 6518

            // Create the main text segment
            if (_mainTextSegment == null) 
            {
                _mainTextSegment = new ContainerParagraph(Element, StructuralCache); 
            } 
        }
 
        internal override void CollapseMargin(
            BaseParaClient paraClient,          // IN:
            MarginCollapsingState mcs,          // IN:  input margin collapsing state
            uint fswdir,                        // IN:  current direction (of the track, in which margin collapsing is happening) 
            bool suppressTopSpace,              // IN:  suppress empty space at the top of page
            out int dvr)                        // OUT: dvr, calculated based on margin collapsing state 
        { 
            // Floaters are not participating in margin collapsing.
            // Top space is always suppressed 
            dvr = 0;
        }

        //-------------------------------------------------------------------- 
        // GetFloaterProperties
        //------------------------------------------------------------------- 
        internal override void GetFloaterProperties( 
            uint fswdirTrack,                       // IN:  direction of track
            out PTS.FSFLOATERPROPS fsfloaterprops)  // OUT: properties of the floater 
        {
            fsfloaterprops = new PTS.FSFLOATERPROPS();
            fsfloaterprops.fFloat   = PTS.True;                     // Floater
            fsfloaterprops.fskclear = PTS.WrapDirectionToFskclear((WrapDirection)Element.GetValue(Block.ClearFloatersProperty)); 

            // Get floater alignment from HorizontalAlignment of the floater element. 
            switch (HorizontalAlignment) 
            {
                case HorizontalAlignment.Right: 
                    fsfloaterprops.fskfloatalignment = PTS.FSKFLOATALIGNMENT.fskfloatalignMax;
                    break;
                case HorizontalAlignment.Center:
                    fsfloaterprops.fskfloatalignment = PTS.FSKFLOATALIGNMENT.fskfloatalignCenter; 
                    break;
                case HorizontalAlignment.Left: 
                default: 
                    fsfloaterprops.fskfloatalignment = PTS.FSKFLOATALIGNMENT.fskfloatalignMin;
                    break; 
            }


            fsfloaterprops.fskwr = PTS.WrapDirectionToFskwrap(WrapDirection); 

            // Always delay floaters if there is no progress. 
            fsfloaterprops.fDelayNoProgress = PTS.True; 
        }
 
        //--------------------------------------------------------------------
        // FormatFloaterContentFinite
        //-------------------------------------------------------------------
        /// 
        /// Critical - as this calls Critical functions PTS.FsDestroySubpage,
        ///            CreateSubpageFiniteHelper and Critical setter for paraClient.SubpageHandle. 
        ///            This takes the unvalidated parameter footnoteRejector. 
        /// 
        [SecurityCritical] 
        internal override void FormatFloaterContentFinite(
            FloaterBaseParaClient paraClient,       // IN:
            IntPtr pbrkrecIn,                   // IN:  break record---use if !IntPtr.Zero
            int fBRFromPreviousPage,            // IN:  break record was created on previous page 
            IntPtr footnoteRejector,            // IN:
            int fEmptyOk,                       // IN:  is it OK not to add anything? 
            int fSuppressTopSpace,              // IN:  suppress empty space at the top of the page 
            uint fswdir,                        // IN:  direction of Track
            int fAtMaxWidth,                    // IN:  formating is at full width of column 
            int durAvailable,                   // IN:  width of available space
            int dvrAvailable,                   // IN:  height of available space
            PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn,
                                                // IN: suppress breaks at track start? 
            out PTS.FSFMTR fsfmtr,              // OUT: result of formatting
            out IntPtr pfsFloatContent,         // OUT: opaque for PTS pointer pointer to formatted content 
            out IntPtr pbrkrecOut,              // OUT: pointer to the floater content break record 
            out int durFloaterWidth,            // OUT: floater width
            out int dvrFloaterHeight,           // OUT: floater height 
            out PTS.FSBBOX fsbbox,              // OUT: floater bbox
            out int cPolygons,                  // OUT: number of polygons
            out int cVertices)                  // OUT: total number of vertices in all polygons
        { 
            uint fswdirPara = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty)));
 
            int subpageWidth, subpageHeight; 
            int dvrTopSpace;
            int cColumns; 
            PTS.FSRECT fsrcSubpageMargin;
            PTS.FSCOLUMNINFO[] columnInfoCollection;
            IntPtr pmcsclientOut;
            double specifiedWidth; 
            MbpInfo mbp;
 
            Invariant.Assert(paraClient is FloaterParaClient); 

            // If horizontal alignment is Stretch and we are not formatting at max width, 
            // we cannot proceed.
            if (IsFloaterRejected(PTS.ToBoolean(fAtMaxWidth), TextDpi.FromTextDpi(durAvailable)))
            {
                durFloaterWidth = dvrFloaterHeight = 0; 
                cPolygons = cVertices = 0;
                fsfmtr = new PTS.FSFMTR(); 
                fsfmtr.kstop = PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace; 
                fsfmtr.fContainsItemThatStoppedBeforeFootnote = PTS.False;
                fsfmtr.fForcedProgress = PTS.False; 
                fsbbox = new PTS.FSBBOX();
                fsbbox.fDefined = PTS.False;
                pbrkrecOut = IntPtr.Zero;
                pfsFloatContent = IntPtr.Zero; 
            }
            else 
            { 
                // When formatting bottomless page, PTS may format paragraphs as finite. This happens
                // in case of multiple columns. In this case make sure that height is not too big. 
                if (!StructuralCache.CurrentFormatContext.FinitePage)
                {
                    if (Double.IsInfinity(StructuralCache.CurrentFormatContext.PageHeight))
                    { 
                        if (dvrAvailable > PTS.dvBottomUndefined / 2)
                        { 
                            dvrAvailable = Math.Min(dvrAvailable, PTS.dvBottomUndefined / 2); 
                            fEmptyOk = PTS.False;
                        } 
                    }
                    else
                    {
                        dvrAvailable = Math.Min(dvrAvailable, TextDpi.ToTextDpi(StructuralCache.CurrentFormatContext.PageHeight)); 
                    }
                } 
 
                // Initialize the subpage size. PTS subpage margin is always set to 0 for Floaters.
                // If width on floater is specified, use the specified value. 
                // Margin, border and padding of the floater is extracted from available subpage height
                mbp = MbpInfo.FromElement(Element);

                // We do not mirror margin as it's used to dist text left and right, and is unnecessary. 
                // Clip Floater.Width to available width
                specifiedWidth = CalculateWidth(TextDpi.FromTextDpi(durAvailable)); 
                AdjustDurAvailable(specifiedWidth, ref durAvailable, out subpageWidth); 
                subpageHeight = Math.Max(1, dvrAvailable - (mbp.MBPTop + mbp.MBPBottom));
                fsrcSubpageMargin = new PTS.FSRECT(); 
                fsrcSubpageMargin.du = subpageWidth;
                fsrcSubpageMargin.dv = subpageHeight;

                // Initialize column info. Floater always has just 1 column. 
                cColumns = 1;
                columnInfoCollection = new PTS.FSCOLUMNINFO[cColumns]; 
                columnInfoCollection[0].durBefore = 0; 
                columnInfoCollection[0].durWidth = subpageWidth;
 
                // Format subpage
                CreateSubpageFiniteHelper(PtsContext, pbrkrecIn, fBRFromPreviousPage, _mainTextSegment.Handle,
                    footnoteRejector, fEmptyOk, PTS.True, fswdir, subpageWidth, subpageHeight,
                    ref fsrcSubpageMargin, cColumns, columnInfoCollection, PTS.False, fsksuppresshardbreakbeforefirstparaIn, 
                    out fsfmtr, out pfsFloatContent,
                    out pbrkrecOut, out dvrFloaterHeight, out fsbbox, out pmcsclientOut, out dvrTopSpace); 
 
                // Initialize subpage metrics
                if (fsfmtr.kstop >= PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace)   // No progress or collision 
                {
                    Debug.Assert(pmcsclientOut == IntPtr.Zero);
                    durFloaterWidth = dvrFloaterHeight = 0;
                    cPolygons = cVertices = 0; 
                    //pbrkrecpara = IntPtr.Zero;
                } 
                else 
                {
                    // PTS subpage does not support autosizing, but Floater needs to autosize to its 
                    // content. To workaround this problem, second format of subpage is performed, if
                    // necessary. It means that if the width of bounding box is smaller than subpage's
                    // width, second formatting is performed.
                    // However, if HorizontalAlignment is set to Stretch we should not reformat because floater 
                    // should be at max width
                    if (PTS.ToBoolean(fsbbox.fDefined)) 
                    { 
                        if(fsbbox.fsrc.du < subpageWidth && Double.IsNaN(specifiedWidth) && HorizontalAlignment != HorizontalAlignment.Stretch)
                        { 
                            // There is a need to reformat PTS subpage, so destroy any resourcces allocated by PTS
                            // during previous formatting.
                            if (pfsFloatContent != IntPtr.Zero)
                            { 
                                PTS.Validate(PTS.FsDestroySubpage(PtsContext.Context, pfsFloatContent), PtsContext);
                                pfsFloatContent = IntPtr.Zero; 
                            } 
                            if (pbrkrecOut != IntPtr.Zero)
                            { 
                                PTS.Validate(PTS.FsDestroySubpageBreakRecord(PtsContext.Context, pbrkrecOut), PtsContext);
                                pbrkrecOut = IntPtr.Zero;
                            }
                            if (pmcsclientOut != IntPtr.Zero) 
                            {
                                MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState; 
                                PTS.ValidateHandle(mcs); 
                                mcs.Dispose();
                                pmcsclientOut = IntPtr.Zero; 
                            }
                            // Create subpage with new width.
                            subpageWidth = fsbbox.fsrc.du + 1; // add 1/300px to avoid rounding errors
                            fsrcSubpageMargin.du = subpageWidth; 
                            fsrcSubpageMargin.dv = subpageHeight;
                            columnInfoCollection[0].durWidth = subpageWidth; 
                            CreateSubpageFiniteHelper(PtsContext, pbrkrecIn, fBRFromPreviousPage, _mainTextSegment.Handle, 
                                 footnoteRejector, fEmptyOk, PTS.True, fswdir, subpageWidth, subpageHeight,
                                ref fsrcSubpageMargin, cColumns, columnInfoCollection, PTS.False, fsksuppresshardbreakbeforefirstparaIn, 
                                out fsfmtr, out pfsFloatContent,
                                out pbrkrecOut, out dvrFloaterHeight, out fsbbox, out pmcsclientOut, out dvrTopSpace);
                        }
                    } 
                    else
                    { 
                        subpageWidth = TextDpi.ToTextDpi(TextDpi.MinWidth); 
                    }
 
                    // Destroy objects created by PTS, but not used here.
                    if (pmcsclientOut != IntPtr.Zero)
                    {
                        MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState; 
                        PTS.ValidateHandle(mcs);
                        mcs.Dispose(); 
                        pmcsclientOut = IntPtr.Zero; 
                    }
 
                    // Get the size of the floater. For height PTS already reports calculated value.
                    // But width is the same as subpage width. Add margin values here since we do not use
                    // distance to text anymore
                    durFloaterWidth = subpageWidth + mbp.MBPLeft + mbp.MBPRight; 

                    // Add back all MBP values since we do not use dist to text 
                    dvrFloaterHeight += mbp.MBPTop + mbp.MBPBottom; 
                    // Check if floater width fits in available width. It may exceed available width because borders and
                    // padding are added. 


                    fsbbox.fsrc.u = 0;
                    fsbbox.fsrc.v = 0; 
                    fsbbox.fsrc.du = durFloaterWidth;
                    fsbbox.fsrc.dv = dvrFloaterHeight; 
                    fsbbox.fDefined = PTS.True; 

                    // Tight wrap is disabled for now. 
                    cPolygons = cVertices = 0;

                    if(durFloaterWidth > durAvailable || dvrFloaterHeight > dvrAvailable)
                    { 
                        if(PTS.ToBoolean(fEmptyOk))
                        { 
                            // Get rid of any previous formatting 
                            if (pfsFloatContent != IntPtr.Zero)
                            { 
                                PTS.Validate(PTS.FsDestroySubpage(PtsContext.Context, pfsFloatContent), PtsContext);
                                pfsFloatContent = IntPtr.Zero;
                            }
                            if (pbrkrecOut != IntPtr.Zero) 
                            {
                                PTS.Validate(PTS.FsDestroySubpageBreakRecord(PtsContext.Context, pbrkrecOut), PtsContext); 
                                pbrkrecOut = IntPtr.Zero; 
                            }
                            cPolygons = cVertices = 0; 
                            fsfmtr.kstop = PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace;
                        }
                        else
                        { 
                            fsfmtr.fForcedProgress = PTS.True;
                        } 
                    } 
                }
            } 

            // Update handle to PTS subpage.
            ((FloaterParaClient)paraClient).SubpageHandle = pfsFloatContent;
        } 

        //------------------------------------------------------------------- 
        // FormatFloaterContentBottomless 
        //-------------------------------------------------------------------
        ///  
        /// Critical - as this calls Critical functions PTS.FsDestroySubpage,
        ///            CreateSubpageBottomlessHelper and setter for SubpageHandle.
        /// Safe - as the parameters passed in are either generated in this function
        ///        or they are Critical for set. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void FormatFloaterContentBottomless( 
            FloaterBaseParaClient paraClient,       // IN:
            int fSuppressTopSpace,              // IN:  suppress empty space at the top of the page 
            uint fswdir,                        // IN:  direction of track
            int fAtMaxWidth,                    // IN:  formating is at full width of column
            int durAvailable,                   // IN:  width of available space
            int dvrAvailable,                   // IN:  height of available space 
            out PTS.FSFMTRBL fsfmtrbl,          // OUT: result of formatting
            out IntPtr pfsFloatContent,         // OUT: opaque for PTS pointer pointer to formatted content 
            out int durFloaterWidth,            // OUT: floater width 
            out int dvrFloaterHeight,           // OUT: floater height
            out PTS.FSBBOX fsbbox,              // OUT: floater bbox 
            out int cPolygons,                  // OUT: number of polygons
            out int cVertices)                  // OUT: total number of vertices in all polygons
        {
            uint fswdirPara = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty))); 

            Invariant.Assert(paraClient is FloaterParaClient); 
 
            int subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin;
            int dvrTopSpace, fPageBecomesUninterruptable; 
            int cColumns;
            PTS.FSCOLUMNINFO[] columnInfoCollection;
            IntPtr pmcsclientOut;
            MbpInfo mbp; 
            double specifiedWidth;
 
            // If horizontal alignment is Stretch and we are not formatting at max width, 
            // we cannot proceed.
            if (IsFloaterRejected(PTS.ToBoolean(fAtMaxWidth), TextDpi.FromTextDpi(durAvailable))) 
            {
                // Set foater width, height to be greater than available values to signal to PTS that floater does not fit in the space
                durFloaterWidth = durAvailable + 1;
                dvrFloaterHeight = dvrAvailable + 1; 
                cPolygons = cVertices = 0;
                fsfmtrbl = PTS.FSFMTRBL.fmtrblInterrupted; 
                fsbbox = new PTS.FSBBOX(); 
                fsbbox.fDefined = PTS.False;
                pfsFloatContent = IntPtr.Zero; 
            }
            else
            {
                // Initialize the subpage size. PTS subpage margin is always set to 0 for Floaters. 
                // If width on floater is specified, use the specified value.
                // Margin, border and padding of the floater is extracted from available subpage width. 
                mbp = MbpInfo.FromElement(Element); 

                specifiedWidth = CalculateWidth(TextDpi.FromTextDpi(durAvailable)); 
                AdjustDurAvailable(specifiedWidth, ref durAvailable, out subpageWidth);
                durSubpageMargin = subpageWidth;
                urSubpageMargin = vrSubpageMargin = 0;
 
                // Initialize column info. Floater always has just 1 column.
                cColumns = 1; 
                columnInfoCollection = new PTS.FSCOLUMNINFO[cColumns]; 
                columnInfoCollection[0].durBefore = 0;
                columnInfoCollection[0].durWidth = subpageWidth; 

                // Create subpage
                InvalidateMainTextSegment();
                CreateSubpageBottomlessHelper(PtsContext, _mainTextSegment.Handle, PTS.True, 
                    fswdir, subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin,
                    cColumns, columnInfoCollection, 
                    out fsfmtrbl, out pfsFloatContent, out dvrFloaterHeight, out fsbbox, out pmcsclientOut, 
                    out dvrTopSpace, out fPageBecomesUninterruptable);
 
                if (fsfmtrbl != PTS.FSFMTRBL.fmtrblCollision)
                {
                    // PTS subpage does not support autosizing, but Floater needs to autosize to its
                    // content. To workaround this problem, second format of subpage is performed, if 
                    // necessary. It means that if the width of bounding box is smaller than subpage's
                    // width, second formatting is performed. 
                    // However, if HorizontalAlignment is set to Stretch we should not reformat because 
                    // floater should be at full column width
                    if (PTS.ToBoolean(fsbbox.fDefined)) 
                    {
                        if(fsbbox.fsrc.du < subpageWidth && Double.IsNaN(specifiedWidth) && HorizontalAlignment != HorizontalAlignment.Stretch)
                        {
                            // There is a need to reformat PTS subpage, so destroy any resourcces allocated by PTS 
                            // during previous formatting.
                            if (pfsFloatContent != IntPtr.Zero) 
                            { 
                                PTS.Validate(PTS.FsDestroySubpage(PtsContext.Context, pfsFloatContent), PtsContext);
                            } 
                            if (pmcsclientOut != IntPtr.Zero)
                            {
                                MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                                PTS.ValidateHandle(mcs); 
                                mcs.Dispose();
                                pmcsclientOut = IntPtr.Zero; 
                            } 
                            // Create subpage with new width.
                            subpageWidth = durSubpageMargin = fsbbox.fsrc.du + 1; // add 1/300px to avoid rounding errors 
                            columnInfoCollection[0].durWidth = subpageWidth;
                            CreateSubpageBottomlessHelper(PtsContext, _mainTextSegment.Handle, PTS.True,
                                fswdir, subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin,
                                cColumns, columnInfoCollection, 
                                out fsfmtrbl, out pfsFloatContent, out dvrFloaterHeight, out fsbbox, out pmcsclientOut,
                                out dvrTopSpace, out fPageBecomesUninterruptable); 
                        } 
                    }
                    else 
                    {
                        subpageWidth = TextDpi.ToTextDpi(TextDpi.MinWidth);
                    }
 
                    // Destroy objects created by PTS, but not used here.
                    if (pmcsclientOut != IntPtr.Zero) 
                    { 
                        MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                        PTS.ValidateHandle(mcs); 
                        mcs.Dispose();
                        pmcsclientOut = IntPtr.Zero;
                    }
 
                    // Get the size of the floater. For height PTS already reports calculated value.
                    // But width is the same as subpage width. 
                    durFloaterWidth = subpageWidth + mbp.MBPLeft + mbp.MBPRight; 

                    dvrFloaterHeight += mbp.MBPTop + mbp.MBPBottom; 

                    // Check if floater width fits in available width. It may exceed available width because borders
                    // and padding are added.
                    if ( dvrFloaterHeight > dvrAvailable || 
                         (durFloaterWidth > durAvailable && !PTS.ToBoolean(fAtMaxWidth))
                       ) 
                    { 
                        // Get rid of any previous formatting
                        if (pfsFloatContent != IntPtr.Zero) 
                        {
                            PTS.Validate(PTS.FsDestroySubpage(PtsContext.Context, pfsFloatContent), PtsContext);
                        }
 
                        Debug.Assert(pmcsclientOut == IntPtr.Zero);
                        cPolygons = cVertices = 0; 
                        pfsFloatContent = IntPtr.Zero; 
                    }
                    else 
                    {
                        // Width and height are OK, format floater
                        // Adjust bounding box to cover entire floater.
                        fsbbox.fsrc.u = 0; 
                        fsbbox.fsrc.v = 0;
                        fsbbox.fsrc.du = durFloaterWidth; 
                        fsbbox.fsrc.dv = dvrFloaterHeight; 

                        // Tight wrap is disabled for now. 
                        cPolygons = cVertices = 0;
                    }
                }
                else 
                {
                    Debug.Assert(pmcsclientOut == IntPtr.Zero); 
                    durFloaterWidth = dvrFloaterHeight = 0; 
                    cPolygons = cVertices = 0;
                    pfsFloatContent = IntPtr.Zero; 
                }
            }

            // Update handle to PTS subpage. 
            ((FloaterParaClient)paraClient).SubpageHandle = pfsFloatContent;
        } 
 
        //--------------------------------------------------------------------
        // UpdateBottomlessFloaterContent 
        //-------------------------------------------------------------------
        internal override void UpdateBottomlessFloaterContent(
            FloaterBaseParaClient paraClient,       // IN:
            int fSuppressTopSpace,              // IN:  suppress empty space at the top of the page 
            uint fswdir,                        // IN:  direction of track
            int fAtMaxWidth,                    // IN:  formating is at full width of column 
            int durAvailable,                   // IN:  width of available space 
            int dvrAvailable,                   // IN:  height of available space
            IntPtr pfsFloatContent,             // IN:  floater content (in UIElementParagraph, this is an alias to the paraClient) 
            out PTS.FSFMTRBL fsfmtrbl,          // OUT: result of formatting
            out int durFloaterWidth,            // OUT: floater width
            out int dvrFloaterHeight,           // OUT: floater height
            out PTS.FSBBOX fsbbox,              // OUT: floater bbox 
            out int cPolygons,                  // OUT: number of polygons
            out int cVertices)                  // OUT: total number of vertices in all polygons 
        { 
            fsfmtrbl = default(PTS.FSFMTRBL);
            durFloaterWidth = dvrFloaterHeight = cPolygons = cVertices = 0; fsbbox = new PTS.FSBBOX(); 

            Invariant.Assert(false, "No appropriate handling for update in attached object floater.");
        }
 

        //-------------------------------------------------------------------- 
        // GetMCSClientAfterFloater 
        //--------------------------------------------------------------------
        internal override void GetMCSClientAfterFloater( 
            uint fswdirTrack,                   // IN:  direction of Track
            MarginCollapsingState mcs,          // IN:  input margin collapsing state
            out IntPtr pmcsclientOut)           // OUT: MCSCLIENT that floater will return to track
        { 
                        // Floaters margins are added during formatting.
            if (mcs != null) 
            { 
                pmcsclientOut = mcs.Handle;
            } 
            else
            {
                pmcsclientOut = IntPtr.Zero;
            } 
        }
 
        #endregion PTS callbacks 

        //------------------------------------------------------------------- 
        //
        //  Internal Methods
        //
        //-------------------------------------------------------------------- 

        #region Internal Methods 
 
        // -----------------------------------------------------------------
        // Clear previously accumulated update info. 
        // -----------------------------------------------------------------
        internal override void ClearUpdateInfo()
        {
            if (_mainTextSegment != null) 
            {
                _mainTextSegment.ClearUpdateInfo(); 
            } 
            base.ClearUpdateInfo();
        } 

        // -----------------------------------------------------------------
        // Invalidate content's structural cache.
        // 
        //      startPosition - Position to start invalidation from.
        // 
        // Returns: 'true' if entire paragraph is invalid. 
        // ------------------------------------------------------------------
        internal override bool InvalidateStructure(int startPosition) 
        {
            Debug.Assert(ParagraphEndCharacterPosition >= startPosition);
            if (_mainTextSegment != null)
            { 
                if (_mainTextSegment.InvalidateStructure(startPosition))
                { 
                    _mainTextSegment.Dispose(); 
                    _mainTextSegment = null;
                } 
            }
            return (_mainTextSegment == null);
        }
 
        // -----------------------------------------------------------------
        // Invalidate accumulated format caches. 
        // ------------------------------------------------------------------ 
        internal override void InvalidateFormatCache()
        { 
            if (_mainTextSegment != null)
            {
                _mainTextSegment.InvalidateFormatCache();
            } 
        }
 
        ///  
        /// Update number of characters consumed by the main text segment.
        ///  
        internal void UpdateSegmentLastFormatPositions()
        {
            _mainTextSegment.UpdateLastFormatPositions();
        } 

        #endregion Internal Methods 
 
        //--------------------------------------------------------------------
        // 
        //  Private Methods
        //
        //-------------------------------------------------------------------
 
        #region Private Methods
 
        ///  
        /// Adjust the width available for the Floater.
        ///  
        private void AdjustDurAvailable(double specifiedWidth, ref int durAvailable, out int subpageWidth)
        {
            // If width on floater is specified, use the specified value.
            // Use page size from current format context to limit MBP 
            MbpInfo mbp = MbpInfo.FromElement(Element);
            if (!Double.IsNaN(specifiedWidth)) 
            { 
                TextDpi.EnsureValidPageWidth(ref specifiedWidth);
                // If specified width is greater than available width, do not exceed available width 
                int durSpecified = TextDpi.ToTextDpi(specifiedWidth);
                if ((durSpecified + mbp.MarginRight + mbp.MarginLeft) <= durAvailable)
                {
                    // Set durAvailable to durSpecified plus margins, which will be added later. 
                    // Set subpage width to specified width less border and padding
                    durAvailable = durSpecified + mbp.MarginLeft + mbp.MarginRight; 
                    subpageWidth = Math.Max(1, durSpecified - (mbp.BPLeft + mbp.BPRight)); 
                 }
                 else 
                 {
                     // Use durAvailable, less MBP to set subpage width. We cannot set figure to specified width
                     subpageWidth = Math.Max(1, durAvailable - (mbp.MBPLeft + mbp.MBPRight));
                 } 
            }
            else 
            { 
                // No width specified. Use durAvailable, less MBP to set subpage width.
                subpageWidth = Math.Max(1, durAvailable - (mbp.MBPLeft + mbp.MBPRight)); 
            }
        }

        //-------------------------------------------------------------------- 
        // CreateSubpageFiniteHelper
        // NOTE: This helper is useful for debugging the caller of this function 
        //       because the debugger cannot show local variables in unsafe methods. 
        //-------------------------------------------------------------------
        ///  
        /// Critical, because:
        ///     a) calls Critical function PTS.FsCreateSubpageFinite and passes
        ///        pointer parameters directly that'll be written to,
        ///     b) calls the Critical constructor of SubpageBreakRecord, 
        ///     c) it is unsafe method.
        ///  
        [SecurityCritical] 
        private unsafe void CreateSubpageFiniteHelper(
            PtsContext ptsContext,              // IN:  ptr to FS context 
            IntPtr brParaIn,                    // IN:  break record---use if !NULL
            int fFromPreviousPage,              // IN:  break record was created on previous page
            IntPtr nSeg,                        // IN:  name of the segment to start from-if pointer to break rec is NULL
            IntPtr pFtnRej,                     // IN:  pftnrej 
            int fEmptyOk,                       // IN:  fEmptyOK
            int fSuppressTopSpace,              // IN:  fSuppressTopSpace 
            uint fswdir,                        // IN:  fswdir 
            int lWidth,                         // IN:  width of subpage
            int lHeight,                        // IN:  height of subpage 
            ref PTS.FSRECT rcMargin,            // IN:  rectangle within subpage margins
            int cColumns,                       // IN:  number of columns
            PTS.FSCOLUMNINFO[] columnInfoCollection, // IN:  array of column info
            int fApplyColumnBalancing,          // IN:  apply column balancing? 
            PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn,
                                                // IN: suppress breaks at track start? 
            out PTS.FSFMTR fsfmtr,              // OUT: why formatting was stopped 
            out IntPtr pSubPage,                // OUT: ptr to the subpage
            out IntPtr brParaOut,               // OUT: break record of the subpage 
            out int dvrUsed,                    // OUT: dvrUsed
            out PTS.FSBBOX fsBBox,              // OUT: subpage bbox
            out IntPtr pfsMcsClient,            // OUT: margin collapsing state at the bottom
            out int topSpace)                   // OUT: top space due to collapsed margins 
        {
            // Exceptions don't need to pop, as the top level measure context will be nulled out if thrown. 
            StructuralCache.CurrentFormatContext.PushNewPageData(new Size(TextDpi.FromTextDpi(lWidth), TextDpi.FromTextDpi(lHeight)), 
                                                                 new Thickness(),
                                                                 false, 
                                                                 true);

            fixed (PTS.FSCOLUMNINFO* rgColumnInfo = columnInfoCollection)
            { 
                PTS.Validate(PTS.FsCreateSubpageFinite(ptsContext.Context, brParaIn, fFromPreviousPage, nSeg,
                    pFtnRej, fEmptyOk, fSuppressTopSpace, fswdir, lWidth, lHeight, 
                    ref rcMargin, cColumns, rgColumnInfo, PTS.False, 
                    0, null, null, 0, null, null, PTS.False,
                    fsksuppresshardbreakbeforefirstparaIn, 
                    out fsfmtr, out pSubPage, out brParaOut, out dvrUsed, out fsBBox, out pfsMcsClient, out topSpace), ptsContext);
            }

            StructuralCache.CurrentFormatContext.PopPageData(); 
        }
 
        //------------------------------------------------------------------- 
        // CreateSubpageBottomlessHelper
        // NOTE: This helper is useful for debugging the caller of this function 
        //       because the debugger cannot show local variables in unsafe methods.
        //-------------------------------------------------------------------
        /// 
        /// Critical, because: 
        ///     a) calls Critical function PTS.FsCreateSubpageBottomless and passes
        ///        pointer parameters directly that'll be written to, 
        ///     b) it is unsafe method. 
        /// 
        [SecurityCritical] 
        private unsafe void CreateSubpageBottomlessHelper(
            PtsContext ptsContext,              // IN:  ptr to FS context
            IntPtr nSeg,                        // IN:  name of the segment to start from
            int fSuppressTopSpace,              // IN:  suppress top space? 
            uint fswdir,                        // IN:  fswdir
            int lWidth,                         // IN:  width of subpage 
            int urMargin,                       // IN:  ur of margin 
            int durMargin,                      // IN:  dur of margin
            int vrMargin,                       // IN:  vr of margin 
            int cColumns,                       // IN:  number of columns
            PTS.FSCOLUMNINFO[] columnInfoCollection, // IN:  array of column info
            out PTS.FSFMTRBL pfsfmtr,           // OUT: why formatting was stopped
            out IntPtr ppSubPage,               // OUT: ptr to the subpage 
            out int pdvrUsed,                   // OUT: dvrUsed
            out PTS.FSBBOX pfsBBox,             // OUT: subpage bbox 
            out IntPtr pfsMcsClient,            // OUT: margin collapsing state at the bottom 
            out int pTopSpace,                  // OUT: top space due to collapsed margins
            out int fPageBecomesUninterruptible)// OUT: interruption is prohibited from now on 
        {
            // Exceptions don't need to pop, as the top level measure context will be nulled out if thrown.
            StructuralCache.CurrentFormatContext.PushNewPageData(new Size(TextDpi.FromTextDpi(lWidth), TextDpi.MaxWidth),
                                                                 new Thickness(), 
                                                                 false,
                                                                 false); 
 
            fixed (PTS.FSCOLUMNINFO* rgColumnInfo = columnInfoCollection)
            { 
                PTS.Validate(PTS.FsCreateSubpageBottomless(ptsContext.Context, nSeg, fSuppressTopSpace,
                    fswdir, lWidth, urMargin, durMargin, vrMargin,
                    cColumns, rgColumnInfo, 0, null, null, 0, null, null, PTS.False,
                    out pfsfmtr, out ppSubPage, out pdvrUsed, out pfsBBox, out pfsMcsClient, 
                    out pTopSpace, out fPageBecomesUninterruptible), ptsContext);
            } 
 
            StructuralCache.CurrentFormatContext.PopPageData();
        } 

        /// 
        /// Invalidates main text segment for bottomless pages if DTR list for this para is non-null.
        ///  
        private void InvalidateMainTextSegment()
        { 
            DtrList dtrs = StructuralCache.DtrsFromRange(ParagraphStartCharacterPosition, LastFormatCch); 
            if (dtrs != null && dtrs.Length > 0)
            { 
                _mainTextSegment.InvalidateStructure(dtrs[0].StartIndex);
            }
        }
 
        //--------------------------------------------------------------------
        // HorizontalAlignment 
        // Returns the horizontal alignment of this floater. Either calculated from the Floater or Figure properties. 
        //-------------------------------------------------------------------
        private HorizontalAlignment HorizontalAlignment 
        {
            get
            {
                if(Element is Floater) 
                {
                    return ((Floater)Element).HorizontalAlignment; 
                } 

                Figure figure = (Figure) Element; 
                FigureHorizontalAnchor horizontalAnchor = figure.HorizontalAnchor;

                if(horizontalAnchor == FigureHorizontalAnchor.PageLeft ||
                   horizontalAnchor == FigureHorizontalAnchor.ContentLeft || 
                   horizontalAnchor == FigureHorizontalAnchor.ColumnLeft)
                { 
                    return HorizontalAlignment.Left; 
                }
                else if(horizontalAnchor == FigureHorizontalAnchor.PageRight || 
                   horizontalAnchor == FigureHorizontalAnchor.ContentRight ||
                   horizontalAnchor == FigureHorizontalAnchor.ColumnRight)
                {
                    return HorizontalAlignment.Right; 
                }
                else if(horizontalAnchor == FigureHorizontalAnchor.PageCenter || 
                   horizontalAnchor == FigureHorizontalAnchor.ContentCenter || 
                   horizontalAnchor == FigureHorizontalAnchor.ColumnCenter)
                { 
                    return HorizontalAlignment.Center;
                }
                else
                { 
                    Debug.Assert(false, "Unknown type of anchor.");
                    return HorizontalAlignment.Center; 
                } 
            }
        } 

        //--------------------------------------------------------------------
        // WrapDirection
        // Returns the wrap direction of this floater. Either calculated from the Floater or Figure properties. 
        //--------------------------------------------------------------------
        private WrapDirection WrapDirection 
        { 
            get
            { 
                if(Element is Floater)
                {
                    // Wrap text on both sides of the floater in all cases except where alignment is stretch, in which
                    // case text must not be wrapped on either side 
                    if (HorizontalAlignment == HorizontalAlignment.Stretch)
                    { 
                        return WrapDirection.None; 
                    }
                    else 
                    {
                        return WrapDirection.Both;
                    }
                } 
                else
                { 
                    Figure figure = (Figure) Element; 

                    return figure.WrapDirection; 
                }
            }
        }
 

 
        //------------------------------------------------------------------- 
        //  Calculates the width of a floater - Returns NaN for auto sized floaters
        //-------------------------------------------------------------------- 
        private double CalculateWidth(double spaceAvailable)
        {
            if(Element is Floater)
            { 
                return (double)((Floater)Element).Width;
            } 
            else 
            {
                bool isWidthAuto; 

                double desiredSize = FigureHelper.CalculateFigureWidth(StructuralCache, (Figure)Element,
                                                                       ((Figure)Element).Width,
                                                                       out isWidthAuto); 

                if(isWidthAuto) 
                { 
                    return Double.NaN;
                } 

                return Math.Min(desiredSize, spaceAvailable);
            }
        } 

        //------------------------------------------------------------------- 
        //  Determines whether a floater should be rejected or not 
        //-------------------------------------------------------------------
        private bool IsFloaterRejected(bool fAtMaxWidth, double availableSpace) 
        {
            if(fAtMaxWidth)
            {
                return false; 
            }
 
            if(Element is Floater && HorizontalAlignment != HorizontalAlignment.Stretch) 
            {
                return false; 
            }
            else if(Element is Figure)
            {
                FigureLength figureLength = ((Figure)Element).Width; 
                if(figureLength.IsAuto)
                { 
                    return false; 
                }
                if(figureLength.IsAbsolute && figureLength.Value < availableSpace) 
                {
                    return false;
                }
            } 
            return true;
        } 
 
        #endregion Private Methods
 
        //-------------------------------------------------------------------
        //
        //  Private Fields
        // 
        //--------------------------------------------------------------------
 
        #region Private Fields 

        // ----------------------------------------------------------------- 
        // Main text segment.
        // ------------------------------------------------------------------
        private BaseParagraph _mainTextSegment;
 
        #endregion Private Fields
    } 
} 

#pragma warning enable 1634, 1691 


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