// ------------------------------------------------------------------ // Returns calculated column information - count, width, gap and rule. // ------------------------------------------------------------------ internal static void GetColumnMetrics(StructuralCache structuralCache, out int cColumns, out double width, out double gap, out double rule) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(structuralCache.PropertyOwner); FontFamily pageFontFamily = (FontFamily)structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty); double lineHeight = DynamicPropertyReader.GetLineHeightValue(structuralCache.PropertyOwner); double pageFontSize = (double)structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty); Size pageSize = structuralCache.CurrentFormatContext.PageSize; Thickness pageMargin = structuralCache.CurrentFormatContext.PageMargin; double pageWidth = pageSize.Width - (pageMargin.Left + pageMargin.Right); cColumns = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, pageWidth, pageFontSize, pageFontFamily, true); double freeSpace; rule = columnProperties.ColumnRuleWidth; PtsHelper.GetColumnMetrics(columnProperties, pageWidth, pageFontSize, pageFontFamily, true, cColumns, ref lineHeight, out width, out freeSpace, out gap); if (columnProperties.IsColumnWidthFlexible && columnProperties.ColumnSpaceDistribution == ColumnSpaceDistribution.Between) { width += freeSpace / cColumns; } width = Math.Min(width, pageWidth); }
// ------------------------------------------------------------------ // Calculates a page margin adjustment to eliminate free space if column width is not flexible // ------------------------------------------------------------------ internal static double CalculatePageMarginAdjustment(StructuralCache structuralCache, double pageMarginWidth) { double pageMarginAdjustment = 0.0; DependencyObject o = structuralCache.Section.Element; if (o is FlowDocument) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(o); if (!columnProperties.IsColumnWidthFlexible) { double lineHeight = DynamicPropertyReader.GetLineHeightValue(o); double pageFontSize = (double)structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty); int ccol = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, pageMarginWidth, pageFontSize, pageFontFamily, true); double columnWidth; double freeSpace; double gap; GetColumnMetrics(columnProperties, pageMarginWidth, pageFontSize, pageFontFamily, true, ccol, ref lineHeight, out columnWidth, out freeSpace, out gap); pageMarginAdjustment = freeSpace; } } return(pageMarginAdjustment); }
// Token: 0x06006943 RID: 26947 RVA: 0x001DCE48 File Offset: 0x001DB048 internal static int CalculateColumnCount(ColumnPropertiesGroup columnProperties, double lineHeight, double pageWidth, double pageFontSize, FontFamily pageFontFamily, bool enableColumns) { int val = 1; double columnRuleWidth = columnProperties.ColumnRuleWidth; if (enableColumns) { double num; if (columnProperties.ColumnGapAuto) { num = 1.0 * lineHeight; } else { num = columnProperties.ColumnGap; } if (!columnProperties.ColumnWidthAuto) { double columnWidth = columnProperties.ColumnWidth; val = (int)((pageWidth + num) / (columnWidth + num)); } else { double num2 = 20.0 * pageFontSize; val = (int)((pageWidth + num) / (num2 + num)); } } return(Math.Max(1, Math.Min(999, val))); }
// Token: 0x06006944 RID: 26948 RVA: 0x001DCEC4 File Offset: 0x001DB0C4 internal static void GetColumnMetrics(ColumnPropertiesGroup columnProperties, double pageWidth, double pageFontSize, FontFamily pageFontFamily, bool enableColumns, int cColumns, ref double lineHeight, out double columnWidth, out double freeSpace, out double gapSpace) { double columnRuleWidth = columnProperties.ColumnRuleWidth; if (!enableColumns) { Invariant.Assert(cColumns == 1); columnWidth = pageWidth; gapSpace = 0.0; lineHeight = 0.0; freeSpace = 0.0; } else { if (columnProperties.ColumnWidthAuto) { columnWidth = 20.0 * pageFontSize; } else { columnWidth = columnProperties.ColumnWidth; } if (columnProperties.ColumnGapAuto) { gapSpace = 1.0 * lineHeight; } else { gapSpace = columnProperties.ColumnGap; } } columnWidth = Math.Max(1.0, Math.Min(columnWidth, pageWidth)); freeSpace = pageWidth - (double)cColumns * columnWidth - (double)(cColumns - 1) * gapSpace; freeSpace = Math.Max(0.0, freeSpace); }
private void UpdateSectionVisuals(SectionVisual visual, PTS.FSKUPDATE fskupdInherited, ref PTS.FSSECTIONDESCRIPTION sectionDesc) { PTS.FSKUPDATE fskupdate = sectionDesc.fsupdinf.fskupd; if (fskupdate == PTS.FSKUPDATE.fskupdInherited) { fskupdate = fskupdInherited; } ErrorHandler.Assert(fskupdate != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); if (fskupdate == PTS.FSKUPDATE.fskupdNoChange) { return; } PTS.FSSECTIONDETAILS fssectiondetails; PTS.Validate(PTS.FsQuerySectionDetails(this.PtsContext.Context, sectionDesc.pfssection, out fssectiondetails)); bool flag; if (PTS.ToBoolean(fssectiondetails.fFootnotesAsPagenotes)) { ErrorHandler.Assert(fssectiondetails.u.withpagenotes.cEndnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); flag = (fssectiondetails.u.withpagenotes.cBasicColumns == 0); if (!flag) { PTS.FSTRACKDESCRIPTION[] array; PtsHelper.TrackListFromSection(this.PtsContext, sectionDesc.pfssection, ref fssectiondetails, out array); flag = (array.Length == 0); if (!flag) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(this._section.Element); visual.DrawColumnRules(ref array, TextDpi.FromTextDpi(sectionDesc.fsrc.v), TextDpi.FromTextDpi(sectionDesc.fsrc.dv), columnProperties); VisualCollection children = visual.Children; if (fskupdate == PTS.FSKUPDATE.fskupdNew) { children.Clear(); for (int i = 0; i < array.Length; i++) { children.Add(new ContainerVisual()); } } ErrorHandler.Assert(children.Count == array.Length, ErrorHandler.ColumnVisualCountMismatch); for (int j = 0; j < array.Length; j++) { ContainerVisual containerVisual = (ContainerVisual)children[j]; PtsHelper.UpdateTrackVisuals(this.PtsContext, containerVisual.Children, fskupdate, ref array[j]); } } } } else { ErrorHandler.Assert(false, ErrorHandler.NotSupportedCompositeColumns); flag = true; } if (flag) { visual.Children.Clear(); } }
internal unsafe void GetSectionColumnInfo(uint fswdir, int ncol, PTS.FSCOLUMNINFO *pfscolinfo, out int ccol) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(this.Element); Size pageSize = this._structuralCache.CurrentFormatContext.PageSize; double lineHeightValue = DynamicPropertyReader.GetLineHeightValue(this.Element); Thickness pageMargin = this._structuralCache.CurrentFormatContext.PageMargin; double pageFontSize = (double)this._structuralCache.PropertyOwner.GetValue(TextElement.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)this._structuralCache.PropertyOwner.GetValue(TextElement.FontFamilyProperty); bool finitePage = this._structuralCache.CurrentFormatContext.FinitePage; ccol = ncol; PtsHelper.GetColumnsInfo(columnProperties, lineHeightValue, pageSize.Width - (pageMargin.Left + pageMargin.Right), pageFontSize, pageFontFamily, ncol, pfscolinfo, finitePage); }
// ------------------------------------------------------------------ // GetColumnMetrics // ------------------------------------------------------------------ internal static void GetColumnMetrics(ColumnPropertiesGroup columnProperties, double pageWidth, double pageFontSize, FontFamily pageFontFamily, bool enableColumns, int cColumns, ref double lineHeight, out double columnWidth, out double freeSpace, out double gapSpace) { double rule = columnProperties.ColumnRuleWidth; if (!enableColumns) { Invariant.Assert(cColumns == 1); columnWidth = pageWidth; gapSpace = 0; lineHeight = 0; freeSpace = 0; } else { // For FlowDocument, calculate default column width if (columnProperties.ColumnWidthAuto) { columnWidth = 20 * pageFontSize; } else { columnWidth = columnProperties.ColumnWidth; } if (columnProperties.ColumnGapAuto) { gapSpace = 1 * lineHeight; } else { gapSpace = columnProperties.ColumnGap; } } columnWidth = Math.Max(1, Math.Min(columnWidth, pageWidth)); freeSpace = pageWidth - (cColumns * columnWidth) - (cColumns - 1) * gapSpace; freeSpace = Math.Max(0, freeSpace); }
// Token: 0x06006A41 RID: 27201 RVA: 0x001E3E34 File Offset: 0x001E2034 internal void GetSectionProperties(out int fNewPage, out uint fswdir, out int fApplyColumnBalancing, out int ccol, out int cSegmentDefinedColumnSpanAreas, out int cHeightDefinedColumnSpanAreas) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(this.Element); Size pageSize = this._structuralCache.CurrentFormatContext.PageSize; double lineHeightValue = DynamicPropertyReader.GetLineHeightValue(this.Element); Thickness pageMargin = this._structuralCache.CurrentFormatContext.PageMargin; double pageFontSize = (double)this._structuralCache.PropertyOwner.GetValue(TextElement.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)this._structuralCache.PropertyOwner.GetValue(TextElement.FontFamilyProperty); bool finitePage = this._structuralCache.CurrentFormatContext.FinitePage; fNewPage = 0; fswdir = PTS.FlowDirectionToFswdir((FlowDirection)this._structuralCache.PropertyOwner.GetValue(FrameworkElement.FlowDirectionProperty)); fApplyColumnBalancing = 0; ccol = PtsHelper.CalculateColumnCount(columnProperties, lineHeightValue, pageSize.Width - (pageMargin.Left + pageMargin.Right), pageFontSize, pageFontFamily, finitePage); cSegmentDefinedColumnSpanAreas = 0; cHeightDefinedColumnSpanAreas = 0; }
internal unsafe static void GetColumnsInfo(ColumnPropertiesGroup columnProperties, double lineHeight, double pageWidth, double pageFontSize, FontFamily pageFontFamily, int cColumns, PTS.FSCOLUMNINFO *pfscolinfo, bool enableColumns) { double columnRuleWidth = columnProperties.ColumnRuleWidth; double num; double num2; double num3; PtsHelper.GetColumnMetrics(columnProperties, pageWidth, pageFontSize, pageFontFamily, enableColumns, cColumns, ref lineHeight, out num, out num2, out num3); if (!columnProperties.IsColumnWidthFlexible) { for (int i = 0; i < cColumns; i++) { pfscolinfo[i].durBefore = TextDpi.ToTextDpi((i == 0) ? 0.0 : num3); pfscolinfo[i].durWidth = TextDpi.ToTextDpi(num); pfscolinfo[i].durBefore = Math.Max(0, pfscolinfo[i].durBefore); pfscolinfo[i].durWidth = Math.Max(1, pfscolinfo[i].durWidth); } return; } for (int j = 0; j < cColumns; j++) { if (columnProperties.ColumnSpaceDistribution == ColumnSpaceDistribution.Right) { pfscolinfo[j].durWidth = TextDpi.ToTextDpi((j == cColumns - 1) ? (num + num2) : num); } else if (columnProperties.ColumnSpaceDistribution == ColumnSpaceDistribution.Left) { pfscolinfo[j].durWidth = TextDpi.ToTextDpi((j == 0) ? (num + num2) : num); } else { pfscolinfo[j].durWidth = TextDpi.ToTextDpi(num + num2 / (double)cColumns); } if (pfscolinfo[j].durWidth > TextDpi.ToTextDpi(pageWidth)) { pfscolinfo[j].durWidth = TextDpi.ToTextDpi(pageWidth); } pfscolinfo[j].durBefore = TextDpi.ToTextDpi((j == 0) ? 0.0 : num3); pfscolinfo[j].durBefore = Math.Max(0, pfscolinfo[j].durBefore); pfscolinfo[j].durWidth = Math.Max(1, pfscolinfo[j].durWidth); } }
// ------------------------------------------------------------------ // Calculate column count based on column properties. // If column width is Auto column count is calculated by assuming // ColumnWidth as 20*FontSize // ------------------------------------------------------------------ internal static int CalculateColumnCount( ColumnPropertiesGroup columnProperties, double lineHeight, double pageWidth, double pageFontSize, FontFamily pageFontFamily, bool enableColumns) { int columns = 1; double gap; double rule = columnProperties.ColumnRuleWidth; if (enableColumns) { if (columnProperties.ColumnGapAuto) { gap = 1 * lineHeight; } else { gap = columnProperties.ColumnGap; } if (!columnProperties.ColumnWidthAuto) { // Column count is ignored in this case double column = columnProperties.ColumnWidth; columns = (int)((pageWidth + gap) / (column + gap)); } else { // Column width is assumed to be 20*FontSize double column = 20 * pageFontSize; columns = (int)((pageWidth + gap) / (column + gap)); } } return(Math.Max(1, Math.Min(PTS.Restrictions.tscColumnRestriction - 1, columns))); // at least 1 column is required }
// ------------------------------------------------------------------ // GetSectionProperties // ------------------------------------------------------------------ /// <summary> /// Get section properties /// </summary> /// <param name="fNewPage"> /// OUT: stop page before this section? /// </param> /// <param name="fswdir"> /// OUT: direction of this section /// </param> /// <param name="fApplyColumnBalancing"> /// OUT: apply column balancing to this section? /// </param> /// <param name="ccol"> /// OUT: number of columns in the main text segment /// </param> /// <param name="cSegmentDefinedColumnSpanAreas"> /// OUT: number of segment-defined columnspan areas /// </param> /// <param name="cHeightDefinedColumnSpanAreas"> /// OUT: number of height-defined columnsapn areas /// </param> internal void GetSectionProperties( out int fNewPage, out uint fswdir, out int fApplyColumnBalancing, out int ccol, out int cSegmentDefinedColumnSpanAreas, out int cHeightDefinedColumnSpanAreas) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(Element); Size pageSize = _structuralCache.CurrentFormatContext.PageSize; double lineHeight = DynamicPropertyReader.GetLineHeightValue(Element); Thickness pageMargin = _structuralCache.CurrentFormatContext.PageMargin; double pageFontSize = (double)_structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)_structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty); bool enableColumns = _structuralCache.CurrentFormatContext.FinitePage; fNewPage = PTS.False; // Since only one section is supported, don't force page break before. fswdir = PTS.FlowDirectionToFswdir((FlowDirection)_structuralCache.PropertyOwner.GetValue(FrameworkElement.FlowDirectionProperty)); fApplyColumnBalancing = PTS.False; ccol = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, pageSize.Width - (pageMargin.Left + pageMargin.Right), pageFontSize, pageFontFamily, enableColumns); cSegmentDefinedColumnSpanAreas = 0; cHeightDefinedColumnSpanAreas = 0; }
// Token: 0x06006942 RID: 26946 RVA: 0x001DCDB0 File Offset: 0x001DAFB0 internal static double CalculatePageMarginAdjustment(StructuralCache structuralCache, double pageMarginWidth) { double result = 0.0; DependencyObject element = structuralCache.Section.Element; if (element is FlowDocument) { ColumnPropertiesGroup columnPropertiesGroup = new ColumnPropertiesGroup(element); if (!columnPropertiesGroup.IsColumnWidthFlexible) { double lineHeightValue = DynamicPropertyReader.GetLineHeightValue(element); double pageFontSize = (double)structuralCache.PropertyOwner.GetValue(TextElement.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)structuralCache.PropertyOwner.GetValue(TextElement.FontFamilyProperty); int cColumns = PtsHelper.CalculateColumnCount(columnPropertiesGroup, lineHeightValue, pageMarginWidth, pageFontSize, pageFontFamily, true); double num; double num2; double num3; PtsHelper.GetColumnMetrics(columnPropertiesGroup, pageMarginWidth, pageFontSize, pageFontFamily, true, cColumns, ref lineHeightValue, out num, out num2, out num3); result = num2; } } return(result); }
internal static unsafe void GetColumnsInfo( ColumnPropertiesGroup columnProperties, double lineHeight, double pageWidth, double pageFontSize, FontFamily pageFontFamily, int cColumns, PTS.FSCOLUMNINFO *pfscolinfo, bool enableColumns) { Debug.Assert(cColumns > 0, "At least one column is required."); double columnWidth; double freeSpace; double gap; double rule = columnProperties.ColumnRuleWidth; GetColumnMetrics(columnProperties, pageWidth, pageFontSize, pageFontFamily, enableColumns, cColumns, ref lineHeight, out columnWidth, out freeSpace, out gap); // Set columns information if (!columnProperties.IsColumnWidthFlexible) { // All columns have the declared width // ColumnGap is flexible and is increased based on ColumnSpaceDistribution policy // (ColumnGap is effectively min) for (int i = 0; i < cColumns; i++) { // Today there is no way to change the default value of ColumnSpaceDistribution. // If column widths are not flexible, always allocate unused space on the right side. pfscolinfo[i].durBefore = TextDpi.ToTextDpi((i == 0) ? 0 : gap); pfscolinfo[i].durWidth = TextDpi.ToTextDpi(columnWidth); // ColumnWidth has to be > 0 and SpaceBefore has to be >= 0 pfscolinfo[i].durBefore = Math.Max(0, pfscolinfo[i].durBefore); pfscolinfo[i].durWidth = Math.Max(1, pfscolinfo[i].durWidth); } } else { // ColumnGap is honored // ColumnWidth is effectively min, and space is distributed according to ColumnSpaceDistribution policy for (int i = 0; i < cColumns; i++) { if (columnProperties.ColumnSpaceDistribution == ColumnSpaceDistribution.Right) { pfscolinfo[i].durWidth = TextDpi.ToTextDpi((i == cColumns - 1) ? columnWidth + freeSpace : columnWidth); } else if (columnProperties.ColumnSpaceDistribution == ColumnSpaceDistribution.Left) { pfscolinfo[i].durWidth = TextDpi.ToTextDpi((i == 0) ? columnWidth + freeSpace : columnWidth); } else { pfscolinfo[i].durWidth = TextDpi.ToTextDpi(columnWidth + (freeSpace / cColumns)); } // If calculated column width is greater than the page width, set it to page width to // avoid clipping if (pfscolinfo[i].durWidth > TextDpi.ToTextDpi(pageWidth)) { pfscolinfo[i].durWidth = TextDpi.ToTextDpi(pageWidth); } pfscolinfo[i].durBefore = TextDpi.ToTextDpi((i == 0) ? 0 : gap); // ColumnWidth has to be > 0 and SpaceBefore has to be >= 0 pfscolinfo[i].durBefore = Math.Max(0, pfscolinfo[i].durBefore); pfscolinfo[i].durWidth = Math.Max(1, pfscolinfo[i].durWidth); } } }
internal override void ValidateVisual(PTS.FSKUPDATE fskupdInherited) { // Floater is always reported as NEW. Override PTS inherited value. fskupdInherited = PTS.FSKUPDATE.fskupdNew; // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); // Obtain all mbd info MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element, Paragraph.StructuralCache.TextFormatterHost.PixelsPerDip); if (ThisFlowDirection != PageFlowDirection) { mbp.MirrorBP(); } Brush backgroundBrush = (Brush)Paragraph.Element.GetValue(TextElement.BackgroundProperty); Visual.DrawBackgroundAndBorder(backgroundBrush, mbp.BorderBrush, mbp.Border, _rect.FromTextDpi(), IsFirstChunk, IsLastChunk); ContainerVisual pageContentVisual; ContainerVisual floatingElementsVisual; if (_visual.Children.Count != 2) { _visual.Children.Clear(); _visual.Children.Add(new ContainerVisual()); _visual.Children.Add(new ContainerVisual()); } pageContentVisual = (ContainerVisual)_visual.Children[0]; floatingElementsVisual = (ContainerVisual)_visual.Children[1]; // Subpage content may be simple or complex - // depending of set of features used in the content of the subpage. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { // (1) simple subpage (contains only one track) PTS.FSKUPDATE fskupd = subpageDetails.u.simple.trackdescr.fsupdinf.fskupd; if (fskupd == PTS.FSKUPDATE.fskupdInherited) { fskupd = fskupdInherited; } VisualCollection visualChildren = pageContentVisual.Children; if (fskupd == PTS.FSKUPDATE.fskupdNew) { visualChildren.Clear(); visualChildren.Add(new ContainerVisual()); } // For complex subpage SectionVisual is added. So, when morphing // complex subpage to simple one, remove SectionVisual. else if (visualChildren.Count == 1 && !(visualChildren[0] is ContainerVisual)) { visualChildren.Clear(); visualChildren.Add(new ContainerVisual()); } Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is ContainerVisual); ContainerVisual trackVisual = (ContainerVisual)visualChildren[0]; PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref subpageDetails.u.simple.trackdescr); } else { // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty bool emptySubpage = (subpageDetails.u.complex.cBasicColumns == 0); if (!emptySubpage) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); emptySubpage = (arrayColumnDesc.Length == 0); if (!emptySubpage) { PTS.FSKUPDATE fskupd = fskupdInherited; ErrorHandler.Assert(fskupd != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); Debug.Assert(fskupd != PTS.FSKUPDATE.fskupdNoChange); // For complex subpage SectionVisual is added. So, when morphing // simple subpage to complex one, remove ParagraphVisual. VisualCollection visualChildren = pageContentVisual.Children; if (visualChildren.Count == 0) { visualChildren.Add(new SectionVisual()); } else if (!(visualChildren[0] is SectionVisual)) { visualChildren.Clear(); visualChildren.Add(new SectionVisual()); } Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is SectionVisual); SectionVisual sectionVisual = (SectionVisual)visualChildren[0]; // Draw column rules. ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(Paragraph.Element); sectionVisual.DrawColumnRules(ref arrayColumnDesc, TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.v), TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.dv), columnProperties); visualChildren = sectionVisual.Children; if (fskupd == PTS.FSKUPDATE.fskupdNew) { visualChildren.Clear(); for (int index = 0; index < arrayColumnDesc.Length; index++) { visualChildren.Add(new ContainerVisual()); } } ErrorHandler.Assert(visualChildren.Count == arrayColumnDesc.Length, ErrorHandler.ColumnVisualCountMismatch); for (int index = 0; index < arrayColumnDesc.Length; index++) { ContainerVisual trackVisual = (ContainerVisual)visualChildren[index]; PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref arrayColumnDesc[index]); } } } if (emptySubpage) { // There is no content, remove all existing visuals. _visual.Children.Clear(); } } pageContentVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi(); floatingElementsVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi(); PTS.FSRECT clipRect = new PTS.FSRECT(_paddingRect.u - _contentRect.u, _paddingRect.v - _contentRect.v, _paddingRect.du, _paddingRect.dv); PtsHelper.ClipChildrenToRect(_visual, clipRect.FromTextDpi()); PtsHelper.UpdateFloatingElementVisuals(floatingElementsVisual, _pageContextOfThisPage.FloatingElementList); }
internal static unsafe void GetColumnsInfo( ColumnPropertiesGroup columnProperties, double lineHeight, double pageWidth, double pageFontSize, FontFamily pageFontFamily, int cColumns, PTS.FSCOLUMNINFO* pfscolinfo, bool enableColumns) { Debug.Assert(cColumns > 0, "At least one column is required."); double columnWidth; double freeSpace; double gap; double rule = columnProperties.ColumnRuleWidth; GetColumnMetrics(columnProperties, pageWidth, pageFontSize, pageFontFamily, enableColumns, cColumns, ref lineHeight, out columnWidth, out freeSpace, out gap); // Set columns information if (!columnProperties.IsColumnWidthFlexible) { // All columns have the declared width // ColumnGap is flexible and is increased based on ColumnSpaceDistribution policy // (ColumnGap is effectively min) for (int i = 0; i < cColumns; i++) { // Today there is no way to change the default value of ColumnSpaceDistribution. // If column widths are not flexible, always allocate unused space on the right side. pfscolinfo[i].durBefore = TextDpi.ToTextDpi((i == 0) ? 0 : gap); pfscolinfo[i].durWidth = TextDpi.ToTextDpi(columnWidth); // ColumnWidth has to be > 0 and SpaceBefore has to be >= 0 pfscolinfo[i].durBefore = Math.Max(0, pfscolinfo[i].durBefore); pfscolinfo[i].durWidth = Math.Max(1, pfscolinfo[i].durWidth); } } else { // ColumnGap is honored // ColumnWidth is effectively min, and space is distributed according to ColumnSpaceDistribution policy for (int i = 0; i < cColumns; i++) { if (columnProperties.ColumnSpaceDistribution == ColumnSpaceDistribution.Right) { pfscolinfo[i].durWidth = TextDpi.ToTextDpi((i == cColumns - 1) ? columnWidth + freeSpace : columnWidth); } else if (columnProperties.ColumnSpaceDistribution == ColumnSpaceDistribution.Left) { pfscolinfo[i].durWidth = TextDpi.ToTextDpi((i == 0) ? columnWidth + freeSpace : columnWidth); } else { pfscolinfo[i].durWidth = TextDpi.ToTextDpi(columnWidth + (freeSpace / cColumns)); } // If calculated column width is greater than the page width, set it to page width to // avoid clipping if (pfscolinfo[i].durWidth > TextDpi.ToTextDpi(pageWidth)) { pfscolinfo[i].durWidth = TextDpi.ToTextDpi(pageWidth); } pfscolinfo[i].durBefore = TextDpi.ToTextDpi((i == 0) ? 0 : gap); // ColumnWidth has to be > 0 and SpaceBefore has to be >= 0 pfscolinfo[i].durBefore = Math.Max(0, pfscolinfo[i].durBefore); pfscolinfo[i].durWidth = Math.Max(1, pfscolinfo[i].durWidth); } } }
// ------------------------------------------------------------------ // GetColumnMetrics // ------------------------------------------------------------------ internal static void GetColumnMetrics(ColumnPropertiesGroup columnProperties, double pageWidth, double pageFontSize, FontFamily pageFontFamily, bool enableColumns, int cColumns, ref double lineHeight, out double columnWidth, out double freeSpace, out double gapSpace) { double rule = columnProperties.ColumnRuleWidth; if (!enableColumns) { Invariant.Assert(cColumns == 1); columnWidth = pageWidth; gapSpace = 0; lineHeight = 0; freeSpace = 0; } else { // For FlowDocument, calculate default column width if (columnProperties.ColumnWidthAuto) { columnWidth = 20 * pageFontSize; } else { columnWidth = columnProperties.ColumnWidth; } if (columnProperties.ColumnGapAuto) { gapSpace = 1 * lineHeight; } else { gapSpace = columnProperties.ColumnGap; } } columnWidth = Math.Max(1, Math.Min(columnWidth, pageWidth)); freeSpace = pageWidth - (cColumns * columnWidth) - (cColumns - 1) * gapSpace; freeSpace = Math.Max(0, freeSpace); }
// ------------------------------------------------------------------ // Calculate column count based on column properties. // If column width is Auto column count is calculated by assuming // ColumnWidth as 20*FontSize // ------------------------------------------------------------------ internal static int CalculateColumnCount( ColumnPropertiesGroup columnProperties, double lineHeight, double pageWidth, double pageFontSize, FontFamily pageFontFamily, bool enableColumns) { int columns = 1; double gap; double rule = columnProperties.ColumnRuleWidth; if (enableColumns) { if (columnProperties.ColumnGapAuto) { gap = 1 * lineHeight; } else { gap = columnProperties.ColumnGap; } if (!columnProperties.ColumnWidthAuto) { // Column count is ignored in this case double column = columnProperties.ColumnWidth; columns = (int)((pageWidth + gap) / (column + gap)); } else { // Column width is assumed to be 20*FontSize double column = 20 * pageFontSize; columns = (int)((pageWidth + gap) / (column + gap)); } } return Math.Max(1, Math.Min(PTS.Restrictions.tscColumnRestriction-1, columns)); // at least 1 column is required }
// ------------------------------------------------------------------ // Calculates a page margin adjustment to eliminate free space if column width is not flexible // ------------------------------------------------------------------ internal static double CalculatePageMarginAdjustment(StructuralCache structuralCache, double pageMarginWidth) { double pageMarginAdjustment = 0.0; DependencyObject o = structuralCache.Section.Element; if(o is FlowDocument) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(o); if(!columnProperties.IsColumnWidthFlexible) { double lineHeight = DynamicPropertyReader.GetLineHeightValue(o); double pageFontSize = (double)structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty); int ccol = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, pageMarginWidth, pageFontSize, pageFontFamily, true); double columnWidth; double freeSpace; double gap; GetColumnMetrics(columnProperties, pageMarginWidth, pageFontSize, pageFontFamily, true, ccol, ref lineHeight, out columnWidth, out freeSpace, out gap); pageMarginAdjustment = freeSpace; } } return pageMarginAdjustment; }
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); }
// ------------------------------------------------------------------ // GetSectionProperties // ------------------------------------------------------------------ /// <summary> /// Get section properties /// </summary> /// <param name="fNewPage"> /// OUT: stop page before this section? /// </param> /// <param name="fswdir"> /// OUT: direction of this section /// </param> /// <param name="fApplyColumnBalancing"> /// OUT: apply column balancing to this section? /// </param> /// <param name="ccol"> /// OUT: number of columns in the main text segment /// </param> /// <param name="cSegmentDefinedColumnSpanAreas"> /// OUT: number of segment-defined columnspan areas /// </param> /// <param name="cHeightDefinedColumnSpanAreas"> /// OUT: number of height-defined columnsapn areas /// </param> internal void GetSectionProperties( out int fNewPage, out uint fswdir, out int fApplyColumnBalancing, out int ccol, out int cSegmentDefinedColumnSpanAreas, out int cHeightDefinedColumnSpanAreas) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(Element); Size pageSize = _structuralCache.CurrentFormatContext.PageSize; double lineHeight = DynamicPropertyReader.GetLineHeightValue(Element); Thickness pageMargin = _structuralCache.CurrentFormatContext.PageMargin; double pageFontSize = (double)_structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)_structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty); bool enableColumns = _structuralCache.CurrentFormatContext.FinitePage; fNewPage = PTS.False; // Since only one section is supported, don't force page break before. fswdir = PTS.FlowDirectionToFswdir((FlowDirection)_structuralCache.PropertyOwner.GetValue(FrameworkElement.FlowDirectionProperty)); fApplyColumnBalancing = PTS.False; ccol = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, pageSize.Width - (pageMargin.Left + pageMargin.Right), pageFontSize, pageFontFamily, enableColumns); cSegmentDefinedColumnSpanAreas = 0; cHeightDefinedColumnSpanAreas = 0; }
// ------------------------------------------------------------------ // Set information about column rules that are necessary for rendering // process. Draw column rules if necessary. // // arrayColumnDesc - column description including rectangle coordinates, etc // columnVStart - vertical start coordinate of column rule // columnHeight - height of column rule // columnProperties - column properties. // ------------------------------------------------------------------ internal void DrawColumnRules(ref PTS.FSTRACKDESCRIPTION[] arrayColumnDesc, double columnVStart, double columnHeight, ColumnPropertiesGroup columnProperties) { // Compute column rules data first. Point[] rulePositions = null; double ruleWidth = columnProperties.ColumnRuleWidth; if (arrayColumnDesc.Length > 1) { if (ruleWidth > 0) { int gapWidth = (arrayColumnDesc[1].fsrc.u - (arrayColumnDesc[0].fsrc.u + arrayColumnDesc[0].fsrc.du)) / 2; rulePositions = new Point[(arrayColumnDesc.Length - 1) * 2]; for (int index = 1; index < arrayColumnDesc.Length; index++) { double u = TextDpi.FromTextDpi(arrayColumnDesc[index].fsrc.u - gapWidth); double v = columnVStart; double dv = columnHeight; rulePositions[(index - 1) * 2].X = u; rulePositions[(index - 1) * 2].Y = v; rulePositions[(index - 1) * 2 + 1].X = u; rulePositions[(index - 1) * 2 + 1].Y = v + dv; } } } // Check if update of the visual render data is needed. bool needsUpdate = _ruleWidth != ruleWidth; if (!needsUpdate && _rulePositions != rulePositions) { int prevSize = _rulePositions == null ? 0 : _rulePositions.Length; int newSize = rulePositions == null ? 0 : rulePositions.Length; if (prevSize == newSize) { for (int index = 0; index < rulePositions.Length; index++) { if (!DoubleUtil.AreClose(rulePositions[index].X, _rulePositions[index].X) || !DoubleUtil.AreClose(rulePositions[index].Y, _rulePositions[index].Y)) { needsUpdate = true; break; } } } else { needsUpdate = true; } } // Draw column rules if necessary if (needsUpdate) { _ruleWidth = ruleWidth; _rulePositions = rulePositions; // Open DrawingContext and draw background. // If background is not set, Open will clear the render data, but it // will preserve visual children. using (DrawingContext dc = RenderOpen()) { if (rulePositions != null) { // We do not want to cause the user's Brush to become frozen when we // freeze pen below, therefore we make our own copy of the Brush if // it is not already frozen. Brush columnRuleBrush = (Brush)FreezableOperations.GetAsFrozenIfPossible(columnProperties.ColumnRuleBrush); Pen pen = new Pen(columnRuleBrush, ruleWidth); // Freeze the pen if possible. Doing this avoids the overhead of // maintaining changed handlers. if (pen.CanFreeze) { pen.Freeze(); } for (int index = 0; index < rulePositions.Length; index += 2) { dc.DrawLine(pen, rulePositions[index], rulePositions[index + 1]); } } } } }
// Token: 0x06006A51 RID: 27217 RVA: 0x001E4130 File Offset: 0x001E2330 internal void DrawColumnRules(ref PTS.FSTRACKDESCRIPTION[] arrayColumnDesc, double columnVStart, double columnHeight, ColumnPropertiesGroup columnProperties) { Point[] array = null; double columnRuleWidth = columnProperties.ColumnRuleWidth; if (arrayColumnDesc.Length > 1 && columnRuleWidth > 0.0) { int num = (arrayColumnDesc[1].fsrc.u - (arrayColumnDesc[0].fsrc.u + arrayColumnDesc[0].fsrc.du)) / 2; array = new Point[(arrayColumnDesc.Length - 1) * 2]; for (int i = 1; i < arrayColumnDesc.Length; i++) { double x = TextDpi.FromTextDpi(arrayColumnDesc[i].fsrc.u - num); array[(i - 1) * 2].X = x; array[(i - 1) * 2].Y = columnVStart; array[(i - 1) * 2 + 1].X = x; array[(i - 1) * 2 + 1].Y = columnVStart + columnHeight; } } bool flag = this._ruleWidth != columnRuleWidth; if (!flag && this._rulePositions != array) { int num2 = (this._rulePositions == null) ? 0 : this._rulePositions.Length; int num3 = (array == null) ? 0 : array.Length; if (num2 == num3) { for (int j = 0; j < array.Length; j++) { if (!DoubleUtil.AreClose(array[j].X, this._rulePositions[j].X) || !DoubleUtil.AreClose(array[j].Y, this._rulePositions[j].Y)) { flag = true; break; } } } else { flag = true; } } if (flag) { this._ruleWidth = columnRuleWidth; this._rulePositions = array; using (DrawingContext drawingContext = base.RenderOpen()) { if (array != null) { Brush brush = (Brush)FreezableOperations.GetAsFrozenIfPossible(columnProperties.ColumnRuleBrush); Pen pen = new Pen(brush, columnRuleWidth); if (pen.CanFreeze) { pen.Freeze(); } for (int k = 0; k < array.Length; k += 2) { drawingContext.DrawLine(pen, array[k], array[k + 1]); } } } } }
internal unsafe void FormatParaFinite(SubpageParaClient paraClient, IntPtr pbrkrecIn, int fBRFromPreviousPage, IntPtr footnoteRejector, int fEmptyOk, int fSuppressTopSpace, uint fswdir, ref PTS.FSRECT fsrcToFill, MarginCollapsingState mcs, PTS.FSKCLEAR fskclearIn, PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn, out PTS.FSFMTR fsfmtr, out IntPtr pfspara, out IntPtr pbrkrecOut, out int dvrUsed, out PTS.FSBBOX fsbbox, out IntPtr pmcsclientOut, out PTS.FSKCLEAR fskclearOut, out int dvrTopSpace) { uint num = PTS.FlowDirectionToFswdir((FlowDirection)base.Element.GetValue(FrameworkElement.FlowDirectionProperty)); if (mcs != null && pbrkrecIn != IntPtr.Zero) { mcs = null; } PTS.FSRECT fsrect = default(PTS.FSRECT); int num2 = fsrcToFill.du; int num3 = fsrcToFill.dv; Invariant.Assert(base.Element is TableCell || base.Element is AnchoredBlock); fskclearIn = PTS.WrapDirectionToFskclear((WrapDirection)base.Element.GetValue(Block.ClearFloatersProperty)); int num4 = 0; MarginCollapsingState marginCollapsingState = null; MbpInfo mbpInfo = MbpInfo.FromElement(base.Element, base.StructuralCache.TextFormatterHost.PixelsPerDip); if (num != fswdir) { PTS.FSRECT pageRect = base.StructuralCache.CurrentFormatContext.PageRect; PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrcToFill, num, out fsrcToFill)); mbpInfo.MirrorMargin(); } num2 = Math.Max(1, num2 - (mbpInfo.MBPLeft + mbpInfo.MBPRight)); if (pbrkrecIn == IntPtr.Zero) { MarginCollapsingState.CollapseTopMargin(base.PtsContext, mbpInfo, mcs, out marginCollapsingState, out num4); if (PTS.ToBoolean(fSuppressTopSpace)) { num4 = 0; } num3 = Math.Max(1, num3 - (num4 + mbpInfo.BPTop)); if (marginCollapsingState != null) { marginCollapsingState.Dispose(); marginCollapsingState = null; } } fsrect.du = num2; fsrect.dv = num3; ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(this._element); double lineHeightValue = DynamicPropertyReader.GetLineHeightValue(this._element); double pageFontSize = (double)this._structuralCache.PropertyOwner.GetValue(TextElement.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)this._structuralCache.PropertyOwner.GetValue(TextElement.FontFamilyProperty); int num5 = PtsHelper.CalculateColumnCount(columnProperties, lineHeightValue, TextDpi.FromTextDpi(num2), pageFontSize, pageFontFamily, false); PTS.FSCOLUMNINFO[] array = new PTS.FSCOLUMNINFO[num5]; fixed(PTS.FSCOLUMNINFO *ptr = array) { PtsHelper.GetColumnsInfo(columnProperties, lineHeightValue, TextDpi.FromTextDpi(num2), pageFontSize, pageFontFamily, num5, ptr, false); } base.StructuralCache.CurrentFormatContext.PushNewPageData(new Size(TextDpi.FromTextDpi(num2), TextDpi.FromTextDpi(num3)), default(Thickness), false, true); fixed(PTS.FSCOLUMNINFO *ptr2 = array) { PTS.Validate(PTS.FsCreateSubpageFinite(base.PtsContext.Context, pbrkrecIn, fBRFromPreviousPage, this._mainTextSegment.Handle, footnoteRejector, fEmptyOk, fSuppressTopSpace, fswdir, num2, num3, ref fsrect, num5, ptr2, 0, 0, null, null, 0, null, null, PTS.FromBoolean(false), fsksuppresshardbreakbeforefirstparaIn, out fsfmtr, out pfspara, out pbrkrecOut, out dvrUsed, out fsbbox, out pmcsclientOut, out dvrTopSpace), base.PtsContext); } base.StructuralCache.CurrentFormatContext.PopPageData(); fskclearOut = PTS.FSKCLEAR.fskclearNone; if (PTS.ToBoolean(fsbbox.fDefined)) { 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) { dvrTopSpace = ((mbpInfo.BPTop != 0) ? num4 : dvrTopSpace); dvrUsed += num4 + mbpInfo.BPTop; } if (pmcsclientOut != IntPtr.Zero) { marginCollapsingState = (base.PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState); PTS.ValidateHandle(marginCollapsingState); pmcsclientOut = IntPtr.Zero; } if (fsfmtr.kstop >= PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace) { dvrUsed = (dvrTopSpace = 0); } else { if (fsfmtr.kstop == PTS.FSFMTRKSTOP.fmtrGoalReached) { MarginCollapsingState marginCollapsingState2; int num6; MarginCollapsingState.CollapseBottomMargin(base.PtsContext, mbpInfo, marginCollapsingState, out marginCollapsingState2, out num6); pmcsclientOut = ((marginCollapsingState2 != null) ? marginCollapsingState2.Handle : IntPtr.Zero); if (pmcsclientOut == IntPtr.Zero) { dvrUsed += num6 + mbpInfo.BPBottom; } } fsbbox.fsrc.u = fsrcToFill.u + mbpInfo.MarginLeft; fsbbox.fsrc.v = fsrcToFill.v + dvrTopSpace; fsbbox.fsrc.du = Math.Max(fsrcToFill.du - (mbpInfo.MarginLeft + mbpInfo.MarginRight), 0); fsbbox.fsrc.dv = Math.Max(dvrUsed - dvrTopSpace, 0); } if (num != fswdir) { PTS.FSRECT pageRect2 = base.StructuralCache.CurrentFormatContext.PageRect; PTS.Validate(PTS.FsTransformBbox(num, ref pageRect2, ref fsbbox, fswdir, out fsbbox)); } if (marginCollapsingState != null) { marginCollapsingState.Dispose(); marginCollapsingState = null; } paraClient.SetChunkInfo(pbrkrecIn == IntPtr.Zero, pbrkrecOut == IntPtr.Zero); }
internal override void ValidateVisual(PTS.FSKUPDATE fskupdInherited) { // Floater is always reported as NEW. Override PTS inherited value. fskupdInherited = PTS.FSKUPDATE.fskupdNew; // Query subpage details PTS.FSSUBPAGEDETAILS subpageDetails; PTS.Validate(PTS.FsQuerySubpageDetails(PtsContext.Context, _paraHandle.Value, out subpageDetails)); // Obtain all mbd info MbpInfo mbp = MbpInfo.FromElement(Paragraph.Element); if(ThisFlowDirection != PageFlowDirection) { mbp.MirrorBP(); } Brush backgroundBrush = (Brush)Paragraph.Element.GetValue(TextElement.BackgroundProperty); Visual.DrawBackgroundAndBorder(backgroundBrush, mbp.BorderBrush, mbp.Border, _rect.FromTextDpi(), IsFirstChunk, IsLastChunk); ContainerVisual pageContentVisual; ContainerVisual floatingElementsVisual; if(_visual.Children.Count != 2) { _visual.Children.Clear(); _visual.Children.Add(new ContainerVisual()); _visual.Children.Add(new ContainerVisual()); } pageContentVisual = (ContainerVisual)_visual.Children[0]; floatingElementsVisual = (ContainerVisual)_visual.Children[1]; // Subpage content may be simple or complex - // depending of set of features used in the content of the subpage. // (1) simple subpage (contains only one track) // (2) complex subpage (contains columns) if (PTS.ToBoolean(subpageDetails.fSimple)) { // (1) simple subpage (contains only one track) PTS.FSKUPDATE fskupd = subpageDetails.u.simple.trackdescr.fsupdinf.fskupd; if (fskupd == PTS.FSKUPDATE.fskupdInherited) { fskupd = fskupdInherited; } VisualCollection visualChildren = pageContentVisual.Children; if (fskupd == PTS.FSKUPDATE.fskupdNew) { visualChildren.Clear(); visualChildren.Add(new ContainerVisual()); } // For complex subpage SectionVisual is added. So, when morphing // complex subpage to simple one, remove SectionVisual. else if (visualChildren.Count == 1 && !(visualChildren[0] is ContainerVisual)) { visualChildren.Clear(); visualChildren.Add(new ContainerVisual()); } Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is ContainerVisual); ContainerVisual trackVisual = (ContainerVisual)visualChildren[0]; PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref subpageDetails.u.simple.trackdescr); } else { // (2) complex page (contains columns) // cBasicColumns == 0, means that subpage content is empty bool emptySubpage = (subpageDetails.u.complex.cBasicColumns == 0); if (!emptySubpage) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION[] arrayColumnDesc; PtsHelper.TrackListFromSubpage(PtsContext, _paraHandle.Value, ref subpageDetails, out arrayColumnDesc); emptySubpage = (arrayColumnDesc.Length == 0); if (!emptySubpage) { PTS.FSKUPDATE fskupd = fskupdInherited; ErrorHandler.Assert(fskupd != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); Debug.Assert(fskupd != PTS.FSKUPDATE.fskupdNoChange); // For complex subpage SectionVisual is added. So, when morphing // simple subpage to complex one, remove ParagraphVisual. VisualCollection visualChildren = pageContentVisual.Children; if (visualChildren.Count == 0) { visualChildren.Add(new SectionVisual()); } else if (!(visualChildren[0] is SectionVisual)) { visualChildren.Clear(); visualChildren.Add(new SectionVisual()); } Debug.Assert(visualChildren.Count == 1 && visualChildren[0] is SectionVisual); SectionVisual sectionVisual = (SectionVisual)visualChildren[0]; // Draw column rules. ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(Paragraph.Element); sectionVisual.DrawColumnRules(ref arrayColumnDesc, TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.v), TextDpi.FromTextDpi(subpageDetails.u.complex.fsrc.dv), columnProperties); visualChildren = sectionVisual.Children; if (fskupd == PTS.FSKUPDATE.fskupdNew) { visualChildren.Clear(); for (int index = 0; index < arrayColumnDesc.Length; index++) { visualChildren.Add(new ContainerVisual()); } } ErrorHandler.Assert(visualChildren.Count == arrayColumnDesc.Length, ErrorHandler.ColumnVisualCountMismatch); for (int index = 0; index < arrayColumnDesc.Length; index++) { ContainerVisual trackVisual = (ContainerVisual)visualChildren[index]; PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupdInherited, ref arrayColumnDesc[index]); } } } if (emptySubpage) { // There is no content, remove all existing visuals. _visual.Children.Clear(); } } pageContentVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi(); floatingElementsVisual.Offset = new PTS.FSVECTOR(ContentRect.u, ContentRect.v).FromTextDpi(); PTS.FSRECT clipRect = new PTS.FSRECT(_paddingRect.u - _contentRect.u, _paddingRect.v - _contentRect.v, _paddingRect.du, _paddingRect.dv); PtsHelper.ClipChildrenToRect(_visual, clipRect.FromTextDpi()); PtsHelper.UpdateFloatingElementVisuals(floatingElementsVisual, _pageContextOfThisPage.FloatingElementList); }
internal override void ValidateVisual(PTS.FSKUPDATE fskupdInherited) { PTS.FSSUBPAGEDETAILS fssubpagedetails; PTS.Validate(PTS.FsQuerySubpageDetails(base.PtsContext.Context, this._paraHandle.Value, out fssubpagedetails)); MbpInfo mbpInfo = MbpInfo.FromElement(base.Paragraph.Element, base.Paragraph.StructuralCache.TextFormatterHost.PixelsPerDip); if (base.ThisFlowDirection != base.PageFlowDirection) { mbpInfo.MirrorBP(); } Brush backgroundBrush = (Brush)base.Paragraph.Element.GetValue(TextElement.BackgroundProperty); this.Visual.DrawBackgroundAndBorder(backgroundBrush, mbpInfo.BorderBrush, mbpInfo.Border, this._rect.FromTextDpi(), this.IsFirstChunk, this.IsLastChunk); if (this._visual.Children.Count != 2) { this._visual.Children.Clear(); this._visual.Children.Add(new ContainerVisual()); this._visual.Children.Add(new ContainerVisual()); } ContainerVisual containerVisual = (ContainerVisual)this._visual.Children[0]; ContainerVisual containerVisual2 = (ContainerVisual)this._visual.Children[1]; if (PTS.ToBoolean(fssubpagedetails.fSimple)) { PTS.FSKUPDATE fskupdate = fssubpagedetails.u.simple.trackdescr.fsupdinf.fskupd; if (fskupdate == PTS.FSKUPDATE.fskupdInherited) { fskupdate = fskupdInherited; } VisualCollection children = containerVisual.Children; if (fskupdate == PTS.FSKUPDATE.fskupdNew) { children.Clear(); children.Add(new ContainerVisual()); } else if (children.Count == 1 && children[0] is SectionVisual) { children.Clear(); children.Add(new ContainerVisual()); } ContainerVisual containerVisual3 = (ContainerVisual)children[0]; PtsHelper.UpdateTrackVisuals(base.PtsContext, containerVisual3.Children, fskupdInherited, ref fssubpagedetails.u.simple.trackdescr); } else { bool flag = fssubpagedetails.u.complex.cBasicColumns == 0; if (!flag) { PTS.FSTRACKDESCRIPTION[] array; PtsHelper.TrackListFromSubpage(base.PtsContext, this._paraHandle.Value, ref fssubpagedetails, out array); flag = (array.Length == 0); if (!flag) { ErrorHandler.Assert(fskupdInherited != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); VisualCollection children2 = containerVisual.Children; if (children2.Count == 0) { children2.Add(new SectionVisual()); } else if (!(children2[0] is SectionVisual)) { children2.Clear(); children2.Add(new SectionVisual()); } SectionVisual sectionVisual = (SectionVisual)children2[0]; ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(base.Paragraph.Element); sectionVisual.DrawColumnRules(ref array, TextDpi.FromTextDpi(fssubpagedetails.u.complex.fsrc.v), TextDpi.FromTextDpi(fssubpagedetails.u.complex.fsrc.dv), columnProperties); children2 = sectionVisual.Children; if (fskupdInherited == PTS.FSKUPDATE.fskupdNew) { children2.Clear(); for (int i = 0; i < array.Length; i++) { children2.Add(new ContainerVisual()); } } ErrorHandler.Assert(children2.Count == array.Length, ErrorHandler.ColumnVisualCountMismatch); for (int j = 0; j < array.Length; j++) { ContainerVisual containerVisual4 = (ContainerVisual)children2[j]; PtsHelper.UpdateTrackVisuals(base.PtsContext, containerVisual4.Children, fskupdInherited, ref array[j]); } } } if (flag) { this._visual.Children.Clear(); } } containerVisual.Offset = new PTS.FSVECTOR(this.ContentRect.u, this.ContentRect.v).FromTextDpi(); containerVisual2.Offset = new PTS.FSVECTOR(this.ContentRect.u, this.ContentRect.v).FromTextDpi(); PTS.FSRECT fsrect = new PTS.FSRECT(this._paddingRect.u - this._contentRect.u, this._paddingRect.v - this._contentRect.v, this._paddingRect.du, this._paddingRect.dv); PtsHelper.ClipChildrenToRect(this._visual, fsrect.FromTextDpi()); PtsHelper.UpdateFloatingElementVisuals(containerVisual2, this._pageContextOfThisPage.FloatingElementList); }
internal unsafe void GetSectionColumnInfo( uint fswdir, int ncol, PTS.FSCOLUMNINFO* pfscolinfo, out int ccol) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(Element); Size pageSize = _structuralCache.CurrentFormatContext.PageSize; double lineHeight = DynamicPropertyReader.GetLineHeightValue(Element); Thickness pageMargin = _structuralCache.CurrentFormatContext.PageMargin; double pageFontSize = (double)_structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)_structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty); bool enableColumns = _structuralCache.CurrentFormatContext.FinitePage; ccol = ncol; PtsHelper.GetColumnsInfo(columnProperties, lineHeight, pageSize.Width - (pageMargin.Left + pageMargin.Right), pageFontSize, pageFontFamily, ncol, pfscolinfo, enableColumns); }
// ------------------------------------------------------------------ // Set information about column rules that are necessary for rendering // process. Draw column rules if necessary. // // arrayColumnDesc - column description including rectangle coordinates, etc // columnVStart - vertical start coordinate of column rule // columnHeight - height of column rule // columnProperties - column properties. // ------------------------------------------------------------------ internal void DrawColumnRules(ref PTS.FSTRACKDESCRIPTION[] arrayColumnDesc, double columnVStart, double columnHeight, ColumnPropertiesGroup columnProperties) { // Compute column rules data first. Point[] rulePositions = null; double ruleWidth = columnProperties.ColumnRuleWidth; if (arrayColumnDesc.Length > 1) { if (ruleWidth > 0) { int gapWidth = (arrayColumnDesc[1].fsrc.u - (arrayColumnDesc[0].fsrc.u + arrayColumnDesc[0].fsrc.du)) / 2; rulePositions = new Point[(arrayColumnDesc.Length - 1)*2]; for (int index = 1; index < arrayColumnDesc.Length; index++) { double u = TextDpi.FromTextDpi(arrayColumnDesc[index].fsrc.u - gapWidth); double v = columnVStart; double dv = columnHeight; rulePositions[(index-1)*2].X = u; rulePositions[(index-1)*2].Y = v; rulePositions[(index-1)*2+1].X = u; rulePositions[(index-1)*2+1].Y = v + dv; } } } // Check if update of the visual render data is needed. bool needsUpdate = _ruleWidth != ruleWidth; if (!needsUpdate && _rulePositions != rulePositions) { int prevSize = _rulePositions == null ? 0 : _rulePositions.Length; int newSize = rulePositions == null ? 0 : rulePositions.Length; if (prevSize == newSize) { for (int index = 0; index < rulePositions.Length; index++) { if (!DoubleUtil.AreClose(rulePositions[index].X, _rulePositions[index].X) || !DoubleUtil.AreClose(rulePositions[index].Y, _rulePositions[index].Y)) { needsUpdate = true; break; } } } else { needsUpdate = true; } } // Draw column rules if necessary if (needsUpdate) { _ruleWidth = ruleWidth; _rulePositions = rulePositions; // Open DrawingContext and draw background. // If background is not set, Open will clear the render data, but it // will preserve visual children. using (DrawingContext dc = RenderOpen()) { if (rulePositions != null) { // We do not want to cause the user's Brush to become frozen when we // freeze pen below, therefore we make our own copy of the Brush if // it is not already frozen. Brush columnRuleBrush = (Brush)FreezableOperations.GetAsFrozenIfPossible(columnProperties.ColumnRuleBrush); Pen pen = new Pen(columnRuleBrush, ruleWidth); // Freeze the pen if possible. Doing this avoids the overhead of // maintaining changed handlers. if (pen.CanFreeze) { pen.Freeze(); } for (int index = 0; index < rulePositions.Length; index += 2) { dc.DrawLine(pen, rulePositions[index], rulePositions[index + 1]); } } } } }
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); }
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); }
// ------------------------------------------------------------------ // Returns calculated column information - count, width, gap and rule. // ------------------------------------------------------------------ internal static void GetColumnMetrics(StructuralCache structuralCache, out int cColumns, out double width, out double gap, out double rule) { ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(structuralCache.PropertyOwner); FontFamily pageFontFamily = (FontFamily)structuralCache.PropertyOwner.GetValue(Block.FontFamilyProperty); double lineHeight = DynamicPropertyReader.GetLineHeightValue(structuralCache.PropertyOwner); double pageFontSize = (double)structuralCache.PropertyOwner.GetValue(Block.FontSizeProperty); Size pageSize = structuralCache.CurrentFormatContext.PageSize; Thickness pageMargin = structuralCache.CurrentFormatContext.PageMargin; double pageWidth = pageSize.Width - (pageMargin.Left + pageMargin.Right); cColumns = PtsHelper.CalculateColumnCount(columnProperties, lineHeight, pageWidth, pageFontSize, pageFontFamily, true); double freeSpace; rule = columnProperties.ColumnRuleWidth; PtsHelper.GetColumnMetrics(columnProperties, pageWidth, pageFontSize, pageFontFamily, true, cColumns, ref lineHeight, out width, out freeSpace, out gap); if (columnProperties.IsColumnWidthFlexible && columnProperties.ColumnSpaceDistribution == ColumnSpaceDistribution.Between) { width += freeSpace / cColumns; } width = Math.Min(width, pageWidth); }
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); }
private void UpdateSectionVisuals( SectionVisual visual, PTS.FSKUPDATE fskupdInherited, ref PTS.FSSECTIONDESCRIPTION sectionDesc) { PTS.FSKUPDATE fskupd = sectionDesc.fsupdinf.fskupd; if (fskupd == PTS.FSKUPDATE.fskupdInherited) { fskupd = fskupdInherited; } ErrorHandler.Assert(fskupd != PTS.FSKUPDATE.fskupdShifted, ErrorHandler.UpdateShiftedNotValid); // If there is no change, visual information is valid if (fskupd == PTS.FSKUPDATE.fskupdNoChange) { return; } bool emptySection; // Get section details PTS.FSSECTIONDETAILS sectionDetails; PTS.Validate(PTS.FsQuerySectionDetails(PtsContext.Context, sectionDesc.pfssection, out sectionDetails)); // There are 2 types of sections: // (1) with page notes - footnotes in section treated as endnotes // (2) with column notes - footnotes in section treated as column notes if (PTS.ToBoolean(sectionDetails.fFootnotesAsPagenotes)) { // (1) with page notes - footnotes in section treated as endnotes ErrorHandler.Assert(sectionDetails.u.withpagenotes.cEndnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // Debug.Assert(sectionDetails.u.withpagenotes.cSegmentDefinedColumnSpanAreas == 0); Debug.Assert(sectionDetails.u.withpagenotes.cHeightDefinedColumnSpanAreas == 0); // cBasicColumns == 0, means that section content is empty. emptySection = (sectionDetails.u.withpagenotes.cBasicColumns == 0); if (!emptySection) { // Retrieve description for each column. PTS.FSTRACKDESCRIPTION [] arrayColumnDesc; PtsHelper.TrackListFromSection(PtsContext, sectionDesc.pfssection, ref sectionDetails, out arrayColumnDesc); emptySection = (arrayColumnDesc.Length == 0); if (!emptySection) { // Draw column rules. ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(_section.Element); visual.DrawColumnRules(ref arrayColumnDesc, TextDpi.FromTextDpi(sectionDesc.fsrc.v), TextDpi.FromTextDpi(sectionDesc.fsrc.dv), columnProperties); VisualCollection visualChildren = visual.Children; if (fskupd == PTS.FSKUPDATE.fskupdNew) { visualChildren.Clear(); for (int index = 0; index < arrayColumnDesc.Length; index++) { visualChildren.Add(new ContainerVisual()); } } ErrorHandler.Assert(visualChildren.Count == arrayColumnDesc.Length, ErrorHandler.ColumnVisualCountMismatch); for (int index = 0; index < arrayColumnDesc.Length; index++) { ContainerVisual trackVisual = (ContainerVisual)visualChildren[index]; PtsHelper.UpdateTrackVisuals(PtsContext, trackVisual.Children, fskupd, ref arrayColumnDesc[index]); } } } } else { // (2) with column notes - footnotes in section treated as column notes ErrorHandler.Assert(false, ErrorHandler.NotSupportedCompositeColumns); emptySection = true; } if (emptySection) { // There is no content, remove all existing visuals. visual.Children.Clear(); } }
internal unsafe void UpdateBottomlessPara(IntPtr pfspara, SubpageParaClient paraClient, int fSuppressTopSpace, uint fswdir, int urTrack, int durTrack, int vrTrack, MarginCollapsingState mcs, PTS.FSKCLEAR fskclearIn, int fInterruptable, out PTS.FSFMTRBL fsfmtrbl, out int dvrUsed, out PTS.FSBBOX fsbbox, out IntPtr pmcsclientOut, out PTS.FSKCLEAR fskclearOut, out int dvrTopSpace, out int fPageBecomesUninterruptable) { uint num = PTS.FlowDirectionToFswdir((FlowDirection)base.Element.GetValue(FrameworkElement.FlowDirectionProperty)); int num2 = durTrack; int urMargin; int vrMargin = urMargin = 0; Invariant.Assert(base.Element is TableCell || base.Element is AnchoredBlock); fskclearIn = PTS.WrapDirectionToFskclear((WrapDirection)base.Element.GetValue(Block.ClearFloatersProperty)); MbpInfo mbpInfo = MbpInfo.FromElement(base.Element, base.StructuralCache.TextFormatterHost.PixelsPerDip); if (num != fswdir) { PTS.FSRECT fsrect = new PTS.FSRECT(urTrack, 0, durTrack, 0); PTS.FSRECT pageRect = base.StructuralCache.CurrentFormatContext.PageRect; PTS.Validate(PTS.FsTransformRectangle(fswdir, ref pageRect, ref fsrect, num, out fsrect)); urTrack = fsrect.u; durTrack = fsrect.du; mbpInfo.MirrorMargin(); } num2 = Math.Max(1, num2 - (mbpInfo.MBPLeft + mbpInfo.MBPRight)); MarginCollapsingState marginCollapsingState; int num3; MarginCollapsingState.CollapseTopMargin(base.PtsContext, mbpInfo, mcs, out marginCollapsingState, out num3); if (marginCollapsingState != null) { marginCollapsingState.Dispose(); marginCollapsingState = null; } int durMargin = num2; ColumnPropertiesGroup columnProperties = new ColumnPropertiesGroup(this._element); double lineHeightValue = DynamicPropertyReader.GetLineHeightValue(this._element); double pageFontSize = (double)this._structuralCache.PropertyOwner.GetValue(TextElement.FontSizeProperty); FontFamily pageFontFamily = (FontFamily)this._structuralCache.PropertyOwner.GetValue(TextElement.FontFamilyProperty); int num4 = PtsHelper.CalculateColumnCount(columnProperties, lineHeightValue, TextDpi.FromTextDpi(num2), pageFontSize, pageFontFamily, false); PTS.FSCOLUMNINFO[] array = new PTS.FSCOLUMNINFO[num4]; fixed(PTS.FSCOLUMNINFO *ptr = array) { PtsHelper.GetColumnsInfo(columnProperties, lineHeightValue, TextDpi.FromTextDpi(num2), pageFontSize, pageFontFamily, num4, ptr, false); } base.StructuralCache.CurrentFormatContext.PushNewPageData(new Size(TextDpi.FromTextDpi(num2), TextDpi.MaxWidth), default(Thickness), true, false); fixed(PTS.FSCOLUMNINFO *ptr2 = array) { PTS.Validate(PTS.FsUpdateBottomlessSubpage(base.PtsContext.Context, pfspara, this._mainTextSegment.Handle, fSuppressTopSpace, fswdir, num2, urMargin, durMargin, vrMargin, num4, ptr2, 0, null, null, 0, null, null, PTS.FromBoolean(true), out fsfmtrbl, out dvrUsed, out fsbbox, out pmcsclientOut, out dvrTopSpace, out fPageBecomesUninterruptable), base.PtsContext); } base.StructuralCache.CurrentFormatContext.PopPageData(); fskclearOut = PTS.FSKCLEAR.fskclearNone; if (fsfmtrbl != PTS.FSFMTRBL.fmtrblCollision) { if (pmcsclientOut != IntPtr.Zero) { marginCollapsingState = (base.PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState); PTS.ValidateHandle(marginCollapsingState); pmcsclientOut = IntPtr.Zero; } MarginCollapsingState marginCollapsingState2; int num5; MarginCollapsingState.CollapseBottomMargin(base.PtsContext, mbpInfo, marginCollapsingState, out marginCollapsingState2, out num5); pmcsclientOut = ((marginCollapsingState2 != null) ? marginCollapsingState2.Handle : IntPtr.Zero); if (marginCollapsingState != null) { marginCollapsingState.Dispose(); marginCollapsingState = null; } if (PTS.ToBoolean(fsbbox.fDefined)) { dvrUsed = Math.Max(dvrUsed, fsbbox.fsrc.dv + fsbbox.fsrc.v); durTrack = Math.Max(durTrack, fsbbox.fsrc.du + fsbbox.fsrc.u); } dvrTopSpace = ((mbpInfo.BPTop != 0) ? num3 : dvrTopSpace); dvrUsed += num3 + mbpInfo.BPTop + (num5 + mbpInfo.BPBottom); fsbbox.fsrc.u = urTrack + mbpInfo.MarginLeft; fsbbox.fsrc.v = vrTrack + dvrTopSpace; fsbbox.fsrc.du = Math.Max(durTrack - (mbpInfo.MarginLeft + mbpInfo.MarginRight), 0); fsbbox.fsrc.dv = Math.Max(dvrUsed - dvrTopSpace, 0); } else { pfspara = IntPtr.Zero; dvrUsed = (dvrTopSpace = 0); } if (num != fswdir) { PTS.FSRECT pageRect2 = base.StructuralCache.CurrentFormatContext.PageRect; PTS.Validate(PTS.FsTransformBbox(num, ref pageRect2, ref fsbbox, fswdir, out fsbbox)); } paraClient.SetChunkInfo(true, true); }