private PageLayout ApplyPageBreak() { // Collapse any space layouts at the top of the page. Space layouts are // intended to provide space _between_ layouts and thus are not appropriate // at the top of a page. We collapse top space after drafting so that we know // where the space layouts fall on this page, but before applying the next // page break because lower layouts might now fit on this page. CollapseTopSpace(); PageDisposition disposition = AssessPageBreak(_bodyBox); // Avoid infinite overflow. If any layout starts at the top of the page and // is longer than the page, then it will return disposition overflow or split // and its page split index will be zero. Splitting at index zero is the same // thing as overflowing. Overflowing a full page will cause this page to move // all of its content onto a new page, leaving itself empty, and this will lead // to infinite overflow. So just stop the overflow right now. This will give us // an oversized page, but that's better than making a report with an infinite // number of empty pages. (In the current implementation, AssessPageBreak here on // a page layout will never return overflow because SetPageSplitIndex always // converts overflow to split, and then because a page can split it doesn't convert // it back to overflow. But for semantic clarity we still check for overflow here.) if ((disposition == PageDisposition.Overflow) || (disposition == PageDisposition.Split && _pageSplitIndex == 0)) { // If we can split as requested then do so. Otherwise bump the page split // index from zero to one - this will leave the oversized layout on this // page but overflow subsequent layouts to the next. If it's not possible // to bump the index then return an empty page to stop the overflow. Bump bump = BumpPageSplitIndex(); switch (bump) { case Bump.Bumped: case Bump.Unnecessary: // The split index has been moved beyond zero (or was already there) // and so we can now do the normal page break. This may still leave // the oversized layout on this page, but later layouts are moved // to the next page. break; case Bump.Impossible: // Couldn't fix the situation by splitting further down, so // just accept the oversized layout return((PageLayout)ShallowCopy()); } } PageLayout overflow = (PageLayout)DoPageBreak(); // This page now contains only the content that can fit in it. Content // that must be moved to the next page, or a later page, is now contained // in the overflow page. If the overflow page is empty then this is the last // page. // Redraft this page to set the layouts' bottoms so that they can // draw borders correctly, and redraft the new page so that its contents // start at the top of the page. Redraft(_bodyBox.Top); overflow?.Redraft(overflow._bodyBox.Top); return(overflow); }