//------------------------------------------------------------------- // 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(); } }
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; }
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; }
// ------------------------------------------------------------------ // 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; } }
//------------------------------------------------------ // // 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; } } }
// 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; }
/// <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; }
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; }
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; }
//------------------------------------------------------------------- // 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; } }
//------------------------------------------------------------------- // 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; } }
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; } }
// 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); } }
// 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; } }
/// <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); } } }
// 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(); } }
// ------------------------------------------------------------------ // 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; }
// 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); }
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 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; }
//------------------------------------------------------------------- // 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(); } }
//------------------------------------------------------------------- // 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); }
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); }
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
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); }
//------------------------------------------------------ // // 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; } } }
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); }
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); }
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); }