internal int SubpageShiftVertical( IntPtr pfspara, // IN: pointer to the para data IntPtr pfsparaclient, // IN: IntPtr pfsshift, // IN: pointer to the shift data uint fswdir, // IN: wdir for bbox - the same as the one passed to formatting method out PTS.FSBBOX pfsbbox) // OUT: output BBox { Debug.Assert(false); pfsbbox = new PTS.FSBBOX(); return PTS.fserrNone; }
private PTS.FSBBOX GetBoundingBox() { PTS.FSBBOX bbox = new PTS.FSBBOX(); // There are 3 cases when calculating bounding box: // (1) PTS page is not created - return empty rect. // (2) PTS page - use page PTS APIs to get bounding box. // (3) PTS subpage - use subpage PTS APIs to get bounding box. if (IsEmpty) { // (1) PTS page is not created - bbox is not defined } else { // (2) PTS page - use page PTS APIs to get bounding box. PTS.FSPAGEDETAILS pageDetails; PTS.Validate(PTS.FsQueryPageDetails(PtsContext.Context, _ptsPage.Value, out pageDetails)); // There are 2 different types of PTS page and bounding box calculation depends on it: // (a) simple page (contains only one track) - get bounding box from the track. // (b) complex page (contains header, page body, footnotes and footer) - get bounding // box of each segment and union them. if (PTS.ToBoolean(pageDetails.fSimple)) { // (a) simple page (contains only one track) - get bounding box from the track. bbox = pageDetails.u.simple.trackdescr.fsbbox; } else { // (b) complex page (contains header, page body, footnotes and footer) - get bounding // box of each segment and union them. //ErrorHandler.Assert(!PTS.ToBoolean(pageDetails.u.complex.fTopBottomHeaderFooter), ErrorHandler.NotSupportedHeadersFooters); //ErrorHandler.Assert(!PTS.ToBoolean(pageDetails.u.complex.fJustified), ErrorHandler.NotSupportedVerticalJustify); ErrorHandler.Assert(pageDetails.u.complex.cFootnoteColumns == 0, ErrorHandler.NotSupportedFootnotes); // Since header/footer and footnotes are not supported yet, use page body bounding box bbox = pageDetails.u.complex.fsbboxPageBody; } } return bbox; }
internal int SubpageFormatParaFinite( IntPtr pfssobjc, // IN: object context IntPtr pfsparaclient, // IN: IntPtr pfsobjbrk, // IN: break record---use if !NULL int fBreakRecordFromPreviousPage, // IN: break record was created on previous page IntPtr nmp, // IN: name of paragraph---use if break record is NULL int iArea, // IN: column-span area index IntPtr pftnrej, // IN: IntPtr pfsgeom, // 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 IntPtr pmcsclientIn, // IN: input margin collapsing state PTS.FSKCLEAR fskclearIn, // IN: clear property that must be satisfied PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn, int fBreakInside, // IN: produce vertical break inside para; needed for recursive KWN logic; out PTS.FSFMTR fsfmtr, // OUT: result of formatting the paragraph out IntPtr pfspara, // OUT: pointer to the para data out IntPtr pbrkrecpara, // 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 out int fBreakInsidePossible) // OUT: internal vertical break possible, needed for recursive KWN logic { int fserr = PTS.fserrNone; fBreakInsidePossible = PTS.False; try { SubpageParagraph para = PtsContext.HandleToObject(nmp) as SubpageParagraph; PTS.ValidateHandle(para); SubpageParaClient paraClient = PtsContext.HandleToObject(pfsparaclient) as SubpageParaClient; PTS.ValidateHandle(paraClient); MarginCollapsingState mcs = null; if (pmcsclientIn != IntPtr.Zero) { mcs = PtsContext.HandleToObject(pmcsclientIn) as MarginCollapsingState; PTS.ValidateHandle(mcs); } para.FormatParaFinite(paraClient, pfsobjbrk, fBreakRecordFromPreviousPage, pftnrej, fEmptyOk, fSuppressTopSpace, fswdir, ref fsrcToFill, mcs, fskclearIn, fsksuppresshardbreakbeforefirstparaIn, out fsfmtr, out pfspara, out pbrkrecpara, out dvrUsed, out fsbbox, out pmcsclientOut, out fskclearOut, out dvrTopSpace); } catch (Exception e) { fsfmtr = new PTS.FSFMTR(); pfspara = pbrkrecpara = pmcsclientOut = IntPtr.Zero; dvrUsed = dvrTopSpace = 0; fsbbox = new PTS.FSBBOX(); fskclearOut = default(PTS.FSKCLEAR); PtsContext.CallbackException = e; fserr = PTS.fserrCallbackException; } catch { fsfmtr = new PTS.FSFMTR(); pfspara = pbrkrecpara = pmcsclientOut = IntPtr.Zero; dvrUsed = dvrTopSpace = 0; fsbbox = new PTS.FSBBOX(); fskclearOut = default(PTS.FSKCLEAR); PtsContext.CallbackException = new System.Exception("Caught a non CLS Exception"); fserr = PTS.fserrCallbackException; } return fserr; }
internal int SubpageUpdateBottomlessPara( IntPtr pfspara, // IN: pointer to the para data IntPtr pfsparaclient, // IN: IntPtr nmp, // IN: name of paragraph 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 IntPtr pmcsclientIn, // 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 fserr = PTS.fserrNone; try { SubpageParagraph para = PtsContext.HandleToObject(nmp) as SubpageParagraph; PTS.ValidateHandle(para); SubpageParaClient paraClient = PtsContext.HandleToObject(pfsparaclient) as SubpageParaClient; PTS.ValidateHandle(paraClient); MarginCollapsingState mcs = null; if (pmcsclientIn != IntPtr.Zero) { mcs = PtsContext.HandleToObject(pmcsclientIn) as MarginCollapsingState; PTS.ValidateHandle(mcs); } para.UpdateBottomlessPara(pfspara, paraClient, fSuppressTopSpace, fswdir, urTrack, durTrack, vrTrack, mcs, fskclearIn, fInterruptable, out fsfmtrbl, out dvrUsed, out fsbbox, out pmcsclientOut, out fskclearOut, out dvrTopSpace, out fPageBecomesUninterruptable); } catch (Exception e) { fsfmtrbl = default(PTS.FSFMTRBL); pfspara = pmcsclientOut = IntPtr.Zero; dvrUsed = dvrTopSpace = fPageBecomesUninterruptable = 0; fsbbox = new PTS.FSBBOX(); fskclearOut = default(PTS.FSKCLEAR); PtsContext.CallbackException = e; fserr = PTS.fserrCallbackException; } catch { fsfmtrbl = default(PTS.FSFMTRBL); pfspara = pmcsclientOut = IntPtr.Zero; dvrUsed = dvrTopSpace = fPageBecomesUninterruptable = 0; fsbbox = new PTS.FSBBOX(); fskclearOut = default(PTS.FSKCLEAR); PtsContext.CallbackException = new System.Exception("Caught a non CLS Exception"); fserr = PTS.fserrCallbackException; } return fserr; }
internal int CalcFigurePosition( IntPtr pfsclient, // IN: client opaque data IntPtr pfsparaclientFigure, // IN: IntPtr nmpFigure, // IN: figure's name uint fswdir, // IN: current direction ref PTS.FSRECT fsrcPage, // IN: page rectangle ref PTS.FSRECT fsrcMargin, // IN: rectangle within page margins ref PTS.FSRECT fsrcTrack, // IN: track rectangle ref PTS.FSRECT fsrcFigurePreliminary,// IN: prelim figure rect calculated from figure props int fMustPosition, // IN: must find position in this track? int fInTextLine, // IN: it is attached to text line out int fPushToNextTrack, // OUT: push to next track? out PTS.FSRECT fsrcFlow, // OUT: FlowAround rectangle out PTS.FSRECT fsrcOverlap, // OUT: Overlap rectangle out PTS.FSBBOX fsbbox, // OUT: bbox out PTS.FSRECT fsrcSearch) // OUT: search area for overlap { int fserr = PTS.fserrNone; try { FigureParagraph para = PtsContext.HandleToObject(nmpFigure) as FigureParagraph; PTS.ValidateHandle(para); FigureParaClient paraClient = PtsContext.HandleToObject(pfsparaclientFigure) as FigureParaClient; PTS.ValidateHandle(paraClient); para.CalcFigurePosition(paraClient, fswdir, ref fsrcPage, ref fsrcMargin, ref fsrcTrack, ref fsrcFigurePreliminary, fMustPosition, fInTextLine, out fPushToNextTrack, out fsrcFlow, out fsrcOverlap, out fsbbox, out fsrcSearch); } catch (Exception e) { fPushToNextTrack = 0; fsrcFlow = fsrcOverlap = fsrcSearch = new PTS.FSRECT(); fsbbox = new PTS.FSBBOX(); PtsContext.CallbackException = e; fserr = PTS.fserrCallbackException; } catch { fPushToNextTrack = 0; fsrcFlow = fsrcOverlap = fsrcSearch = new PTS.FSRECT(); fsbbox = new PTS.FSBBOX(); PtsContext.CallbackException = new System.Exception("Caught a non CLS Exception"); fserr = PTS.fserrCallbackException; } return fserr; }
internal int UpdateBottomlessFloaterContent( IntPtr pfsFloaterContent, // IN: opaque for PTS pointer to floater content IntPtr pfsparaclient, // IN: IntPtr nmFloater, // IN: name of floater int fSuppressTopSpace, // IN: suppress empty space at the top of the page uint fswdirTrack, // 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 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 { int fserr = PTS.fserrNone; try { FloaterBaseParagraph para = PtsContext.HandleToObject(nmFloater) as FloaterBaseParagraph; PTS.ValidateHandle(para); FloaterBaseParaClient paraClient = PtsContext.HandleToObject(pfsparaclient) as FloaterBaseParaClient; PTS.ValidateHandle(paraClient); para.UpdateBottomlessFloaterContent(paraClient, fSuppressTopSpace, fswdirTrack, fAtMaxWidth, durAvailable, dvrAvailable, pfsFloaterContent, out fsfmtrbl, out durFloaterWidth, out dvrFloaterHeight, out fsbbox, out cPolygons, out cVertices); } catch (Exception e) { fsfmtrbl = default(PTS.FSFMTRBL); durFloaterWidth = dvrFloaterHeight = cPolygons = cVertices = 0; fsbbox = new PTS.FSBBOX(); PtsContext.CallbackException = e; fserr = PTS.fserrCallbackException; } catch { fsfmtrbl = default(PTS.FSFMTRBL); durFloaterWidth = dvrFloaterHeight = cPolygons = cVertices = 0; fsbbox = new PTS.FSBBOX(); PtsContext.CallbackException = new System.Exception("Caught a non CLS Exception"); fserr = PTS.fserrCallbackException; } return fserr; }
//------------------------------------------------------------------- // CalcFigurePosition //------------------------------------------------------------------- internal void CalcFigurePosition( FigureParaClient paraClient, // IN: uint fswdir, // IN: current direction ref PTS.FSRECT fsrcPage, // IN: page rectangle ref PTS.FSRECT fsrcMargin, // IN: rectangle within page margins ref PTS.FSRECT fsrcTrack, // IN: track rectangle ref PTS.FSRECT fsrcFigurePreliminary,// IN: prelim figure rect calculated from figure props int fMustPosition, // IN: must find position in this track? int fInTextLine, // IN: it is attached to text line out int fPushToNextTrack, // OUT: push to next track? out PTS.FSRECT fsrcFlow, // OUT: FlowAround rectangle out PTS.FSRECT fsrcOverlap, // OUT: Overlap rectangle out PTS.FSBBOX fsbbox, // OUT: bbox out PTS.FSRECT fsrcSearch) // OUT: search area for overlap { Figure element = (Figure)Element; // If overlapping happens, let PTS find another position withing // the track rectangle. FigureHorizontalAnchor horizAnchor = element.HorizontalAnchor; FigureVerticalAnchor vertAnchor = element.VerticalAnchor; fsrcSearch = CalculateSearchArea(horizAnchor, vertAnchor, ref fsrcPage, ref fsrcMargin, ref fsrcTrack, ref fsrcFigurePreliminary); if(vertAnchor == FigureVerticalAnchor.ParagraphTop && fsrcFigurePreliminary.v != fsrcMargin.v && // If we're not at the top of the column ( (fsrcFigurePreliminary.v + fsrcFigurePreliminary.dv) > (fsrcTrack.v + fsrcTrack.dv) ) && // And we exceed column height !PTS.ToBoolean(fMustPosition)) // Can delay placement is handled by figure properties. { fPushToNextTrack = PTS.True; } else { fPushToNextTrack = PTS.False; } // Use rectangle proposed by PTS and make sure that figure fits completely in the page. fsrcFlow = fsrcFigurePreliminary; if(FigureHelper.IsHorizontalColumnAnchor(horizAnchor)) { fsrcFlow.u += CalculateParagraphToColumnOffset(horizAnchor, fsrcFigurePreliminary); } // Apply horizontal and vertical offsets. Offsets are limited by page height and width fsrcFlow.u += TextDpi.ToTextDpi(element.HorizontalOffset); fsrcFlow.v += TextDpi.ToTextDpi(element.VerticalOffset); // Overlap rectangle is the same as flow around rect fsrcOverlap = fsrcFlow; /* If we're anchored to column/content left or right, inflate our overlap width to prevent from aligning two figures right next to one another by incorporating column gap information */ if(!FigureHelper.IsHorizontalPageAnchor(horizAnchor) && horizAnchor != FigureHorizontalAnchor.ColumnCenter && horizAnchor != FigureHorizontalAnchor.ContentCenter) { double columnWidth, gap, rule; int cColumns; FigureHelper.GetColumnMetrics(StructuralCache, out cColumns, out columnWidth, out gap, out rule); int duColumnWidth = TextDpi.ToTextDpi(columnWidth); int duGapWidth = TextDpi.ToTextDpi(gap); int duColumnWidthWithGap = duColumnWidth + duGapWidth; int fullColumns = (fsrcOverlap.du / duColumnWidthWithGap); int duRoundedToNearestColumn = ((fullColumns + 1) * duColumnWidthWithGap) - duGapWidth; fsrcOverlap.du = duRoundedToNearestColumn; // Round overlap rect to nearest column if(horizAnchor == FigureHorizontalAnchor.ContentRight || horizAnchor == FigureHorizontalAnchor.ColumnRight) { fsrcOverlap.u = (fsrcFlow.u + fsrcFlow.du + duGapWidth) - fsrcOverlap.du; } // Force search rect to only work vertically within overlap space. fsrcSearch.u = fsrcOverlap.u; fsrcSearch.du = fsrcOverlap.du; } // Bounding box is equal to actual size of the figure. fsbbox = new PTS.FSBBOX(); fsbbox.fDefined = PTS.True; fsbbox.fsrc = fsrcFlow; }
internal int FormatFloaterContentFinite( IntPtr pfsclient, // IN: client opaque data IntPtr pfsparaclient, // IN: IntPtr pfsbrkFloaterContentIn, // IN: break record---use if !NULL int fBreakRecordFromPreviousPage, // IN: break record was created on previous page IntPtr nmFloater, // IN: name of floater IntPtr pftnrej, // IN: int fEmptyOk, // IN: is it OK not to add anything? int fSuppressTopSpace, // IN: suppress empty space at the top of the page uint fswdirTrack, // 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, out PTS.FSFMTR fsfmtr, // OUT: result of formatting out IntPtr pfsFloatContent, // OUT: opaque for PTS pointer pointer to formatted content out IntPtr pbrkrecpara, // 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 { int fserr = PTS.fserrNone; try { FloaterBaseParagraph para = PtsContext.HandleToObject(nmFloater) as FloaterBaseParagraph; PTS.ValidateHandle(para); FloaterBaseParaClient paraClient = PtsContext.HandleToObject(pfsparaclient) as FloaterBaseParaClient; PTS.ValidateHandle(paraClient); para.FormatFloaterContentFinite(paraClient, pfsbrkFloaterContentIn, fBreakRecordFromPreviousPage, pftnrej, fEmptyOk, fSuppressTopSpace, fswdirTrack, fAtMaxWidth, durAvailable, dvrAvailable, fsksuppresshardbreakbeforefirstparaIn, out fsfmtr, out pfsFloatContent, out pbrkrecpara, out durFloaterWidth, out dvrFloaterHeight, out fsbbox, out cPolygons, out cVertices); } catch (Exception e) { fsfmtr = new PTS.FSFMTR(); pfsFloatContent = pbrkrecpara = IntPtr.Zero; durFloaterWidth = dvrFloaterHeight = cPolygons = cVertices = 0; fsbbox = new PTS.FSBBOX(); PtsContext.CallbackException = e; fserr = PTS.fserrCallbackException; } catch { fsfmtr = new PTS.FSFMTR(); pfsFloatContent = pbrkrecpara = IntPtr.Zero; durFloaterWidth = dvrFloaterHeight = cPolygons = cVertices = 0; fsbbox = new PTS.FSBBOX(); PtsContext.CallbackException = new System.Exception("Caught a non CLS Exception"); fserr = PTS.fserrCallbackException; } return fserr; }
//------------------------------------------------------------------- // UpdateBottomlessFloaterContent //------------------------------------------------------------------- internal override void UpdateBottomlessFloaterContent( FloaterBaseParaClient paraClient, // IN: int fSuppressTopSpace, // IN: suppress empty space at the top of the page uint fswdir, // IN: direction of track int fAtMaxWidth, // IN: formating is at full width of column int durAvailable, // IN: width of available space int dvrAvailable, // IN: height of available space IntPtr pfsFloatContent, // IN: floater content (in UIElementParagraph, this is an alias to the paraClient) out PTS.FSFMTRBL fsfmtrbl, // OUT: result of formatting out int durFloaterWidth, // OUT: floater width out int dvrFloaterHeight, // OUT: floater height out PTS.FSBBOX fsbbox, // OUT: floater bbox out int cPolygons, // OUT: number of polygons out int cVertices) // OUT: total number of vertices in all polygons { fsfmtrbl = default(PTS.FSFMTRBL); durFloaterWidth = dvrFloaterHeight = cPolygons = cVertices = 0; fsbbox = new PTS.FSBBOX(); Invariant.Assert(false, "No appropriate handling for update in attached object floater."); }
internal override void FormatFloaterContentBottomless( FloaterBaseParaClient paraClient, // IN: int fSuppressTopSpace, // IN: suppress empty space at the top of the page uint fswdir, // IN: direction of track int fAtMaxWidth, // IN: formating is at full width of column int durAvailable, // IN: width of available space int dvrAvailable, // IN: height of available space out PTS.FSFMTRBL fsfmtrbl, // OUT: result of formatting out IntPtr pfsFloatContent, // OUT: opaque for PTS pointer pointer to formatted content out int durFloaterWidth, // OUT: floater width out int dvrFloaterHeight, // OUT: floater height out PTS.FSBBOX fsbbox, // OUT: floater bbox out int cPolygons, // OUT: number of polygons out int cVertices) // OUT: total number of vertices in all polygons { uint fswdirPara = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty))); Invariant.Assert(paraClient is FloaterParaClient); int subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin; int dvrTopSpace, fPageBecomesUninterruptable; int cColumns; PTS.FSCOLUMNINFO[] columnInfoCollection; IntPtr pmcsclientOut; MbpInfo mbp; double specifiedWidth; // If horizontal alignment is Stretch and we are not formatting at max width, // we cannot proceed. if (IsFloaterRejected(PTS.ToBoolean(fAtMaxWidth), TextDpi.FromTextDpi(durAvailable))) { // Set foater width, height to be greater than available values to signal to PTS that floater does not fit in the space durFloaterWidth = durAvailable + 1; dvrFloaterHeight = dvrAvailable + 1; cPolygons = cVertices = 0; fsfmtrbl = PTS.FSFMTRBL.fmtrblInterrupted; fsbbox = new PTS.FSBBOX(); fsbbox.fDefined = PTS.False; pfsFloatContent = IntPtr.Zero; } else { // Initialize the subpage size. PTS subpage margin is always set to 0 for Floaters. // If width on floater is specified, use the specified value. // Margin, border and padding of the floater is extracted from available subpage width. mbp = MbpInfo.FromElement(Element); specifiedWidth = CalculateWidth(TextDpi.FromTextDpi(durAvailable)); AdjustDurAvailable(specifiedWidth, ref durAvailable, out subpageWidth); durSubpageMargin = subpageWidth; urSubpageMargin = vrSubpageMargin = 0; // Initialize column info. Floater always has just 1 column. cColumns = 1; columnInfoCollection = new PTS.FSCOLUMNINFO[cColumns]; columnInfoCollection[0].durBefore = 0; columnInfoCollection[0].durWidth = subpageWidth; // Create subpage InvalidateMainTextSegment(); CreateSubpageBottomlessHelper(PtsContext, _mainTextSegment.Handle, PTS.True, fswdir, subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin, cColumns, columnInfoCollection, out fsfmtrbl, out pfsFloatContent, out dvrFloaterHeight, out fsbbox, out pmcsclientOut, out dvrTopSpace, out fPageBecomesUninterruptable); if (fsfmtrbl != PTS.FSFMTRBL.fmtrblCollision) { // PTS subpage does not support autosizing, but Floater needs to autosize to its // content. To workaround this problem, second format of subpage is performed, if // necessary. It means that if the width of bounding box is smaller than subpage's // width, second formatting is performed. // However, if HorizontalAlignment is set to Stretch we should not reformat because // floater should be at full column width if (PTS.ToBoolean(fsbbox.fDefined)) { if(fsbbox.fsrc.du < subpageWidth && Double.IsNaN(specifiedWidth) && HorizontalAlignment != HorizontalAlignment.Stretch) { // There is a need to reformat PTS subpage, so destroy any resourcces allocated by PTS // during previous formatting. if (pfsFloatContent != IntPtr.Zero) { PTS.Validate(PTS.FsDestroySubpage(PtsContext.Context, pfsFloatContent), PtsContext); } if (pmcsclientOut != IntPtr.Zero) { MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState; PTS.ValidateHandle(mcs); mcs.Dispose(); pmcsclientOut = IntPtr.Zero; } // Create subpage with new width. subpageWidth = durSubpageMargin = fsbbox.fsrc.du + 1; // add 1/300px to avoid rounding errors columnInfoCollection[0].durWidth = subpageWidth; CreateSubpageBottomlessHelper(PtsContext, _mainTextSegment.Handle, PTS.True, fswdir, subpageWidth, urSubpageMargin, durSubpageMargin, vrSubpageMargin, cColumns, columnInfoCollection, out fsfmtrbl, out pfsFloatContent, out dvrFloaterHeight, out fsbbox, out pmcsclientOut, out dvrTopSpace, out fPageBecomesUninterruptable); } } else { subpageWidth = TextDpi.ToTextDpi(TextDpi.MinWidth); } // Destroy objects created by PTS, but not used here. if (pmcsclientOut != IntPtr.Zero) { MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState; PTS.ValidateHandle(mcs); mcs.Dispose(); pmcsclientOut = IntPtr.Zero; } // Get the size of the floater. For height PTS already reports calculated value. // But width is the same as subpage width. durFloaterWidth = subpageWidth + mbp.MBPLeft + mbp.MBPRight; dvrFloaterHeight += mbp.MBPTop + mbp.MBPBottom; // Check if floater width fits in available width. It may exceed available width because borders // and padding are added. if ( dvrFloaterHeight > dvrAvailable || (durFloaterWidth > durAvailable && !PTS.ToBoolean(fAtMaxWidth)) ) { // Get rid of any previous formatting if (pfsFloatContent != IntPtr.Zero) { PTS.Validate(PTS.FsDestroySubpage(PtsContext.Context, pfsFloatContent), PtsContext); } Debug.Assert(pmcsclientOut == IntPtr.Zero); cPolygons = cVertices = 0; pfsFloatContent = IntPtr.Zero; } else { // Width and height are OK, format floater // Adjust bounding box to cover entire floater. fsbbox.fsrc.u = 0; fsbbox.fsrc.v = 0; fsbbox.fsrc.du = durFloaterWidth; fsbbox.fsrc.dv = dvrFloaterHeight; // Tight wrap is disabled for now. cPolygons = cVertices = 0; } } else { Debug.Assert(pmcsclientOut == IntPtr.Zero); durFloaterWidth = dvrFloaterHeight = 0; cPolygons = cVertices = 0; pfsFloatContent = IntPtr.Zero; } } // Update handle to PTS subpage. ((FloaterParaClient)paraClient).SubpageHandle = pfsFloatContent; }
internal override void FormatFloaterContentFinite( FloaterBaseParaClient paraClient, // IN: IntPtr pbrkrecIn, // IN: break record---use if !IntPtr.Zero int fBRFromPreviousPage, // IN: break record was created on previous page IntPtr footnoteRejector, // IN: int fEmptyOk, // IN: is it OK not to add anything? int fSuppressTopSpace, // IN: suppress empty space at the top of the page uint fswdir, // IN: direction of Track int fAtMaxWidth, // IN: formating is at full width of column int durAvailable, // IN: width of available space int dvrAvailable, // IN: height of available space PTS.FSKSUPPRESSHARDBREAKBEFOREFIRSTPARA fsksuppresshardbreakbeforefirstparaIn, // IN: suppress breaks at track start? out PTS.FSFMTR fsfmtr, // OUT: result of formatting out IntPtr pfsFloatContent, // OUT: opaque for PTS pointer pointer to formatted content out IntPtr pbrkrecOut, // OUT: pointer to the floater content break record out int durFloaterWidth, // OUT: floater width out int dvrFloaterHeight, // OUT: floater height out PTS.FSBBOX fsbbox, // OUT: floater bbox out int cPolygons, // OUT: number of polygons out int cVertices) // OUT: total number of vertices in all polygons { uint fswdirPara = PTS.FlowDirectionToFswdir(((FlowDirection)Element.GetValue(FrameworkElement.FlowDirectionProperty))); int subpageWidth, subpageHeight; int dvrTopSpace; int cColumns; PTS.FSRECT fsrcSubpageMargin; PTS.FSCOLUMNINFO[] columnInfoCollection; IntPtr pmcsclientOut; double specifiedWidth; MbpInfo mbp; Invariant.Assert(paraClient is FloaterParaClient); // If horizontal alignment is Stretch and we are not formatting at max width, // we cannot proceed. if (IsFloaterRejected(PTS.ToBoolean(fAtMaxWidth), TextDpi.FromTextDpi(durAvailable))) { durFloaterWidth = dvrFloaterHeight = 0; cPolygons = cVertices = 0; fsfmtr = new PTS.FSFMTR(); fsfmtr.kstop = PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace; fsfmtr.fContainsItemThatStoppedBeforeFootnote = PTS.False; fsfmtr.fForcedProgress = PTS.False; fsbbox = new PTS.FSBBOX(); fsbbox.fDefined = PTS.False; pbrkrecOut = IntPtr.Zero; pfsFloatContent = IntPtr.Zero; } else { // When formatting bottomless page, PTS may format paragraphs as finite. This happens // in case of multiple columns. In this case make sure that height is not too big. if (!StructuralCache.CurrentFormatContext.FinitePage) { if (Double.IsInfinity(StructuralCache.CurrentFormatContext.PageHeight)) { if (dvrAvailable > PTS.dvBottomUndefined / 2) { dvrAvailable = Math.Min(dvrAvailable, PTS.dvBottomUndefined / 2); fEmptyOk = PTS.False; } } else { dvrAvailable = Math.Min(dvrAvailable, TextDpi.ToTextDpi(StructuralCache.CurrentFormatContext.PageHeight)); } } // Initialize the subpage size. PTS subpage margin is always set to 0 for Floaters. // If width on floater is specified, use the specified value. // Margin, border and padding of the floater is extracted from available subpage height mbp = MbpInfo.FromElement(Element); // We do not mirror margin as it's used to dist text left and right, and is unnecessary. // Clip Floater.Width to available width specifiedWidth = CalculateWidth(TextDpi.FromTextDpi(durAvailable)); AdjustDurAvailable(specifiedWidth, ref durAvailable, out subpageWidth); subpageHeight = Math.Max(1, dvrAvailable - (mbp.MBPTop + mbp.MBPBottom)); fsrcSubpageMargin = new PTS.FSRECT(); fsrcSubpageMargin.du = subpageWidth; fsrcSubpageMargin.dv = subpageHeight; // Initialize column info. Floater always has just 1 column. cColumns = 1; columnInfoCollection = new PTS.FSCOLUMNINFO[cColumns]; columnInfoCollection[0].durBefore = 0; columnInfoCollection[0].durWidth = subpageWidth; // Format subpage CreateSubpageFiniteHelper(PtsContext, pbrkrecIn, fBRFromPreviousPage, _mainTextSegment.Handle, footnoteRejector, fEmptyOk, PTS.True, fswdir, subpageWidth, subpageHeight, ref fsrcSubpageMargin, cColumns, columnInfoCollection, PTS.False, fsksuppresshardbreakbeforefirstparaIn, out fsfmtr, out pfsFloatContent, out pbrkrecOut, out dvrFloaterHeight, out fsbbox, out pmcsclientOut, out dvrTopSpace); // Initialize subpage metrics if (fsfmtr.kstop >= PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace) // No progress or collision { Debug.Assert(pmcsclientOut == IntPtr.Zero); durFloaterWidth = dvrFloaterHeight = 0; cPolygons = cVertices = 0; //pbrkrecpara = IntPtr.Zero; } else { // PTS subpage does not support autosizing, but Floater needs to autosize to its // content. To workaround this problem, second format of subpage is performed, if // necessary. It means that if the width of bounding box is smaller than subpage's // width, second formatting is performed. // However, if HorizontalAlignment is set to Stretch we should not reformat because floater // should be at max width if (PTS.ToBoolean(fsbbox.fDefined)) { if(fsbbox.fsrc.du < subpageWidth && Double.IsNaN(specifiedWidth) && HorizontalAlignment != HorizontalAlignment.Stretch) { // There is a need to reformat PTS subpage, so destroy any resourcces allocated by PTS // during previous formatting. if (pfsFloatContent != IntPtr.Zero) { PTS.Validate(PTS.FsDestroySubpage(PtsContext.Context, pfsFloatContent), PtsContext); pfsFloatContent = IntPtr.Zero; } if (pbrkrecOut != IntPtr.Zero) { PTS.Validate(PTS.FsDestroySubpageBreakRecord(PtsContext.Context, pbrkrecOut), PtsContext); pbrkrecOut = IntPtr.Zero; } if (pmcsclientOut != IntPtr.Zero) { MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState; PTS.ValidateHandle(mcs); mcs.Dispose(); pmcsclientOut = IntPtr.Zero; } // Create subpage with new width. subpageWidth = fsbbox.fsrc.du + 1; // add 1/300px to avoid rounding errors fsrcSubpageMargin.du = subpageWidth; fsrcSubpageMargin.dv = subpageHeight; columnInfoCollection[0].durWidth = subpageWidth; CreateSubpageFiniteHelper(PtsContext, pbrkrecIn, fBRFromPreviousPage, _mainTextSegment.Handle, footnoteRejector, fEmptyOk, PTS.True, fswdir, subpageWidth, subpageHeight, ref fsrcSubpageMargin, cColumns, columnInfoCollection, PTS.False, fsksuppresshardbreakbeforefirstparaIn, out fsfmtr, out pfsFloatContent, out pbrkrecOut, out dvrFloaterHeight, out fsbbox, out pmcsclientOut, out dvrTopSpace); } } else { subpageWidth = TextDpi.ToTextDpi(TextDpi.MinWidth); } // Destroy objects created by PTS, but not used here. if (pmcsclientOut != IntPtr.Zero) { MarginCollapsingState mcs = PtsContext.HandleToObject(pmcsclientOut) as MarginCollapsingState; PTS.ValidateHandle(mcs); mcs.Dispose(); pmcsclientOut = IntPtr.Zero; } // Get the size of the floater. For height PTS already reports calculated value. // But width is the same as subpage width. Add margin values here since we do not use // distance to text anymore durFloaterWidth = subpageWidth + mbp.MBPLeft + mbp.MBPRight; // Add back all MBP values since we do not use dist to text dvrFloaterHeight += mbp.MBPTop + mbp.MBPBottom; // Check if floater width fits in available width. It may exceed available width because borders and // padding are added. fsbbox.fsrc.u = 0; fsbbox.fsrc.v = 0; fsbbox.fsrc.du = durFloaterWidth; fsbbox.fsrc.dv = dvrFloaterHeight; fsbbox.fDefined = PTS.True; // Tight wrap is disabled for now. cPolygons = cVertices = 0; if(durFloaterWidth > durAvailable || dvrFloaterHeight > dvrAvailable) { if(PTS.ToBoolean(fEmptyOk)) { // Get rid of any previous formatting if (pfsFloatContent != IntPtr.Zero) { PTS.Validate(PTS.FsDestroySubpage(PtsContext.Context, pfsFloatContent), PtsContext); pfsFloatContent = IntPtr.Zero; } if (pbrkrecOut != IntPtr.Zero) { PTS.Validate(PTS.FsDestroySubpageBreakRecord(PtsContext.Context, pbrkrecOut), PtsContext); pbrkrecOut = IntPtr.Zero; } cPolygons = cVertices = 0; fsfmtr.kstop = PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace; } else { fsfmtr.fForcedProgress = PTS.True; } } } } // Update handle to PTS subpage. ((FloaterParaClient)paraClient).SubpageHandle = pfsFloatContent; }
//------------------------------------------------------------------- // FormatFloaterContentBottomless //------------------------------------------------------------------- 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 { Invariant.Assert(paraClient is UIElementParaClient); Invariant.Assert(Element is BlockUIContainer); if (fAtMaxWidth == PTS.False) { // BlockUIContainer is only formatted at full column width // 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 { cPolygons = cVertices = 0; // Format UIElement if (((BlockUIContainer)Element).Child != null) { EnsureUIElementIsland(); FormatUIElement(durAvailable, out fsbbox); // Set output values for floater content pfsFloatContent = paraClient.Handle; fsfmtrbl = PTS.FSFMTRBL.fmtrblGoalReached; fsbbox.fDefined = PTS.True; durFloaterWidth = fsbbox.fsrc.du; dvrFloaterHeight = fsbbox.fsrc.dv; } else { ClearUIElementIsland(); MbpInfo mbp = MbpInfo.FromElement(Element); fsbbox.fsrc = new PTS.FSRECT(); fsbbox.fsrc.du = durAvailable; fsbbox.fsrc.dv = mbp.BPTop + mbp.BPBottom; fsbbox.fDefined = PTS.True; pfsFloatContent = paraClient.Handle; fsfmtrbl = PTS.FSFMTRBL.fmtrblGoalReached; durFloaterWidth = fsbbox.fsrc.du; dvrFloaterHeight = fsbbox.fsrc.dv; } } }
//------------------------------------------------------------------- // FormatFloaterContentFinite //------------------------------------------------------------------- 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 { Invariant.Assert(paraClient is UIElementParaClient); Invariant.Assert(Element is BlockUIContainer); if (fAtMaxWidth == PTS.False && fEmptyOk == PTS.True) { // Do not format if not at max width, and if fEmptyOk is true 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 { cPolygons = cVertices = 0; // Formatting is not at max width but proceeds anyway because adding no content is not allowed fsfmtr.fForcedProgress = PTS.FromBoolean(fAtMaxWidth == PTS.False); // Format UIElement if (((BlockUIContainer)Element).Child != null) { EnsureUIElementIsland(); FormatUIElement(durAvailable, out fsbbox); } else { // Child elementis null. Create fsbbox only with border and padding info ClearUIElementIsland(); MbpInfo mbp = MbpInfo.FromElement(Element); fsbbox.fsrc = new PTS.FSRECT(); fsbbox.fsrc.du = durAvailable; fsbbox.fsrc.dv = mbp.BPTop + mbp.BPBottom; } durFloaterWidth = fsbbox.fsrc.du; dvrFloaterHeight = fsbbox.fsrc.dv; if (dvrAvailable < dvrFloaterHeight && fEmptyOk == PTS.True) { // Will not fit in available space. Since fEmptyOk is true, we can return null floater durFloaterWidth = dvrFloaterHeight = 0; fsfmtr = new PTS.FSFMTR(); fsfmtr.kstop = PTS.FSFMTRKSTOP.fmtrNoProgressOutOfSpace; fsbbox = new PTS.FSBBOX(); fsbbox.fDefined = PTS.False; pfsFloatContent = IntPtr.Zero; } else { // Either floater fits in available space or it doesn't but we cannot return nothing. // Use the space needed, and set formatter result to forced progress if BUC does not fit in available space. fsbbox.fDefined = PTS.True; pfsFloatContent = paraClient.Handle; if (dvrAvailable < dvrFloaterHeight) { // Indicate that progress was forced Invariant.Assert(fEmptyOk == PTS.False); fsfmtr.fForcedProgress = PTS.True; } fsfmtr.kstop = PTS.FSFMTRKSTOP.fmtrGoalReached; } // Set output values for floater content pbrkrecOut = IntPtr.Zero; fsfmtr.fContainsItemThatStoppedBeforeFootnote = PTS.False; } }