예제 #1
0
        //-------------------------------------------------------------------
        // CollapseMargin
        //-------------------------------------------------------------------
        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
        {
            MbpInfo mbp = MbpInfo.FromElement(Element, StructuralCache.TextFormatterHost.PixelsPerDip);
            MarginCollapsingState mcsNew;
            int margin;

            MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsNew, out margin);

            if (suppressTopSpace)
            {
                dvr = 0;
            }
            else
            {
                dvr = margin;
                if (mcsNew != null)
                {
                    dvr += mcsNew.Margin;
                }
            }
            if (mcsNew != null)
            {
                mcsNew.Dispose();
            }
        }
예제 #2
0
        internal void FormatCellBottomless(uint fswdir, double width, out PTS.FSFMTRBL fmtrbl, out int dvrUsed)
        {
            if (this.CellParagraph.StructuralCache.DtrList != null)
            {
                this.CellParagraph.InvalidateStructure(TextContainerHelper.GetCPFromElement(this.CellParagraph.StructuralCache.TextContainer, this.CellParagraph.Element, ElementEdge.BeforeStart));
            }
            PTS.FSPAP fspap = default(PTS.FSPAP);
            this.CellParagraph.GetParaProperties(ref fspap);
            IntPtr value;

            PTS.FSBBOX fsbbox;
            IntPtr     zero;

            PTS.FSKCLEAR fskclear;
            int          num;
            int          num2;

            this.CellParagraph.FormatParaBottomless(this, PTS.FromBoolean(false), fswdir, 0, TextDpi.ToTextDpi(width), 0, null, PTS.FSKCLEAR.fskclearNone, PTS.FromBoolean(true), out fmtrbl, out value, out dvrUsed, out fsbbox, out zero, out fskclear, out num, out num2);
            if (zero != IntPtr.Zero)
            {
                MarginCollapsingState marginCollapsingState = base.PtsContext.HandleToObject(zero) as MarginCollapsingState;
                PTS.ValidateHandle(marginCollapsingState);
                dvrUsed += marginCollapsingState.Margin;
                marginCollapsingState.Dispose();
                zero = IntPtr.Zero;
            }
            this._paraHandle.Value = value;
        }
예제 #3
0
        internal void FormatCellFinite(Size subpageSize, IntPtr breakRecordIn, bool isEmptyOk, uint fswdir, PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn, out PTS.FSFMTR fsfmtr, out int dvrUsed, out IntPtr breakRecordOut)
        {
            if (this.CellParagraph.StructuralCache.DtrList != null)
            {
                this.CellParagraph.InvalidateStructure(TextContainerHelper.GetCPFromElement(this.CellParagraph.StructuralCache.TextContainer, this.CellParagraph.Element, ElementEdge.BeforeStart));
            }
            PTS.FSPAP fspap = default(PTS.FSPAP);
            this.CellParagraph.GetParaProperties(ref fspap);
            PTS.FSRECT fsrect = default(PTS.FSRECT);
            fsrect.u  = (fsrect.v = 0);
            fsrect.du = TextDpi.ToTextDpi(subpageSize.Width);
            fsrect.dv = TextDpi.ToTextDpi(subpageSize.Height);
            bool   condition = breakRecordIn != IntPtr.Zero;
            IntPtr value;

            PTS.FSBBOX fsbbox;
            IntPtr     zero;

            PTS.FSKCLEAR fskclear;
            int          num;

            this.CellParagraph.FormatParaFinite(this, breakRecordIn, PTS.FromBoolean(true), IntPtr.Zero, PTS.FromBoolean(isEmptyOk), PTS.FromBoolean(condition), fswdir, ref fsrect, null, PTS.FSKCLEAR.fskclearNone, fsksuppresshardbreakbeforefirstparaIn, out fsfmtr, out value, out breakRecordOut, out dvrUsed, out fsbbox, out zero, out fskclear, out num);
            if (zero != IntPtr.Zero)
            {
                MarginCollapsingState marginCollapsingState = base.PtsContext.HandleToObject(zero) as MarginCollapsingState;
                PTS.ValidateHandle(marginCollapsingState);
                dvrUsed += marginCollapsingState.Margin;
                marginCollapsingState.Dispose();
                zero = IntPtr.Zero;
            }
            this._paraHandle.Value = value;
        }
예제 #4
0
        // ------------------------------------------------------------------
        // Create new margin collapsing state and collapse margins if necessary.
        // If no collapsing happens, retrieve margin from old collapsing state.
        // This margin value should be used to advance pen.
        // ------------------------------------------------------------------
        internal static void CollapseTopMargin(
            PtsContext ptsContext,              // Current PTS Context.
            MbpInfo mbp,                        // MBP information for element entering the scope
            MarginCollapsingState mcsCurrent,   // current margin collapsing state (adjacent to the new one).
            out MarginCollapsingState mcsNew,   // margin collapsing state for element entering the scope
            out int margin)                     // collapsed margin value
        {
            margin = 0;
            mcsNew = null;

            // Create new margin collapsing info
            mcsNew = new MarginCollapsingState(ptsContext, mbp.MarginTop);
            // collapse margins, if current margin collapsing exists
            if (mcsCurrent != null)
            {
                mcsNew.Collapse(mcsCurrent);
            }

            // If border or paddind is specified:
            // (1) get collapsed margin value
            // (2) set new mcs to null, because we don't have one anymore
            if (mbp.BPTop != 0)
            {
                margin = mcsNew.Margin;
                mcsNew.Dispose();
                mcsNew = null;
            }
            else if (mcsCurrent == null && DoubleUtil.IsZero(mbp.Margin.Top))
            {
                // No need to create new margin collapsing info
                mcsNew.Dispose();
                mcsNew = null;
            }
        }
        // ------------------------------------------------------------------
        // Create new margin collapsing state and collapse margins if necessary.
        // If no collapsing happens, retrieve margin from old collapsing state.
        // This margin value should be used to advance pen.
        // ------------------------------------------------------------------
        internal static void CollapseTopMargin(
            PtsContext ptsContext,              // Current PTS Context.
            MbpInfo mbp,                        // MBP information for element entering the scope
            MarginCollapsingState mcsCurrent,   // current margin collapsing state (adjacent to the new one).
            out MarginCollapsingState mcsNew,   // margin collapsing state for element entering the scope
            out int margin)                     // collapsed margin value
        {
            margin = 0;
            mcsNew = null;

            // Create new margin collapsing info
            mcsNew = new MarginCollapsingState(ptsContext, mbp.MarginTop);
            // collapse margins, if current margin collapsing exists
            if (mcsCurrent != null)
            {
                mcsNew.Collapse(mcsCurrent);
            }

            // If border or paddind is specified:
            // (1) get collapsed margin value
            // (2) set new mcs to null, because we don't have one anymore
            if (mbp.BPTop != 0)
            {
                margin = mcsNew.Margin;
                mcsNew.Dispose();
                mcsNew = null;
            }
            else if (mcsCurrent == null && DoubleUtil.IsZero(mbp.Margin.Top))
            {
                // No need to create new margin collapsing info
                mcsNew.Dispose();
                mcsNew = null;
            }
        }
예제 #6
0
        //------------------------------------------------------
        //
        //  Protected Methods
        //
        //------------------------------------------------------

        #region Protected Methods
        #endregion Protected Methods

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

        #region Internal Methods

        /// <summary>
        /// Collapse Margins
        /// </summary>
        /// <param name="paraClient">Para client</param>
        /// <param name="mcs">input margin collapsing state</param>
        /// <param name="fswdir">current direction (of the track, in which margin collapsing is happening)</param>
        /// <param name="suppressTopSpace">suppress empty space at the top of page</param>
        /// <param name="dvr">dvr, calculated based on margin collapsing state</param>
        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
        {
            if (suppressTopSpace && (StructuralCache.CurrentFormatContext.FinitePage || mcs == null))
            {
                dvr = 0;
            }
            else
            {
                MbpInfo mbp = MbpInfo.FromElement(Table, StructuralCache.TextFormatterHost.PixelsPerDip);
                MarginCollapsingState mcsOut = null;
                MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsOut, out dvr);

                if (mcsOut != null)
                {
                    dvr = mcsOut.Margin;
                    mcsOut.Dispose();
                    mcsOut = null;
                }
            }
        }
예제 #7
0
 // Token: 0x06006823 RID: 26659 RVA: 0x001D54A2 File Offset: 0x001D36A2
 internal override void GetMCSClientAfterFloater(uint fswdirTrack, MarginCollapsingState mcs, out IntPtr pmcsclientOut)
 {
     if (mcs != null)
     {
         pmcsclientOut = mcs.Handle;
         return;
     }
     pmcsclientOut = IntPtr.Zero;
 }
예제 #8
0
 /// <summary>
 /// Collapse margins
 /// </summary>
 /// <param name="paraClient">
 /// IN: Paragraph's para client
 /// </param>
 /// <param name="mcs">
 /// IN: input margin collapsing state
 /// </param>
 /// <param name="fswdir">
 /// IN: current direction (of the track, in which margin collapsing is happening)
 /// </param>
 /// <param name="suppressTopSpace">
 /// IN: suppress empty space at the top of page
 /// </param>
 /// <param name="dvr">
 /// OUT: dvr, calculated based on margin collapsing state
 /// </param>
 internal virtual void CollapseMargin(
     BaseParaClient paraClient,
     MarginCollapsingState mcs,
     uint fswdir,
     bool suppressTopSpace,
     out int dvr)
 {
     // Suppress top space only in paginated scenarios.
     dvr = (mcs == null || (suppressTopSpace)) ? 0 : mcs.Margin;
 }
예제 #9
0
 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;
 }
예제 #10
0
            out IntPtr pmcsclientOut);         // OUT: MCSCLIENT that floater will return to track

        //-------------------------------------------------------------------
        // GetDvrUsedForFloater
        //-------------------------------------------------------------------
        internal virtual void GetDvrUsedForFloater(
            uint fswdirTrack,                   // IN:  direction of Track
            MarginCollapsingState mcs,          // IN:  input margin collapsing state
            int dvrDisplaced,                   // IN:
            out int dvrUsed)                    // OUT:
        {
            // When floater is pushed down due to collision, text may need to be
            // pushed down together with the floater. In such case dvrUsed needs to be
            // set to height of the floater.
            // But for now there is no case, where we need this feature, hence dvrUsed is
            // always 0.
            dvrUsed = 0;
        }
        // Token: 0x06006B63 RID: 27491 RVA: 0x001F0474 File Offset: 0x001EE674
        internal override void GetMCSClientAfterFloater(uint fswdirTrack, MarginCollapsingState mcs, out IntPtr pmcsclientOut)
        {
            MbpInfo mbp = MbpInfo.FromElement(base.Element, base.StructuralCache.TextFormatterHost.PixelsPerDip);
            MarginCollapsingState marginCollapsingState;
            int num;

            MarginCollapsingState.CollapseBottomMargin(base.PtsContext, mbp, null, out marginCollapsingState, out num);
            if (marginCollapsingState != null)
            {
                pmcsclientOut = marginCollapsingState.Handle;
                return;
            }
            pmcsclientOut = IntPtr.Zero;
        }
예제 #12
0
 //-------------------------------------------------------------------
 // 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;
     }
 }
        /// <summary>
        /// FormatCellBottomless
        /// </summary>
        /// <param name="fswdir">Text Direction</param>
        /// <param name="width">Width of cell (height is specified by row props)</param>
        /// <param name="fmtrbl">bottomless format result</param>
        /// <param name="dvrUsed">dvr Used</param>
        internal void FormatCellBottomless(uint fswdir, double width, out PTS.FSFMTRBL fmtrbl, out int dvrUsed)
        {
            IntPtr pfspara;

            PTS.FSBBOX fsbbox;
            IntPtr     pmcsclientOut;

            PTS.FSKCLEAR fskclearOut;
            int          dvrTopSpace;
            int          fPageBecomesUninterruptable;

            PTS.FSPAP fspap;


            if (CellParagraph.StructuralCache.DtrList != null)
            {
                CellParagraph.InvalidateStructure(TextContainerHelper.GetCPFromElement(CellParagraph.StructuralCache.TextContainer, CellParagraph.Element, ElementEdge.BeforeStart));
            }

            fspap = new PTS.FSPAP();
            CellParagraph.GetParaProperties(ref fspap);

            CellParagraph.FormatParaBottomless(this, PTS.FromBoolean(false),
                                               fswdir, 0, TextDpi.ToTextDpi(width),
                                               0, null, PTS.FSKCLEAR.fskclearNone,
                                               PTS.FromBoolean(true),
                                               out fmtrbl,
                                               out pfspara,
                                               out dvrUsed,
                                               out fsbbox,
                                               out pmcsclientOut,
                                               out fskclearOut,
                                               out dvrTopSpace,
                                               out fPageBecomesUninterruptable);

            if (pmcsclientOut != IntPtr.Zero)
            {
                MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                PTS.ValidateHandle(mcs);
                dvrUsed += mcs.Margin;
                mcs.Dispose();
                pmcsclientOut = IntPtr.Zero;
            }

            _paraHandle.Value = pfspara;
        }
        // Token: 0x06006AC8 RID: 27336 RVA: 0x001E9078 File Offset: 0x001E7278
        internal override void CollapseMargin(BaseParaClient paraClient, MarginCollapsingState mcs, uint fswdir, bool suppressTopSpace, out int dvr)
        {
            if (suppressTopSpace && (base.StructuralCache.CurrentFormatContext.FinitePage || mcs == null))
            {
                dvr = 0;
                return;
            }
            MbpInfo mbp = MbpInfo.FromElement(this.Table, base.StructuralCache.TextFormatterHost.PixelsPerDip);
            MarginCollapsingState marginCollapsingState = null;

            MarginCollapsingState.CollapseTopMargin(base.PtsContext, mbp, mcs, out marginCollapsingState, out dvr);
            if (marginCollapsingState != null)
            {
                dvr = marginCollapsingState.Margin;
                marginCollapsingState.Dispose();
                marginCollapsingState = null;
            }
        }
        // Token: 0x06006ACC RID: 27340 RVA: 0x001E9198 File Offset: 0x001E7398
        internal void GetMCSClientAfterTable(uint fswdirTrack, IntPtr pmcsclientIn, out IntPtr ppmcsclientOut)
        {
            ppmcsclientOut = IntPtr.Zero;
            MbpInfo mbp = MbpInfo.FromElement(this.Table, base.StructuralCache.TextFormatterHost.PixelsPerDip);
            MarginCollapsingState mcsCurrent = null;

            if (pmcsclientIn != IntPtr.Zero)
            {
                mcsCurrent = (base.PtsContext.HandleToObject(pmcsclientIn) as MarginCollapsingState);
            }
            MarginCollapsingState marginCollapsingState = null;
            int num;

            MarginCollapsingState.CollapseBottomMargin(base.PtsContext, mbp, mcsCurrent, out marginCollapsingState, out num);
            if (marginCollapsingState != null)
            {
                ppmcsclientOut = marginCollapsingState.Handle;
            }
        }
예제 #16
0
        //-------------------------------------------------------------------
        // 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
        {
            MarginCollapsingState mcsNew;
            int     margin;
            MbpInfo mbp = MbpInfo.FromElement(Element, StructuralCache.TextFormatterHost.PixelsPerDip);

            MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, null, out mcsNew, out margin);
            if (mcsNew != null)
            {
                pmcsclientOut = mcsNew.Handle;
            }
            else
            {
                pmcsclientOut = IntPtr.Zero;
            }
        }
예제 #17
0
        internal void UpdateBottomlessCell(uint fswdir, double width, out PTS.FSFMTRBL fmtrbl, out int dvrUsed)
        {
            PTS.FSPAP fspap = default(PTS.FSPAP);
            this.CellParagraph.GetParaProperties(ref fspap);
            PTS.FSBBOX fsbbox;
            IntPtr     zero;

            PTS.FSKCLEAR fskclear;
            int          num;
            int          num2;

            this.CellParagraph.UpdateBottomlessPara(this._paraHandle.Value, this, PTS.FromBoolean(false), fswdir, 0, TextDpi.ToTextDpi(width), 0, null, PTS.FSKCLEAR.fskclearNone, PTS.FromBoolean(true), out fmtrbl, out dvrUsed, out fsbbox, out zero, out fskclear, out num, out num2);
            if (zero != IntPtr.Zero)
            {
                MarginCollapsingState marginCollapsingState = base.PtsContext.HandleToObject(zero) as MarginCollapsingState;
                PTS.ValidateHandle(marginCollapsingState);
                dvrUsed += marginCollapsingState.Margin;
                marginCollapsingState.Dispose();
                zero = IntPtr.Zero;
            }
        }
예제 #18
0
 // Token: 0x060068B2 RID: 26802 RVA: 0x001D8D54 File Offset: 0x001D6F54
 internal static void CollapseBottomMargin(PtsContext ptsContext, MbpInfo mbp, MarginCollapsingState mcsCurrent, out MarginCollapsingState mcsNew, out int margin)
 {
     margin = 0;
     mcsNew = null;
     if (!DoubleUtil.IsZero(mbp.Margin.Bottom))
     {
         mcsNew = new MarginCollapsingState(ptsContext, mbp.MarginBottom);
     }
     if (mcsCurrent != null)
     {
         if (mbp.BPBottom != 0)
         {
             margin = mcsCurrent.Margin;
             return;
         }
         if (mcsNew == null)
         {
             mcsNew = new MarginCollapsingState(ptsContext, 0);
         }
         mcsNew.Collapse(mcsCurrent);
     }
 }
예제 #19
0
 // Token: 0x060068B1 RID: 26801 RVA: 0x001D8CE8 File Offset: 0x001D6EE8
 internal static void CollapseTopMargin(PtsContext ptsContext, MbpInfo mbp, MarginCollapsingState mcsCurrent, out MarginCollapsingState mcsNew, out int margin)
 {
     margin = 0;
     mcsNew = null;
     mcsNew = new MarginCollapsingState(ptsContext, mbp.MarginTop);
     if (mcsCurrent != null)
     {
         mcsNew.Collapse(mcsCurrent);
     }
     if (mbp.BPTop != 0)
     {
         margin = mcsNew.Margin;
         mcsNew.Dispose();
         mcsNew = null;
         return;
     }
     if (mcsCurrent == null && DoubleUtil.IsZero(mbp.Margin.Top))
     {
         mcsNew.Dispose();
         mcsNew = null;
     }
 }
예제 #20
0
        /// <summary>
        /// GetMCSClientAfterTable
        /// </summary>
        /// <param name="fswdirTrack">Direction of Track</param>
        /// <param name="pmcsclientIn">Margin collapsing state</param>
        /// <param name="ppmcsclientOut">Margin collapsing state</param>
        internal void GetMCSClientAfterTable(
            uint fswdirTrack,
            IntPtr pmcsclientIn,
            out IntPtr ppmcsclientOut)
        {
            ppmcsclientOut = IntPtr.Zero;
            MbpInfo mbp = MbpInfo.FromElement(Table, StructuralCache.TextFormatterHost.PixelsPerDip);
            MarginCollapsingState mcs = null;

            if (pmcsclientIn != IntPtr.Zero)
            {
                mcs = PtsContext.HandleToObject(pmcsclientIn) as MarginCollapsingState;
            }

            MarginCollapsingState mcsNew = null;
            int margin;

            MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, mcs, out mcsNew, out margin);
            if (mcsNew != null)
            {
                ppmcsclientOut = mcsNew.Handle;
            }
        }
        /// <summary>
        /// UpdateBottomlessCell
        /// </summary>
        /// <param name="fswdir">Text Direction</param>
        /// <param name="width">Width of cell (height is specified by row props)</param>
        /// <param name="fmtrbl">bottomless format result</param>
        /// <param name="dvrUsed">dvr Used</param>
        internal void UpdateBottomlessCell(uint fswdir, double width, out PTS.FSFMTRBL fmtrbl, out int dvrUsed)
        {
            IntPtr pmcsclientOut;

            PTS.FSKCLEAR fskclearOut;
            PTS.FSBBOX   fsbbox;
            int          dvrTopSpace;
            int          fPageBecomesUninterruptable;

            PTS.FSPAP fspap;

            fspap = new PTS.FSPAP();
            CellParagraph.GetParaProperties(ref fspap);

            CellParagraph.UpdateBottomlessPara(_paraHandle.Value, this,
                                               PTS.FromBoolean(false),
                                               fswdir, 0,
                                               TextDpi.ToTextDpi(width),
                                               0, null,
                                               PTS.FSKCLEAR.fskclearNone,
                                               PTS.FromBoolean(true),
                                               out fmtrbl,
                                               out dvrUsed,
                                               out fsbbox,
                                               out pmcsclientOut,
                                               out fskclearOut,
                                               out dvrTopSpace,
                                               out fPageBecomesUninterruptable);
            if (pmcsclientOut != IntPtr.Zero)
            {
                MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                PTS.ValidateHandle(mcs);
                dvrUsed += mcs.Margin;
                mcs.Dispose();
                pmcsclientOut = IntPtr.Zero;
            }
        }
        // ------------------------------------------------------------------
        // Update current margin collapsing state and collapse margins if
        // necessary. If no collapsing happens, retrieve margin from previous
        // collapsing state. This margin value should be used to advance pen.
        // ------------------------------------------------------------------
        internal static void CollapseBottomMargin(
            PtsContext ptsContext,              // Current PTS Context.
            MbpInfo mbp,                        // MBP information for element leaving the scope
            MarginCollapsingState mcsCurrent,   // current margin collapsing state (adjacent to the new one).
            out MarginCollapsingState mcsNew,   // margin collapsing state for element leaving the scope
            out int margin)                     // collapsed margin value
        {
            margin = 0;
            mcsNew = null;

            // Create new margin collapsing state, if necessary
            if (!DoubleUtil.IsZero(mbp.Margin.Bottom))
            {
                mcsNew = new MarginCollapsingState(ptsContext, mbp.MarginBottom);
            }

            // If the current margin collapsing state does not exist, we are done.
            // Otherwise, get current border and padding and decide if to collapse margin.
            if (mcsCurrent != null)
            {
                if (mbp.BPBottom != 0)
                {
                    // No collapsing happens, get margin value
                    margin = mcsCurrent.Margin;
                }
                else
                {
                    // Collapse margins
                    if (mcsNew == null)
                    {
                        mcsNew = new MarginCollapsingState(ptsContext, 0);
                    }
                    mcsNew.Collapse(mcsCurrent);
                }
            }
        }
예제 #23
0
        // ------------------------------------------------------------------
        // Update current margin collapsing state and collapse margins if 
        // necessary. If no collapsing happens, retrieve margin from previous 
        // collapsing state. This margin value should be used to advance pen.
        // ------------------------------------------------------------------
        internal static void CollapseBottomMargin(
            PtsContext ptsContext,              // Current PTS Context.
            MbpInfo mbp,                        // MBP information for element leaving the scope
            MarginCollapsingState mcsCurrent,   // current margin collapsing state (adjacent to the new one).
            out MarginCollapsingState mcsNew,   // margin collapsing state for element leaving the scope
            out int margin)                     // collapsed margin value
        {
            margin = 0;
            mcsNew = null;

            // Create new margin collapsing state, if necessary
            if (!DoubleUtil.IsZero(mbp.Margin.Bottom))
            {
                mcsNew = new MarginCollapsingState(ptsContext, mbp.MarginBottom);
            }

            // If the current margin collapsing state does not exist, we are done.
            // Otherwise, get current border and padding and decide if to collapse margin.
            if (mcsCurrent != null)
            {
                if (mbp.BPBottom != 0)
                {
                    // No collapsing happens, get margin value
                    margin = mcsCurrent.Margin;
                }
                else
                {
                    // Collapse margins
                    if (mcsNew == null)
                    {
                        mcsNew = new MarginCollapsingState(ptsContext, 0);
                    }
                    mcsNew.Collapse(mcsCurrent);
                }
            }
        }
        // Token: 0x06006B5E RID: 27486 RVA: 0x001F0080 File Offset: 0x001EE280
        internal override void CollapseMargin(BaseParaClient paraClient, MarginCollapsingState mcs, uint fswdir, bool suppressTopSpace, out int dvr)
        {
            MbpInfo mbp = MbpInfo.FromElement(base.Element, base.StructuralCache.TextFormatterHost.PixelsPerDip);
            MarginCollapsingState marginCollapsingState;
            int num;

            MarginCollapsingState.CollapseTopMargin(base.PtsContext, mbp, mcs, out marginCollapsingState, out num);
            if (suppressTopSpace)
            {
                dvr = 0;
            }
            else
            {
                dvr = num;
                if (marginCollapsingState != null)
                {
                    dvr += marginCollapsingState.Margin;
                }
            }
            if (marginCollapsingState != null)
            {
                marginCollapsingState.Dispose();
            }
        }
예제 #25
0
 // ------------------------------------------------------------------
 // Compare margin collapsing state with another one.
 //
 //      mcs - another margin collapsing state
 //
 // Returns: 'true' if both are the same.
 // ------------------------------------------------------------------
 internal bool IsEqual(MarginCollapsingState mcs)
 {
     return (_maxPositive == mcs._maxPositive && _minNegative == mcs._minNegative);
 }
예제 #26
0
 // ------------------------------------------------------------------
 // Constructor. Make identical copy of the margin collapsing state.
 //
 //      mcs - margin collapsing state to copy
 // ------------------------------------------------------------------
 private MarginCollapsingState(MarginCollapsingState mcs) : base(mcs.PtsContext)
 {
     _maxPositive = mcs._maxPositive;
     _minNegative = mcs._minNegative;
 }
 // Token: 0x06006744 RID: 26436 RVA: 0x001CDDAD File Offset: 0x001CBFAD
 internal virtual void CollapseMargin(BaseParaClient paraClient, MarginCollapsingState mcs, uint fswdir, bool suppressTopSpace, out int dvr)
 {
     dvr = ((mcs == null || suppressTopSpace) ? 0 : mcs.Margin);
 }
예제 #28
0
        internal unsafe void UpdateBottomlessPara(
            IntPtr pfspara,                      // IN:  pointer to the para data
            SubpageParaClient paraClient,        // IN:
            int fSuppressTopSpace,               // IN:  suppress empty space at the top of the page
            uint fswdir,                         // IN:  current direction
            int urTrack,                         // IN:  u of bootomless rectangle to fill
            int durTrack,                        // IN:  du of bootomless rectangle to fill
            int vrTrack,                         // IN:  v of bootomless rectangle to fill
            MarginCollapsingState mcs,           // IN:  input margin collapsing state
            PTS.FSKCLEAR fskclearIn,             // IN:  clear property that must be satisfied
            int fInterruptable,                  // IN:  formatting can be interrupted
            out PTS.FSFMTRBL fsfmtrbl,           // OUT: result of formatting the paragraph
            out int dvrUsed,                     // OUT: vertical space used by the para
            out PTS.FSBBOX fsbbox,               // OUT: para BBox
            out IntPtr pmcsclientOut,            // OUT: margin collapsing state at the bottom
            out PTS.FSKCLEAR fskclearOut,        // OUT: ClearIn for the next paragraph
            out int dvrTopSpace,                 // OUT: top space due to collapsed margin
            out int fPageBecomesUninterruptable) // OUT: interruption is prohibited from now on
        {
            int     subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin;
            int     cColumns;
            int     marginTop, marginBottom;
            MbpInfo mbp;
            MarginCollapsingState mcsSubpage, mcsBottom;

            PTS.FSCOLUMNINFO[] columnInfoCollection;
            uint fswdirSubpage = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty)));

            // Initialize the subpage size and its margin.
            subpageWidth    = durTrack;
            urSubpageMargin = vrSubpageMargin = 0;

            // Set clear property
            Invariant.Assert(Element is TableCell || Element is AnchoredBlock);
            fskclearIn = PTS.WrapDirectionToFskclear((WrapDirection)Element.GetValue(Block.ClearFloatersProperty));

            // Take into account MBPs and modify subpage metrics,
            // and make sure that subpage is at least 1 unit wide (cannot measure at width <= 0)
            // NOTE: Do not suppress top space for bottomles pages.
            mbp = MbpInfo.FromElement(Element, StructuralCache.TextFormatterHost.PixelsPerDip);

            if (fswdirSubpage != fswdir)
            {
                PTS.FSRECT fsrcToFillSubpage = new PTS.FSRECT(urTrack, 0, durTrack, 0);
                PTS.FSRECT pageRect          = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrcToFillSubpage, fswdirSubpage, out fsrcToFillSubpage));

                urTrack  = fsrcToFillSubpage.u;
                durTrack = fsrcToFillSubpage.du;

                mbp.MirrorMargin();
            }

            subpageWidth = Math.Max(1, subpageWidth - (mbp.MBPLeft + mbp.MBPRight));
            MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsSubpage, out marginTop);
            // Destroy top margin collapsing state (not needed anymore).
            if (mcsSubpage != null)
            {
                mcsSubpage.Dispose();
                mcsSubpage = null;
            }
            durSubpageMargin = subpageWidth;

            // Initialize column info
            // For bottomles spara, limit line height to the height of the current format context in structural cache.
            ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(_element);
            double     lineHeight     = DynamicPropertyReader.GetLineHeightValue(_element);
            double     pageFontSize   = (double)_structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty);
            FontFamily pageFontFamily = (FontFamily)_structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty);

            // Get columns info, setting ownerIsFlowDocument flag to false. A flow document should not be formatted as a subpage and we
            // do not want default column widths to be set on TableCells and floaters
            cColumns             = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, TextDpi.FromTextDpi(subpageWidth), pageFontSize, pageFontFamily, false);
            columnInfoCollection = new PTS.FSCOLUMNINFO[cColumns];
            fixed(PTS.FSCOLUMNINFO *rgColumnInfo = columnInfoCollection)
            {
                PtsHelper.GetColumnsInfo(columnProperties, lineHeight, TextDpi.FromTextDpi(subpageWidth), pageFontSize, pageFontFamily, cColumns, rgColumnInfo, false);
            }

            StructuralCache.CurrentFormatContext.PushNewPageData(new Size(TextDpi.FromTextDpi(subpageWidth), TextDpi.MaxWidth),
                                                                 new Thickness(),
                                                                 true,
                                                                 false);

            // Create subpage
            fixed(PTS.FSCOLUMNINFO *rgColumnInfo = columnInfoCollection)
            {
                PTS.Validate(PTS.FsUpdateBottomlessSubpage(PtsContext.Context, pfspara, _mainTextSegment.Handle, fSuppressTopSpace,
                                                           fswdir, subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin,
                                                           cColumns, rgColumnInfo, 0, null, null, 0, null, null, PTS.FromBoolean(true),
                                                           out fsfmtrbl, out dvrUsed, out fsbbox, out pmcsclientOut, out dvrTopSpace,
                                                           out fPageBecomesUninterruptable), PtsContext);
            }

            StructuralCache.CurrentFormatContext.PopPageData();

            fskclearOut = PTS.FSKCLEAR.fskclearNone;

            if (fsfmtrbl != PTS.FSFMTRBL.fmtrblCollision)
            {
                // Bottom margin collapsing:
                // (1) retrieve mcs from the subtrack
                // (2) do margin collapsing; create a new margin collapsing state
                if (pmcsclientOut != IntPtr.Zero)
                {
                    mcsSubpage = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                    PTS.ValidateHandle(mcsSubpage);
                    pmcsclientOut = IntPtr.Zero;
                }
                MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, mcsSubpage, out mcsBottom, out marginBottom);
                pmcsclientOut = (mcsBottom != null) ? mcsBottom.Handle : IntPtr.Zero;

                // Since MCS returned by PTS is never passed back, destroy MCS provided by PTS.
                // If necessary, new MCS is created and passed back to PTS.
                if (mcsSubpage != null)
                {
                    mcsSubpage.Dispose();
                    mcsSubpage = null;
                }

                if (PTS.ToBoolean(fsbbox.fDefined))
                {
                    // Workaround for PTS bug 860: get max of the page rect and
                    // bounding box of the page.
                    dvrUsed  = Math.Max(dvrUsed, fsbbox.fsrc.dv + fsbbox.fsrc.v);
                    durTrack = Math.Max(durTrack, fsbbox.fsrc.du + fsbbox.fsrc.u);
                }

                // Take into account MBPs and modify subtrack metrics
                dvrTopSpace = (mbp.BPTop != 0) ? marginTop : dvrTopSpace;
                dvrUsed    += (marginTop + mbp.BPTop) + (marginBottom + mbp.BPBottom);

                // Update bounding box
                fsbbox.fsrc.u  = urTrack + mbp.MarginLeft;
                fsbbox.fsrc.v  = vrTrack + dvrTopSpace;
                fsbbox.fsrc.du = Math.Max(durTrack - (mbp.MarginLeft + mbp.MarginRight), 0);
                fsbbox.fsrc.dv = Math.Max(dvrUsed - dvrTopSpace, 0);
            }
            else
            {
                Debug.Assert(pmcsclientOut == IntPtr.Zero);
                pfspara = IntPtr.Zero;
                dvrUsed = dvrTopSpace = 0;
            }


            if (fswdirSubpage != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformBbox(fswdirSubpage, ref pageRect, ref fsbbox, fswdir, out fsbbox));
            }

            // Update information about first/last chunk. In bottomless scenario
            // paragraph is not broken, so there is only one chunk.
            paraClient.SetChunkInfo(true, true);
        }
 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;            
 }
예제 #30
0
        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, StructuralCache.TextFormatterHost.PixelsPerDip);

                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;
        }
예제 #31
0
 //-------------------------------------------------------------------
 // CollapseMargin
 //-------------------------------------------------------------------
 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
 {
     MbpInfo mbp = MbpInfo.FromElement(Element);
     MarginCollapsingState mcsNew;
     int margin;
     MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsNew, out margin);
     
     if (suppressTopSpace)
     {
         dvr = 0;
     }
     else
     {
         dvr = margin;
         if (mcsNew != null)
         {
             dvr += mcsNew.Margin;
         }
     }
     if (mcsNew != null)
     {
         mcsNew.Dispose();
     }
 }
예제 #32
0
 //-------------------------------------------------------------------
 // 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
 {
     MarginCollapsingState mcsNew;
     int margin;
     MbpInfo mbp = MbpInfo.FromElement(Element);
     MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, null, out mcsNew, out margin);
     if (mcsNew != null)
     {
         pmcsclientOut = mcsNew.Handle;
     }
     else
     {
         pmcsclientOut = IntPtr.Zero;
     }
 }
 // ------------------------------------------------------------------
 // The resulting margin width is the maximum of the adjoining margin
 // widths. In the case of negative margins, the absolute maximum of
 // the negative adjoining margins is deducted from the maximum of
 // the positive adjoining margins. If there are no positive margins,
 // the absolute maximum of the negative adjoining margins is deducted
 // from zero.
 //
 //      mcs - margin collapsing state to collapse with
 // ------------------------------------------------------------------
 internal void Collapse(MarginCollapsingState mcs)
 {
     _maxPositive = Math.Max(_maxPositive, mcs._maxPositive);
     _minNegative = Math.Min(_minNegative, mcs._minNegative);
 }
 // ------------------------------------------------------------------
 // Compare margin collapsing state with another one.
 //
 //      mcs - another margin collapsing state
 //
 // Returns: 'true' if both are the same.
 // ------------------------------------------------------------------
 internal bool IsEqual(MarginCollapsingState mcs)
 {
     return(_maxPositive == mcs._maxPositive && _minNegative == mcs._minNegative);
 }
 // ------------------------------------------------------------------
 // Constructor. Make identical copy of the margin collapsing state.
 //
 //      mcs - margin collapsing state to copy
 // ------------------------------------------------------------------
 private MarginCollapsingState(MarginCollapsingState mcs) : base(mcs.PtsContext)
 {
     _maxPositive = mcs._maxPositive;
     _minNegative = mcs._minNegative;
 }
        internal unsafe void FormatParaFinite(
            SubpageParaClient paraClient,       // IN:
            IntPtr pbrkrecIn,                   // IN:  break record---use if !NULL
            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:  current direction
            ref PTS.FSRECT fsrcToFill,          // IN:  rectangle to fill
            MarginCollapsingState mcs,          // IN:  input margin collapsing state
            PTS.FSKCLEAR fskclearIn,            // IN:  clear property that must be satisfied
            PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn,
                                                // IN: suppress breaks at track start?
            out PTS.FSFMTR fsfmtr,              // OUT: result of formatting the paragraph
            out IntPtr pfspara,                 // OUT: pointer to the para data
            out IntPtr pbrkrecOut,              // OUT: pointer to the para break record
            out int dvrUsed,                    // OUT: vertical space used by the para
            out PTS.FSBBOX fsbbox,              // OUT: para BBox
            out IntPtr pmcsclientOut,           // OUT: margin collapsing state at the bottom
            out PTS.FSKCLEAR fskclearOut,       // OUT: ClearIn for the next paragraph
            out int dvrTopSpace)                // OUT: top space due to collapsed margin
        {
            uint fswdirSubpage = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty)));

            int subpageWidth, subpageHeight;
            int cColumns;
            int marginTop, marginBottom;
            MbpInfo mbp;
            MarginCollapsingState mcsSubpage, mcsBottom;
            PTS.FSRECT fsrcSubpageMargin;
            PTS.FSCOLUMNINFO [] columnInfoCollection;

            // Currently it is possible to get MCS and BR in following situation:
            // At the end of the page there is a paragraph with delayed figure, so the figure
            // gets delayed to the next page. But part of the next paragraph fits in the page,
            // so it gets broken. PTS creates BR with delayed figure and broken para.
            // PTS will format the next page starting from delayed figure, which can produce MCS.
            // So when the next paragraph is continued from BR, it has MCS.
            // This problem is currently investigated by PTS team: PTSLS bug 915.
            // For now, MCS gets ignored here.
            //Debug.Assert(pbrkrecIn == IntPtr.Zero || mcs == null, "Broken paragraph cannot have margin collapsing state.");
            if (mcs != null && pbrkrecIn != IntPtr.Zero)
            {
                mcs = null;
            }

            // Initialize the subpage size and its margin.
            fsrcSubpageMargin = new PTS.FSRECT();
            subpageWidth = fsrcToFill.du;
            subpageHeight = fsrcToFill.dv;

            // Set clear property
            Invariant.Assert(Element is TableCell || Element is AnchoredBlock);
            fskclearIn = PTS.WrapDirectionToFskclear((WrapDirection)Element.GetValue(Block.ClearFloatersProperty));

            // Take into account MBPs and modify subpage metrics,
            // and make sure that subpage is at least 1 unit wide (cannot measure at width <= 0)
            marginTop = 0;
            mcsSubpage = null;
            
            // Get MBP info. Since subpage height and width must be at least 1, the max size for MBP is subpage dimensions less 1
            mbp = MbpInfo.FromElement(Element); 

            if(fswdirSubpage != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrcToFill, fswdirSubpage, out fsrcToFill));
                mbp.MirrorMargin();
            }

            subpageWidth = Math.Max(1, subpageWidth - (mbp.MBPLeft + mbp.MBPRight));
            if (pbrkrecIn == IntPtr.Zero)
            {
                // Top margin collapsing. If suppresing top space, top margin is always 0.
                MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsSubpage, out marginTop);
                if (PTS.ToBoolean(fSuppressTopSpace))
                {
                    marginTop = 0;
                }
                subpageHeight = Math.Max(1, subpageHeight - (marginTop + mbp.BPTop));
                // Destroy top margin collapsing state (not needed anymore).
                if (mcsSubpage != null)
                {
                    mcsSubpage.Dispose();
                    mcsSubpage = null;
                }
            }
            else
            {
                Debug.Assert(fSuppressTopSpace == 1, "Top space should be always suppressed at the top of broken paragraph.");
            }
            fsrcSubpageMargin.du = subpageWidth;
            fsrcSubpageMargin.dv = subpageHeight;

            // Initialize column info
            ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(_element);
            double lineHeight = DynamicPropertyReader.GetLineHeightValue(_element);
            double pageFontSize = (double)_structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty);
            FontFamily pageFontFamily = (FontFamily)_structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty);

            // Get columns info, setting ownerIsFlowDocument flag to false. A flow document should not be formatted as a subpage and we
            // do not want default column widths to be set on TableCells and floaters
            cColumns = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, TextDpi.FromTextDpi(subpageWidth), pageFontSize, pageFontFamily, false);
            columnInfoCollection = new PTS.FSCOLUMNINFO[cColumns];
            fixed (PTS.FSCOLUMNINFO* rgColumnInfo = columnInfoCollection)
            {
                PtsHelper.GetColumnsInfo(columnProperties, lineHeight, TextDpi.FromTextDpi(subpageWidth), pageFontSize, pageFontFamily, cColumns, rgColumnInfo, false);
            }

            // Format subpage
            StructuralCache.CurrentFormatContext.PushNewPageData(new Size(TextDpi.FromTextDpi(subpageWidth), TextDpi.FromTextDpi(subpageHeight)),
                                                                 new Thickness(), 
                                                                 false, 
                                                                 true);

            fixed (PTS.FSCOLUMNINFO* rgColumnInfo = columnInfoCollection)
            {
                PTS.Validate(PTS.FsCreateSubpageFinite(PtsContext.Context, pbrkrecIn, fBRFromPreviousPage, _mainTextSegment.Handle,
                    footnoteRejector, fEmptyOk, fSuppressTopSpace, fswdir, subpageWidth, subpageHeight,
                    ref fsrcSubpageMargin, cColumns, rgColumnInfo, PTS.False,
                    0, null, null, 0, null, null, PTS.FromBoolean(false), 
                    fsksuppresshardbreakbeforefirstparaIn, 
                    out fsfmtr, out pfspara, out pbrkrecOut, out dvrUsed, out fsbbox, out pmcsclientOut, out dvrTopSpace), PtsContext);
            }

            StructuralCache.CurrentFormatContext.PopPageData();

            fskclearOut = PTS.FSKCLEAR.fskclearNone;

            if (PTS.ToBoolean(fsbbox.fDefined))
            {
                // Workaround for PTS bug 860: get max of the page rect and 
                // bounding box of the page.
                dvrUsed = Math.Max(dvrUsed, fsbbox.fsrc.dv + fsbbox.fsrc.v);
                fsrcToFill.du = Math.Max(fsrcToFill.du, fsbbox.fsrc.du + fsbbox.fsrc.u);
            }

            if (pbrkrecIn == IntPtr.Zero) // if first chunk
            {
                // Take into account MBPs and modify subpage metrics
                dvrTopSpace = (mbp.BPTop != 0) ? marginTop : dvrTopSpace;
                dvrUsed += (marginTop + mbp.BPTop);
            }

            if (pmcsclientOut != IntPtr.Zero)
            {
                mcsSubpage = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                PTS.ValidateHandle(mcsSubpage);
                pmcsclientOut = IntPtr.Zero;
            }

            // Initialize subpage metrics
            if (fsfmtr.kstop >= PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace)   // No progress or collision
            {
                dvrUsed = dvrTopSpace = 0;
                //pbrkrecOut = IntPtr.Zero;
                //pfspara = IntPtr.Zero;
                //pmcsclientOut = IntPtr.Zero;
            }
            else
            {
                if (fsfmtr.kstop == PTS.FSFMTRKSTOP.fmtrGoalReached)
                {
                    // Bottom margin collapsing:
                    // (a) retrieve mcs from the subpage
                    // (b) do margin collapsing; create a new margin collapsing state
                    // There is no bottom margin collapsing if paragraph will be continued (output break record is not null).
                    MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, mcsSubpage, out mcsBottom, out marginBottom);
                    pmcsclientOut = (mcsBottom != null) ? mcsBottom.Handle : IntPtr.Zero;

                    if (pmcsclientOut == IntPtr.Zero) // if last chunk
                        dvrUsed += marginBottom + mbp.BPBottom;
                }

                // Update bounding box
                fsbbox.fsrc.u = fsrcToFill.u + mbp.MarginLeft;
                fsbbox.fsrc.v = fsrcToFill.v + dvrTopSpace;
                fsbbox.fsrc.du = Math.Max(fsrcToFill.du - (mbp.MarginLeft + mbp.MarginRight), 0);
                fsbbox.fsrc.dv = Math.Max(dvrUsed - dvrTopSpace, 0);
            }

            if(fswdirSubpage != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformBbox(fswdirSubpage, ref pageRect, ref fsbbox, fswdir, out fsbbox));
            }


            // Since MCS returned by PTS is never passed back, destroy MCS provided by PTS.
            // If necessary, new MCS is created and passed back to PTS (see above).
            if (mcsSubpage != null)
            {
                mcsSubpage.Dispose();
                mcsSubpage = null;
            }


            // Update information about first/last chunk
            paraClient.SetChunkInfo(pbrkrecIn == IntPtr.Zero, pbrkrecOut == IntPtr.Zero);
        }
예제 #37
0
 // ------------------------------------------------------------------
 // The resulting margin width is the maximum of the adjoining margin 
 // widths. In the case of negative margins, the absolute maximum of 
 // the negative adjoining margins is deducted from the maximum of 
 // the positive adjoining margins. If there are no positive margins, 
 // the absolute maximum of the negative adjoining margins is deducted 
 // from zero.
 //
 //      mcs - margin collapsing state to collapse with
 // ------------------------------------------------------------------
 internal void Collapse(MarginCollapsingState mcs)
 {
     _maxPositive = Math.Max(_maxPositive, mcs._maxPositive);
     _minNegative = Math.Min(_minNegative, mcs._minNegative);
 }
예제 #38
0
            out int cVertices);                 // OUT: total number of vertices in all polygons
 
        //-------------------------------------------------------------------
        // GetMCSClientAfterFloater 
        //-------------------------------------------------------------------- 
        internal abstract 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
예제 #39
0
            out IntPtr paraClientHandle);       // OUT: opaque to PTS paragraph client

        //--------------------------------------------------------------------
        // CollapseMargin 
        //-------------------------------------------------------------------
        internal override abstract 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
        internal unsafe void UpdateBottomlessPara(
            IntPtr pfspara,                     // IN:  pointer to the para data
            SubpageParaClient paraClient,       // IN:
            int fSuppressTopSpace,              // IN:  suppress empty space at the top of the page
            uint fswdir,                        // IN:  current direction
            int urTrack,                        // IN:  u of bootomless rectangle to fill
            int durTrack,                       // IN:  du of bootomless rectangle to fill
            int vrTrack,                        // IN:  v of bootomless rectangle to fill
            MarginCollapsingState mcs,          // IN:  input margin collapsing state
            PTS.FSKCLEAR fskclearIn,            // IN:  clear property that must be satisfied
            int fInterruptable,                 // IN:  formatting can be interrupted
            out PTS.FSFMTRBL fsfmtrbl,          // OUT: result of formatting the paragraph
            out int dvrUsed,                    // OUT: vertical space used by the para
            out PTS.FSBBOX fsbbox,              // OUT: para BBox
            out IntPtr pmcsclientOut,           // OUT: margin collapsing state at the bottom
            out PTS.FSKCLEAR fskclearOut,       // OUT: ClearIn for the next paragraph
            out int dvrTopSpace,                // OUT: top space due to collapsed margin
            out int fPageBecomesUninterruptable)// OUT: interruption is prohibited from now on
        {
            int subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin;
            int cColumns;
            int marginTop, marginBottom;
            MbpInfo mbp;
            MarginCollapsingState mcsSubpage, mcsBottom;
            PTS.FSCOLUMNINFO[] columnInfoCollection;
            uint fswdirSubpage = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty)));

            // Initialize the subpage size and its margin.
            subpageWidth = durTrack;
            urSubpageMargin = vrSubpageMargin = 0;

            // Set clear property
            Invariant.Assert(Element is TableCell || Element is AnchoredBlock);
            fskclearIn = PTS.WrapDirectionToFskclear((WrapDirection)Element.GetValue(Block.ClearFloatersProperty));

            // Take into account MBPs and modify subpage metrics,
            // and make sure that subpage is at least 1 unit wide (cannot measure at width <= 0)
            // NOTE: Do not suppress top space for bottomles pages.
            mbp = MbpInfo.FromElement(Element);

            if(fswdirSubpage != fswdir)
            {
                PTS.FSRECT fsrcToFillSubpage = new PTS.FSRECT(urTrack, 0, durTrack, 0);
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrcToFillSubpage, fswdirSubpage, out fsrcToFillSubpage));

                urTrack = fsrcToFillSubpage.u;
                durTrack = fsrcToFillSubpage.du;

                mbp.MirrorMargin();
            }

            subpageWidth = Math.Max(1, subpageWidth - (mbp.MBPLeft + mbp.MBPRight));
            MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsSubpage, out marginTop);
            // Destroy top margin collapsing state (not needed anymore).
            if (mcsSubpage != null)
            {
                mcsSubpage.Dispose();
                mcsSubpage = null;
            }
            durSubpageMargin = subpageWidth;

            // Initialize column info
            // For bottomles spara, limit line height to the height of the current format context in structural cache.
            ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(_element);
            double lineHeight = DynamicPropertyReader.GetLineHeightValue(_element);
            double pageFontSize = (double)_structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty);
            FontFamily pageFontFamily = (FontFamily)_structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty);

            // Get columns info, setting ownerIsFlowDocument flag to false. A flow document should not be formatted as a subpage and we
            // do not want default column widths to be set on TableCells and floaters
            cColumns = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, TextDpi.FromTextDpi(subpageWidth), pageFontSize, pageFontFamily, false);
            columnInfoCollection = new PTS.FSCOLUMNINFO[cColumns];
            fixed (PTS.FSCOLUMNINFO* rgColumnInfo = columnInfoCollection)
            {
                PtsHelper.GetColumnsInfo(columnProperties, lineHeight, TextDpi.FromTextDpi(subpageWidth), pageFontSize, pageFontFamily, cColumns, rgColumnInfo, false);
            }

            StructuralCache.CurrentFormatContext.PushNewPageData(new Size(TextDpi.FromTextDpi(subpageWidth), TextDpi.MaxWidth),
                                                                 new Thickness(), 
                                                                 true, 
                                                                 false);

            // Create subpage
            fixed (PTS.FSCOLUMNINFO* rgColumnInfo = columnInfoCollection)
            {
                PTS.Validate(PTS.FsUpdateBottomlessSubpage(PtsContext.Context, pfspara, _mainTextSegment.Handle, fSuppressTopSpace,
                    fswdir, subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin,
                    cColumns, rgColumnInfo, 0, null, null, 0, null, null, PTS.FromBoolean(true),
                    out fsfmtrbl, out dvrUsed, out fsbbox, out pmcsclientOut, out dvrTopSpace,
                    out fPageBecomesUninterruptable), PtsContext);
            }

            StructuralCache.CurrentFormatContext.PopPageData();

            fskclearOut = PTS.FSKCLEAR.fskclearNone;

            if (fsfmtrbl != PTS.FSFMTRBL.fmtrblCollision)
            {
                // Bottom margin collapsing:
                // (1) retrieve mcs from the subtrack
                // (2) do margin collapsing; create a new margin collapsing state
                if (pmcsclientOut != IntPtr.Zero)
                {
                    mcsSubpage = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                    PTS.ValidateHandle(mcsSubpage);
                    pmcsclientOut = IntPtr.Zero;
                }
                MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, mcsSubpage, out mcsBottom, out marginBottom);
                pmcsclientOut = (mcsBottom != null) ? mcsBottom.Handle : IntPtr.Zero;

                // Since MCS returned by PTS is never passed back, destroy MCS provided by PTS.
                // If necessary, new MCS is created and passed back to PTS.
                if (mcsSubpage != null)
                {
                    mcsSubpage.Dispose();
                    mcsSubpage = null;
                }

                if (PTS.ToBoolean(fsbbox.fDefined))
                {
                    // Workaround for PTS bug 860: get max of the page rect and 
                    // bounding box of the page.
                    dvrUsed = Math.Max(dvrUsed, fsbbox.fsrc.dv + fsbbox.fsrc.v);
                    durTrack = Math.Max(durTrack, fsbbox.fsrc.du + fsbbox.fsrc.u);
                }

                // Take into account MBPs and modify subtrack metrics
                dvrTopSpace = (mbp.BPTop != 0) ? marginTop : dvrTopSpace;
                dvrUsed += (marginTop + mbp.BPTop) + (marginBottom + mbp.BPBottom);

                // Update bounding box
                fsbbox.fsrc.u = urTrack + mbp.MarginLeft;
                fsbbox.fsrc.v = vrTrack + dvrTopSpace;
                fsbbox.fsrc.du = Math.Max(durTrack - (mbp.MarginLeft + mbp.MarginRight), 0);
                fsbbox.fsrc.dv = Math.Max(dvrUsed - dvrTopSpace, 0);
            }
            else
            {
                Debug.Assert(pmcsclientOut == IntPtr.Zero);
                pfspara = IntPtr.Zero;
                dvrUsed = dvrTopSpace = 0;
            }


            if(fswdirSubpage != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformBbox(fswdirSubpage, ref pageRect, ref fsbbox, fswdir, out fsbbox));
            }

            // Update information about first/last chunk. In bottomless scenario
            // paragraph is not broken, so there is only one chunk.
            paraClient.SetChunkInfo(true, true);
        }
예제 #41
0
        //------------------------------------------------------
        //
        //  Protected Methods
        //
        //------------------------------------------------------

        #region Protected Methods 
        #endregion Protected Methods 

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

        #region Internal Methods 

        /// <summary>
        /// Collapse Margins
        /// </summary>
        /// <param name="paraClient">Para client</param>
        /// <param name="mcs">input margin collapsing state</param>
        /// <param name="fswdir">current direction (of the track, in which margin collapsing is happening)</param>
        /// <param name="suppressTopSpace">suppress empty space at the top of page</param>
        /// <param name="dvr">dvr, calculated based on margin collapsing state</param>
        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
        {
            if (suppressTopSpace && (StructuralCache.CurrentFormatContext.FinitePage || mcs == null))
                dvr = 0;
            else
            {
                MbpInfo mbp = MbpInfo.FromElement(Table);
                MarginCollapsingState mcsOut = null;
                MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsOut, out dvr);

                if (mcsOut != null)
                {
                    dvr = mcsOut.Margin;
                    mcsOut.Dispose();
                    mcsOut = null;
                }
            }
        }
예제 #42
0
 /// <summary>
 /// Collapse margins
 /// </summary>
 /// <param name="paraClient">
 /// IN: Paragraph's para client
 /// </param>
 /// <param name="mcs">
 /// IN: input margin collapsing state
 /// </param>
 /// <param name="fswdir">
 /// IN: current direction (of the track, in which margin collapsing is happening)
 /// </param>
 /// <param name="suppressTopSpace">
 /// IN: suppress empty space at the top of page
 /// </param>
 /// <param name="dvr">
 /// OUT: dvr, calculated based on margin collapsing state
 /// </param>
 internal virtual void CollapseMargin(
     BaseParaClient paraClient,          
     MarginCollapsingState mcs,           
     uint fswdir,                         
     bool suppressTopSpace,               
     out int dvr)                        
 {
     // Suppress top space only in paginated scenarios.
     dvr = (mcs == null || (suppressTopSpace)) ? 0 : mcs.Margin;
 }
예제 #43
0
            out IntPtr pmcsclientOut);         // OUT: MCSCLIENT that floater will return to track

        //------------------------------------------------------------------- 
        // GetDvrUsedForFloater
        //-------------------------------------------------------------------- 
        internal virtual void GetDvrUsedForFloater( 
            uint fswdirTrack,                   // IN:  direction of Track
            MarginCollapsingState mcs,          // IN:  input margin collapsing state 
            int dvrDisplaced,                   // IN:
            out int dvrUsed)                    // OUT:
        {
            // When floater is pushed down due to collision, text may need to be 
            // pushed down together with the floater. In such case dvrUsed needs to be
            // set to height of the floater. 
            // But for now there is no case, where we need this feature, hence dvrUsed is 
            // always 0.
            dvrUsed = 0; 
        }
        internal void UpdateBottomlessPara(
            IntPtr pfspara,                     // IN:  pointer to the para data
            ContainerParaClient paraClient,     // IN:
            int iArea,                          // IN:  column-span area index
            IntPtr pfsgeom,                     // IN:  pointer to geometry
            int fSuppressTopSpace,              // IN:  suppress empty space at the top of the page
            uint fswdir,                        // IN:  current direction
            int urTrack,                        // IN:  u of bootomless rectangle to fill
            int durTrack,                       // IN:  du of bootomless rectangle to fill
            int vrTrack,                        // IN:  v of bootomless rectangle to fill
            MarginCollapsingState mcs,          // IN:  input margin collapsing state
            PTS.FSKCLEAR fskclearIn,            // IN:  clear property that must be satisfied
            int fInterruptable,                 // IN:  formatting can be interrupted
            out PTS.FSFMTRBL fsfmtrbl,          // OUT: result of formatting the paragraph
            out int dvrUsed,                    // OUT: vertical space used by the para
            out PTS.FSBBOX fsbbox,              // OUT: para BBox
            out IntPtr pmcsclientOut,           // OUT: margin collapsing state at the bottom
            out PTS.FSKCLEAR fskclearOut,       // OUT: ClearIn for the next paragraph
            out int dvrTopSpace,                // OUT: top space due to collapsed margin
            out int fPageBecomesUninterruptable)// OUT: interruption is prohibited from now on
        {
            uint fswdirSubtrack = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty)));

            Debug.Assert(iArea == 0);

            // Top margin collapsing.
            int marginTop;
            MarginCollapsingState mcsContainer;

            MbpInfo mbp = MbpInfo.FromElement(Element);
            MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsContainer, out marginTop);
            if (PTS.ToBoolean(fSuppressTopSpace))
            {
                marginTop = 0;
            }

            // Set clear property
            Invariant.Assert(Element is Block || Element is ListItem);
            fskclearIn = PTS.WrapDirectionToFskclear((WrapDirection)Element.GetValue(Block.ClearFloatersProperty));

            if(fswdirSubtrack != fswdir)
            {
                PTS.FSRECT fsrcToFillSubtrack = new PTS.FSRECT(urTrack, 0, durTrack, 0);
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrcToFillSubtrack, fswdirSubtrack, out fsrcToFillSubtrack));

                urTrack = fsrcToFillSubtrack.u;
                durTrack = fsrcToFillSubtrack.du;
                mbp.MirrorMargin();
            }

            // Take into accound MBPs and modify subtrack metrics,
            // and make sure that subtrack is at least 1 unit wide (cannot measure at width <= 0)
            int urSubtrack, durSubtrack, vrSubtrack;
            int dvrSubTrackTopSpace = 0;
            urSubtrack  = Math.Max(Math.Min(urTrack + mbp.MBPLeft, urTrack + durTrack - 1), urTrack);
            durSubtrack = Math.Max(durTrack - (mbp.MBPLeft + mbp.MBPRight), 0);
            vrSubtrack  = vrTrack + (marginTop + mbp.BPTop);

            // Format subtrack
            try
            {
                PTS.Validate(PTS.FsUpdateBottomlessSubtrack(PtsContext.Context, pfspara, this.Handle, iArea,
                    pfsgeom, fSuppressTopSpace, fswdirSubtrack, urSubtrack, durSubtrack, vrSubtrack, 
                    (mcsContainer != null) ? mcsContainer.Handle : IntPtr.Zero, fskclearIn, fInterruptable, 
                    out fsfmtrbl, out dvrUsed, out fsbbox, out pmcsclientOut, 
                    out fskclearOut, out dvrSubTrackTopSpace, out fPageBecomesUninterruptable), PtsContext);
            }
            finally
            {
                // Destroy top margin collapsing state (not needed anymore).
                if (mcsContainer != null)
                {
                    mcsContainer.Dispose();
                    mcsContainer = null;
                }
            }

            if (fsfmtrbl != PTS.FSFMTRBL.fmtrblCollision)
            {
                // Bottom margin collapsing:
                // (1) retrieve mcs from the subtrack
                // (2) do margin collapsing; create a new margin collapsing state
                if (pmcsclientOut != IntPtr.Zero)
                {
                    mcsContainer = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                    PTS.ValidateHandle(mcsContainer);
                    pmcsclientOut = IntPtr.Zero;
                }
                int marginBottom;
                MarginCollapsingState mcsNew;
                MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, mcsContainer, out mcsNew, out marginBottom);
                pmcsclientOut = (mcsNew != null) ? mcsNew.Handle : IntPtr.Zero;

                // Since MCS returned by PTS is never passed back, destroy MCS provided by PTS.
                // If necessary, new MCS is created and passed back to PTS.
                if (mcsContainer != null)
                {
                    mcsContainer.Dispose();
                    mcsContainer = null;
                }

                // Take into accound MBPs and modify subtrack metrics
                dvrTopSpace = (mbp.BPTop != 0) ? marginTop : dvrSubTrackTopSpace;
                dvrUsed += (vrSubtrack - vrTrack) + marginBottom + mbp.BPBottom;
            }
            else
            {
                Debug.Assert(pmcsclientOut == IntPtr.Zero);
                pfspara = IntPtr.Zero;
                dvrTopSpace = 0;
            }

            // Adjust fsbbox to account for margins
            fsbbox.fsrc.u -= mbp.MBPLeft;
            fsbbox.fsrc.du += mbp.MBPLeft + mbp.MBPRight;
            if(fswdirSubtrack != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformBbox(fswdirSubtrack, ref pageRect, ref fsbbox, fswdir, out fsbbox));
            }

            // Update information about first/last chunk. In bottomless scenario
            // paragraph is not broken, so there is only one chunk.
            paraClient.SetChunkInfo(true, true);
        }
예제 #45
0
        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, StructuralCache.TextFormatterHost.PixelsPerDip);

                // 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;
        }
        internal void FormatParaFinite(
            ContainerParaClient paraClient,     // IN:
            IntPtr pbrkrecIn,                   // IN:  break record---use if !IntPtr.Zero
            int fBRFromPreviousPage,            // IN:  break record was created on previous page
            int iArea,                          // IN:  column-span area index
            IntPtr footnoteRejector,            // IN:
            IntPtr geometry,                    // IN:  pointer to geometry
            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:  current direction
            ref PTS.FSRECT fsrcToFill,          // IN:  rectangle to fill
            MarginCollapsingState mcs,          // IN:  input margin collapsing state
            PTS.FSKCLEAR fskclearIn,            // IN:  clear property that must be satisfied
            PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn,
                                                // IN: suppress breaks at track start?
            out PTS.FSFMTR fsfmtr,              // OUT: result of formatting the paragraph
            out IntPtr pfspara,                 // OUT: pointer to the para data
            out IntPtr pbrkrecOut,              // OUT: pointer to the para break record
            out int dvrUsed,                    // OUT: vertical space used by the para
            out PTS.FSBBOX fsbbox,              // OUT: para BBox
            out IntPtr pmcsclientOut,           // OUT: margin collapsing state at the bottom
            out PTS.FSKCLEAR fskclearOut,       // OUT: ClearIn for the next paragraph
            out int dvrTopSpace)                // OUT: top space due to collapsed margin
        {
            uint fswdirSubtrack = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty)));

            Debug.Assert(iArea == 0);
            // Currently it is possible to get MCS and BR in following situation:
            // At the end of the page there is a paragraph with delayed figure, so the figure
            // gets delayed to the next page. But part of the next paragraph fits in the page,
            // so it gets broken. PTS creates BR with delayed figure and broken para.
            // PTS will format the next page starting from delayed figure, which can produce MCS.
            // So when the next paragraph is continued from BR, it has MCS.
            // This problem is currently investigated by PTS team: PTSLS bug 915.
            // For now, MCS gets ignored here.
            //ErrorHandler.Assert(pbrkrecIn == IntPtr.Zero || mcs == null, ErrorHandler.BrokenParaHasMcs);
            if (mcs != null && pbrkrecIn != IntPtr.Zero)
            {
                mcs = null;
            }

            int marginTop = 0;
            int marginBottom = 0;
            MarginCollapsingState mcsContainer = null;

            // Set clear property
            Invariant.Assert(Element is Block || Element is ListItem);
            fskclearIn = PTS.WrapDirectionToFskclear((WrapDirection)Element.GetValue(Block.ClearFloatersProperty));


            // Take into accound MBPs and modify subtrack metrics,
            // and make sure that subtrack is at least 1 unit wide (cannot measure at width <= 0)
            PTS.FSRECT fsrcToFillSubtrack = fsrcToFill;
            MbpInfo mbp = MbpInfo.FromElement(Element);

            if(fswdirSubtrack != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;

                PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrcToFillSubtrack, fswdirSubtrack, out fsrcToFillSubtrack));
                PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrcToFill, fswdirSubtrack, out fsrcToFill));
                mbp.MirrorMargin();
            }

            fsrcToFillSubtrack.u  += mbp.MBPLeft;
            fsrcToFillSubtrack.du -= mbp.MBPLeft + mbp.MBPRight;
            fsrcToFillSubtrack.u  = Math.Max(Math.Min(fsrcToFillSubtrack.u, fsrcToFill.u + fsrcToFill.du - 1), fsrcToFill.u);
            fsrcToFillSubtrack.du = Math.Max(fsrcToFillSubtrack.du, 0);

            if (pbrkrecIn == IntPtr.Zero)
            {
                // Top margin collapsing. If suppresing top space, top margin is always 0.
                MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsContainer, out marginTop);
                if (PTS.ToBoolean(fSuppressTopSpace))
                {
                    marginTop = 0;
                }

                fsrcToFillSubtrack.v  += marginTop + mbp.BPTop;
                fsrcToFillSubtrack.dv -= marginTop + mbp.BPTop;
                fsrcToFillSubtrack.v = Math.Max(Math.Min(fsrcToFillSubtrack.v, fsrcToFill.v + fsrcToFill.dv - 1), fsrcToFill.v);
                fsrcToFillSubtrack.dv = Math.Max(fsrcToFillSubtrack.dv, 0);
            }

            // Format subtrack
            int dvrSubTrackTopSpace = 0;
            try
            {
                PTS.Validate(PTS.FsFormatSubtrackFinite(PtsContext.Context, pbrkrecIn, fBRFromPreviousPage, this.Handle, iArea, 
                    footnoteRejector, geometry, fEmptyOk, fSuppressTopSpace, fswdirSubtrack, ref fsrcToFillSubtrack, 
                    (mcsContainer != null) ? mcsContainer.Handle : IntPtr.Zero, fskclearIn, 
                    fsksuppresshardbreakbeforefirstparaIn, 
                    out fsfmtr, out pfspara, out pbrkrecOut, out dvrUsed, out fsbbox, out pmcsclientOut, out fskclearOut, 
                    out dvrSubTrackTopSpace), PtsContext);
            }
            finally
            {
                // Destroy top margin collapsing state (not needed anymore).
                if (mcsContainer != null)
                {
                    mcsContainer.Dispose();
                    mcsContainer = null;
                }
                // 
                if (dvrSubTrackTopSpace > PTS.dvBottomUndefined / 2)
                {
                    dvrSubTrackTopSpace = 0;
                }
            }

            // Take into accound MBPs and modify subtrack metrics
            dvrTopSpace = (mbp.BPTop != 0) ? marginTop : dvrSubTrackTopSpace;
            dvrUsed += (fsrcToFillSubtrack.v - fsrcToFill.v);

            // Initialize subtrack metrics
            if (fsfmtr.kstop >= PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace)   // No progress or collision
            {
                dvrUsed = 0;
            }

            // Since MCS returned by PTS is never passed back, destroy MCS provided by PTS.
            // If necessary, new MCS is created and passed back to PTS.
            if (pmcsclientOut != IntPtr.Zero)
            {
                mcsContainer = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                PTS.ValidateHandle(mcsContainer);
                pmcsclientOut = IntPtr.Zero;
            }

            if (fsfmtr.kstop == PTS.FSFMTRKSTOP.fmtrGoalReached)
            {
                // Bottom margin collapsing:
                // (a) retrieve mcs from the subtrack
                // (b) do margin collapsing; create a new margin collapsing state
                // There is no bottom margin collapsing if paragraph will be continued (output break record is not null).
                MarginCollapsingState mcsNew = null;
                MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, mcsContainer, out mcsNew, out marginBottom);
                pmcsclientOut = (mcsNew != null) ? mcsNew.Handle : IntPtr.Zero;

                // If we exceed fill rectangle after adding bottom border and padding, clip them
                dvrUsed += marginBottom + mbp.BPBottom;
                dvrUsed = Math.Min(fsrcToFill.dv, dvrUsed);
            }

            // Since MCS returned by PTS is never passed back, destroy MCS provided by PTS.
            // If necessary, new MCS is created and passed back to PTS.
            if (mcsContainer != null)
            {
                mcsContainer.Dispose();
                mcsContainer = null;
            }

            // Adjust fsbbox to account for margins
            fsbbox.fsrc.u -= mbp.MBPLeft;
            fsbbox.fsrc.du += mbp.MBPLeft + mbp.MBPRight;

            if(fswdirSubtrack != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformBbox(fswdirSubtrack, ref pageRect, ref fsbbox, fswdir, out fsbbox));
            }

            // Update information about first/last chunk
            paraClient.SetChunkInfo(pbrkrecIn == IntPtr.Zero, pbrkrecOut == IntPtr.Zero);
        }
예제 #47
0
        internal unsafe void FormatParaFinite(
            SubpageParaClient paraClient,       // IN:
            IntPtr pbrkrecIn,                   // IN:  break record---use if !NULL
            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:  current direction
            ref PTS.FSRECT fsrcToFill,          // IN:  rectangle to fill
            MarginCollapsingState mcs,          // IN:  input margin collapsing state
            PTS.FSKCLEAR fskclearIn,            // IN:  clear property that must be satisfied
            PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn,
            // IN: suppress breaks at track start?
            out PTS.FSFMTR fsfmtr,              // OUT: result of formatting the paragraph
            out IntPtr pfspara,                 // OUT: pointer to the para data
            out IntPtr pbrkrecOut,              // OUT: pointer to the para break record
            out int dvrUsed,                    // OUT: vertical space used by the para
            out PTS.FSBBOX fsbbox,              // OUT: para BBox
            out IntPtr pmcsclientOut,           // OUT: margin collapsing state at the bottom
            out PTS.FSKCLEAR fskclearOut,       // OUT: ClearIn for the next paragraph
            out int dvrTopSpace)                // OUT: top space due to collapsed margin
        {
            uint fswdirSubpage = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty)));

            int     subpageWidth, subpageHeight;
            int     cColumns;
            int     marginTop, marginBottom;
            MbpInfo mbp;
            MarginCollapsingState mcsSubpage, mcsBottom;

            PTS.FSRECT          fsrcSubpageMargin;
            PTS.FSCOLUMNINFO [] columnInfoCollection;

            // Currently it is possible to get MCS and BR in following situation:
            // At the end of the page there is a paragraph with delayed figure, so the figure
            // gets delayed to the next page. But part of the next paragraph fits in the page,
            // so it gets broken. PTS creates BR with delayed figure and broken para.
            // PTS will format the next page starting from delayed figure, which can produce MCS.
            // So when the next paragraph is continued from BR, it has MCS.
            // This problem is currently investigated by PTS team: PTSLS bug 915.
            // For now, MCS gets ignored here.
            //Debug.Assert(pbrkrecIn == IntPtr.Zero || mcs == null, "Broken paragraph cannot have margin collapsing state.");
            if (mcs != null && pbrkrecIn != IntPtr.Zero)
            {
                mcs = null;
            }

            // Initialize the subpage size and its margin.
            fsrcSubpageMargin = new PTS.FSRECT();
            subpageWidth      = fsrcToFill.du;
            subpageHeight     = fsrcToFill.dv;

            // Set clear property
            Invariant.Assert(Element is TableCell || Element is AnchoredBlock);
            fskclearIn = PTS.WrapDirectionToFskclear((WrapDirection)Element.GetValue(Block.ClearFloatersProperty));

            // Take into account MBPs and modify subpage metrics,
            // and make sure that subpage is at least 1 unit wide (cannot measure at width <= 0)
            marginTop  = 0;
            mcsSubpage = null;

            // Get MBP info. Since subpage height and width must be at least 1, the max size for MBP is subpage dimensions less 1
            mbp = MbpInfo.FromElement(Element, StructuralCache.TextFormatterHost.PixelsPerDip);

            if (fswdirSubpage != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrcToFill, fswdirSubpage, out fsrcToFill));
                mbp.MirrorMargin();
            }

            subpageWidth = Math.Max(1, subpageWidth - (mbp.MBPLeft + mbp.MBPRight));
            if (pbrkrecIn == IntPtr.Zero)
            {
                // Top margin collapsing. If suppresing top space, top margin is always 0.
                MarginCollapsingState.CollapseTopMargin(PtsContext, mbp, mcs, out mcsSubpage, out marginTop);
                if (PTS.ToBoolean(fSuppressTopSpace))
                {
                    marginTop = 0;
                }
                subpageHeight = Math.Max(1, subpageHeight - (marginTop + mbp.BPTop));
                // Destroy top margin collapsing state (not needed anymore).
                if (mcsSubpage != null)
                {
                    mcsSubpage.Dispose();
                    mcsSubpage = null;
                }
            }
            else
            {
                Debug.Assert(fSuppressTopSpace == 1, "Top space should be always suppressed at the top of broken paragraph.");
            }
            fsrcSubpageMargin.du = subpageWidth;
            fsrcSubpageMargin.dv = subpageHeight;

            // Initialize column info
            ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(_element);
            double     lineHeight     = DynamicPropertyReader.GetLineHeightValue(_element);
            double     pageFontSize   = (double)_structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty);
            FontFamily pageFontFamily = (FontFamily)_structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty);

            // Get columns info, setting ownerIsFlowDocument flag to false. A flow document should not be formatted as a subpage and we
            // do not want default column widths to be set on TableCells and floaters
            cColumns             = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, TextDpi.FromTextDpi(subpageWidth), pageFontSize, pageFontFamily, false);
            columnInfoCollection = new PTS.FSCOLUMNINFO[cColumns];
            fixed(PTS.FSCOLUMNINFO *rgColumnInfo = columnInfoCollection)
            {
                PtsHelper.GetColumnsInfo(columnProperties, lineHeight, TextDpi.FromTextDpi(subpageWidth), pageFontSize, pageFontFamily, cColumns, rgColumnInfo, false);
            }

            // Format subpage
            StructuralCache.CurrentFormatContext.PushNewPageData(new Size(TextDpi.FromTextDpi(subpageWidth), TextDpi.FromTextDpi(subpageHeight)),
                                                                 new Thickness(),
                                                                 false,
                                                                 true);

            fixed(PTS.FSCOLUMNINFO *rgColumnInfo = columnInfoCollection)
            {
                PTS.Validate(PTS.FsCreateSubpageFinite(PtsContext.Context, pbrkrecIn, fBRFromPreviousPage, _mainTextSegment.Handle,
                                                       footnoteRejector, fEmptyOk, fSuppressTopSpace, fswdir, subpageWidth, subpageHeight,
                                                       ref fsrcSubpageMargin, cColumns, rgColumnInfo, PTS.False,
                                                       0, null, null, 0, null, null, PTS.FromBoolean(false),
                                                       fsksuppresshardbreakbeforefirstparaIn,
                                                       out fsfmtr, out pfspara, out pbrkrecOut, out dvrUsed, out fsbbox, out pmcsclientOut, out dvrTopSpace), PtsContext);
            }

            StructuralCache.CurrentFormatContext.PopPageData();

            fskclearOut = PTS.FSKCLEAR.fskclearNone;

            if (PTS.ToBoolean(fsbbox.fDefined))
            {
                // Workaround for PTS bug 860: get max of the page rect and
                // bounding box of the page.
                dvrUsed       = Math.Max(dvrUsed, fsbbox.fsrc.dv + fsbbox.fsrc.v);
                fsrcToFill.du = Math.Max(fsrcToFill.du, fsbbox.fsrc.du + fsbbox.fsrc.u);
            }

            if (pbrkrecIn == IntPtr.Zero) // if first chunk
            {
                // Take into account MBPs and modify subpage metrics
                dvrTopSpace = (mbp.BPTop != 0) ? marginTop : dvrTopSpace;
                dvrUsed    += (marginTop + mbp.BPTop);
            }

            if (pmcsclientOut != IntPtr.Zero)
            {
                mcsSubpage = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState;
                PTS.ValidateHandle(mcsSubpage);
                pmcsclientOut = IntPtr.Zero;
            }

            // Initialize subpage metrics
            if (fsfmtr.kstop >= PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace)   // No progress or collision
            {
                dvrUsed = dvrTopSpace = 0;
                //pbrkrecOut = IntPtr.Zero;
                //pfspara = IntPtr.Zero;
                //pmcsclientOut = IntPtr.Zero;
            }
            else
            {
                if (fsfmtr.kstop == PTS.FSFMTRKSTOP.fmtrGoalReached)
                {
                    // Bottom margin collapsing:
                    // (a) retrieve mcs from the subpage
                    // (b) do margin collapsing; create a new margin collapsing state
                    // There is no bottom margin collapsing if paragraph will be continued (output break record is not null).
                    MarginCollapsingState.CollapseBottomMargin(PtsContext, mbp, mcsSubpage, out mcsBottom, out marginBottom);
                    pmcsclientOut = (mcsBottom != null) ? mcsBottom.Handle : IntPtr.Zero;

                    if (pmcsclientOut == IntPtr.Zero) // if last chunk
                    {
                        dvrUsed += marginBottom + mbp.BPBottom;
                    }
                }

                // Update bounding box
                fsbbox.fsrc.u  = fsrcToFill.u + mbp.MarginLeft;
                fsbbox.fsrc.v  = fsrcToFill.v + dvrTopSpace;
                fsbbox.fsrc.du = Math.Max(fsrcToFill.du - (mbp.MarginLeft + mbp.MarginRight), 0);
                fsbbox.fsrc.dv = Math.Max(dvrUsed - dvrTopSpace, 0);
            }

            if (fswdirSubpage != fswdir)
            {
                PTS.FSRECT pageRect = StructuralCache.CurrentFormatContext.PageRect;
                PTS.Validate(PTS.FsTransformBbox(fswdirSubpage, ref pageRect, ref fsbbox, fswdir, out fsbbox));
            }


            // Since MCS returned by PTS is never passed back, destroy MCS provided by PTS.
            // If necessary, new MCS is created and passed back to PTS (see above).
            if (mcsSubpage != null)
            {
                mcsSubpage.Dispose();
                mcsSubpage = null;
            }


            // Update information about first/last chunk
            paraClient.SetChunkInfo(pbrkrecIn == IntPtr.Zero, pbrkrecOut == IntPtr.Zero);
        }
 //-------------------------------------------------------------------
 // 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;
     }
 }