aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageBreaker.java266
1 files changed, 134 insertions, 132 deletions
diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
index 1137065ab..20fd89cd9 100644
--- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java
+++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
@@ -28,7 +28,6 @@ import org.apache.fop.area.Footnote;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
-import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.RegionBody;
import org.apache.fop.fo.pagination.StaticContent;
@@ -136,16 +135,9 @@ public class PageBreaker extends AbstractBreaker {
return super.getNextBlockList(childLC, nextSequenceStartsOn);
}
- /** {@inheritDoc} */
- protected List getNextKnuthElements(LayoutContext context, int alignment) {
- List contentList = null;
-
- while (!childFLM.isFinished() && contentList == null) {
- contentList = childFLM.getNextKnuthElements(context, alignment);
- }
+ private boolean containsFootnotes(List contentList, LayoutContext context) {
- // scan contentList, searching for footnotes
- boolean bFootnotesPresent = false;
+ boolean containsFootnotes = false;
if (contentList != null) {
ListIterator contentListIterator = contentList.listIterator();
while (contentListIterator.hasNext()) {
@@ -153,7 +145,7 @@ public class PageBreaker extends AbstractBreaker {
if (element instanceof KnuthBlockBox
&& ((KnuthBlockBox) element).hasAnchors()) {
// element represents a line with footnote citations
- bFootnotesPresent = true;
+ containsFootnotes = true;
LayoutContext footnoteContext = new LayoutContext(context);
footnoteContext.setStackLimitBP(context.getStackLimitBP());
footnoteContext.setRefIPD(pslm.getCurrentPV()
@@ -173,31 +165,46 @@ public class PageBreaker extends AbstractBreaker {
}
}
}
+ return containsFootnotes;
+ }
- if (bFootnotesPresent) {
- // handle the footnote separator
- StaticContent footnoteSeparator;
- footnoteSeparator = pslm.getPageSequence().getStaticContent("xsl-footnote-separator");
- if (footnoteSeparator != null) {
- // the footnote separator can contain page-dependent content such as
- // page numbers or retrieve markers, so its areas cannot simply be
- // obtained now and repeated in each page;
- // we need to know in advance the separator bpd: the actual separator
- // could be different from page to page, but its bpd would likely be
- // always the same
-
- // create a Block area that will contain the separator areas
- separatorArea = new Block();
- separatorArea.setIPD(pslm.getCurrentPV()
- .getRegionReference(Constants.FO_REGION_BODY).getIPD());
- // create a StaticContentLM for the footnote separator
- footnoteSeparatorLM = (StaticContentLayoutManager)
- pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
- pslm, footnoteSeparator, separatorArea);
- footnoteSeparatorLM.doLayout();
+ private void handleFootnoteSeparator() {
+ StaticContent footnoteSeparator;
+ footnoteSeparator = pslm.getPageSequence().getStaticContent("xsl-footnote-separator");
+ if (footnoteSeparator != null) {
+ // the footnote separator can contain page-dependent content such as
+ // page numbers or retrieve markers, so its areas cannot simply be
+ // obtained now and repeated in each page;
+ // we need to know in advance the separator bpd: the actual separator
+ // could be different from page to page, but its bpd would likely be
+ // always the same
- footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
- }
+ // create a Block area that will contain the separator areas
+ separatorArea = new Block();
+ separatorArea.setIPD(pslm.getCurrentPV()
+ .getRegionReference(Constants.FO_REGION_BODY).getIPD());
+ // create a StaticContentLM for the footnote separator
+ footnoteSeparatorLM
+ = pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
+ pslm, footnoteSeparator, separatorArea);
+ footnoteSeparatorLM.doLayout();
+
+ footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected List getNextKnuthElements(LayoutContext context, int alignment) {
+ List contentList = null;
+
+ while (!childFLM.isFinished() && contentList == null) {
+ contentList = childFLM.getNextKnuthElements(context, alignment);
+ }
+
+ // scan contentList, searching for footnotes
+ if (containsFootnotes(contentList, context)) {
+ // handle the footnote separator
+ handleFootnoteSeparator();
}
return contentList;
}
@@ -241,49 +248,61 @@ public class PageBreaker extends AbstractBreaker {
}
/**
- * Performs phase 3 operation
- *
- * @param alg page breaking algorithm
- * @param partCount part count
- * @param originalList the block sequence original list
- * @param effectiveList the block sequence effective list
+ * {@inheritDoc}
+ * This implementation checks whether to trigger column-balancing,
+ * or whether to take into account a 'last-page' condition.
*/
protected void doPhase3(PageBreakingAlgorithm alg, int partCount,
BlockSequence originalList, BlockSequence effectiveList) {
+
if (needColumnBalancing) {
- doPhase3WithColumnBalancing(alg, partCount, originalList, effectiveList);
- } else {
- if (!hasMoreContent() && pslm.getPageSequence().hasPagePositionLast()) {
- //last part is reached and we have a "last page" condition
- doPhase3WithLastPage(alg, partCount, originalList, effectiveList);
- } else {
- //Directly add areas after finding the breaks
- addAreas(alg, partCount, originalList, effectiveList);
+ //column balancing for the last part
+ doPhase3(alg, partCount, originalList, effectiveList, false);
+ return;
+ }
+
+ boolean lastPageMasterDefined = pslm.getPageSequence().hasPagePositionLast();
+ if (!hasMoreContent()) {
+ //last part is reached
+ if (lastPageMasterDefined) {
+ //last-page condition
+ doPhase3(alg, partCount, originalList, effectiveList, true);
+ return;
}
}
+
+ //nothing special: just add the areas now
+ addAreas(alg, partCount, originalList, effectiveList);
}
- private void doPhase3WithLastPage(PageBreakingAlgorithm alg, int partCount,
- BlockSequence originalList, BlockSequence effectiveList) {
- int newStartPos;
+ /**
+ * Restart the algorithm at the break corresponding
+ * to the given partCount
+ * (currently only used to redo the part after the
+ * last break in case of column-balancing
+ * and/or a last page-master)
+ */
+ private void doPhase3(PageBreakingAlgorithm alg, int partCount,
+ BlockSequence originalList, BlockSequence effectiveList,
+ boolean isLastPart) {
+
+
+ int newStartPos = 0;
int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
if (restartPoint > 0) {
- //Add definitive areas before last page
+ //Add definitive areas for the parts before the
+ //restarting point
addAreas(alg, restartPoint, originalList, effectiveList);
//Get page break from which we restart
PageBreakPosition pbp = (PageBreakPosition)
alg.getPageBreaks().get(restartPoint - 1);
- //Set starting position to the first element *after* the page-break
newStartPos = pbp.getLeafPos() + 1;
//Handle page break right here to avoid any side-effects
if (newStartPos > 0) {
handleBreakTrait(Constants.EN_PAGE);
}
- } else {
- newStartPos = 0;
}
- AbstractBreaker.log.debug("Last page handling now!!!");
- AbstractBreaker.log.debug("===================================================");
+
AbstractBreaker.log.debug("Restarting at " + restartPoint
+ ", new start position: " + newStartPos);
@@ -292,91 +311,74 @@ public class PageBreaker extends AbstractBreaker {
int currentPageNum = pslm.getCurrentPageNum();
pageProvider.setStartOfNextElementList(currentPageNum,
pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
- pageProvider.setLastPageIndex(currentPageNum);
-
- //Restart last page
- PageBreakingAlgorithm algRestart = new PageBreakingAlgorithm(
- getTopLevelLM(),
- getPageProvider(), createLayoutListener(),
- alg.getAlignment(), alg.getAlignmentLast(),
- footnoteSeparatorLength,
- isPartOverflowRecoveryActivated(), false, false);
- //alg.setConstantLineWidth(flowBPD);
- int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
- newStartPos,
- 1, true, BreakingAlgorithm.ALL_BREAKS);
- AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
- + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
+
+ PageBreakingAlgorithm algRestart = null;
+ int optimalPageCount;
//Make sure we only add the areas we haven't added already
effectiveList.ignoreAtStart = newStartPos;
- boolean replaceLastPage
- = iOptPageCount <= pslm.getCurrentPV().getBodyRegion().getColumnCount();
- if (replaceLastPage) {
- //Replace last page
- pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
- addAreas(algRestart, iOptPageCount, originalList, effectiveList);
- } else {
- addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
- //Add blank last page
- pageProvider.setLastPageIndex(currentPageNum + 1);
- pslm.setCurrentPage(pslm.makeNewPage(true, true));
- }
- AbstractBreaker.log.debug("===================================================");
- }
- private void doPhase3WithColumnBalancing(PageBreakingAlgorithm alg, int partCount,
- BlockSequence originalList, BlockSequence effectiveList) {
- AbstractBreaker.log.debug("Column balancing now!!!");
- AbstractBreaker.log.debug("===================================================");
- int newStartPos;
- int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
- if (restartPoint > 0) {
- //Add definitive areas
- addAreas(alg, restartPoint, originalList, effectiveList);
- //Get page break from which we restart
- PageBreakPosition pbp = (PageBreakPosition)
- alg.getPageBreaks().get(restartPoint - 1);
- newStartPos = pbp.getLeafPos();
- //Handle page break right here to avoid any side-effects
- if (newStartPos > 0) {
- handleBreakTrait(Constants.EN_PAGE);
- }
- } else {
- newStartPos = 0;
+ if (isLastPart) {
+ pageProvider.setLastPageIndex(currentPageNum);
}
- AbstractBreaker.log.debug("Restarting at " + restartPoint
- + ", new start position: " + newStartPos);
- pageBreakHandled = true;
- //Update so the available BPD is reported correctly
- pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
- pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+ if (needColumnBalancing) {
+ AbstractBreaker.log.debug("Column balancing now!!!");
+ AbstractBreaker.log.debug("===================================================");
+
+ //Restart last page
+ algRestart = new BalancingColumnBreakingAlgorithm(
+ getTopLevelLM(), getPageProvider(), createLayoutListener(),
+ alignment, Constants.EN_START, footnoteSeparatorLength,
+ isPartOverflowRecoveryActivated(),
+ pslm.getCurrentPV().getBodyRegion().getColumnCount());
+ AbstractBreaker.log.debug("===================================================");
+ } else {
+ //plain last page, no column balancing
+ AbstractBreaker.log.debug("Last page handling now!!!");
+ AbstractBreaker.log.debug("===================================================");
+ //Restart last page
+ algRestart = new PageBreakingAlgorithm(
+ getTopLevelLM(), getPageProvider(), createLayoutListener(),
+ alg.getAlignment(), alg.getAlignmentLast(),
+ footnoteSeparatorLength,
+ isPartOverflowRecoveryActivated(), false, false);
+ AbstractBreaker.log.debug("===================================================");
+ }
- //Restart last page
- PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm(
- getTopLevelLM(),
- getPageProvider(), createLayoutListener(),
- alignment, Constants.EN_START, footnoteSeparatorLength,
- isPartOverflowRecoveryActivated(),
- pslm.getCurrentPV().getBodyRegion().getColumnCount());
- //alg.setConstantLineWidth(flowBPD);
- int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
+ optimalPageCount = algRestart.findBreakingPoints(effectiveList,
newStartPos,
1, true, BreakingAlgorithm.ALL_BREAKS);
- AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
+ AbstractBreaker.log.debug("restart: optimalPageCount= " + optimalPageCount
+ " pageBreaks.size()= " + algRestart.getPageBreaks().size());
- if (iOptPageCount > pslm.getCurrentPV().getBodyRegion().getColumnCount()) {
- AbstractBreaker.log.warn(
- "Breaking algorithm produced more columns than are available.");
- /* reenable when everything works
- throw new IllegalStateException(
- "Breaking algorithm must not produce more columns than available.");
- */
+
+ boolean fitsOnePage
+ = optimalPageCount <= pslm.getCurrentPV().getBodyRegion().getColumnCount();
+
+ if (isLastPart) {
+ if (fitsOnePage) {
+ //Replace last page
+ pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
+ } else {
+ //Last page-master cannot hold the content.
+ //Add areas now...
+ addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
+ //...and add a blank last page
+ pageProvider.setLastPageIndex(currentPageNum + 1);
+ pslm.setCurrentPage(pslm.makeNewPage(true, true));
+ return;
+ }
+ } else {
+ if (!fitsOnePage) {
+ AbstractBreaker.log.warn(
+ "Breaking algorithm produced more columns than are available.");
+ /* reenable when everything works
+ throw new IllegalStateException(
+ "Breaking algorithm must not produce more columns than available.");
+ */
+ }
}
- //Make sure we only add the areas we haven't added already
- effectiveList.ignoreAtStart = newStartPos;
- addAreas(algRestart, iOptPageCount, originalList, effectiveList);
- AbstractBreaker.log.debug("===================================================");
+
+ addAreas(algRestart, optimalPageCount, originalList, effectiveList);
}
protected void startPart(BlockSequence list, int breakClass) {