diff options
author | Vincent Hennebert <vhennebert@apache.org> | 2013-10-08 11:29:05 +0000 |
---|---|---|
committer | Vincent Hennebert <vhennebert@apache.org> | 2013-10-08 11:29:05 +0000 |
commit | 54aa3369126225b7152d8692796babbc7f79135b (patch) | |
tree | eba35b6674992926f7bb60e9027d7b25756b7a72 /src | |
parent | bd40eedf996567982667e5987f64be54df417f1e (diff) | |
download | xmlgraphics-fop-54aa3369126225b7152d8692796babbc7f79135b.tar.gz xmlgraphics-fop-54aa3369126225b7152d8692796babbc7f79135b.zip |
FOP-2106: Footnote put on earlier page than the one that contains the footnote call
Patch by Alexey Neyman, committed with minor modifications
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1530232 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r-- | src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java | 78 |
1 files changed, 46 insertions, 32 deletions
diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 59145dd72..a5084bac5 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -140,7 +140,10 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { */ protected class KnuthPageNode extends KnuthNode { - /** Additional length due to footnotes. */ + /** Additional length due to already inserted footnotes. */ + public int insertedFootnotes; + + /** Total length of the footnotes. */ public int totalFootnotes; /** Index of the last inserted footnote. */ @@ -152,7 +155,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { public KnuthPageNode(int position, int line, int fitness, int totalWidth, int totalStretch, int totalShrink, - int totalFootnotes, int footnoteListIndex, int footnoteElementIndex, + int insertedFootnotes, int totalFootnotes, + int footnoteListIndex, int footnoteElementIndex, double adjustRatio, int availableShrink, int availableStretch, int difference, double totalDemerits, KnuthNode previous) { super(position, line, fitness, @@ -160,6 +164,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { adjustRatio, availableShrink, availableStretch, difference, totalDemerits, previous); this.totalFootnotes = totalFootnotes; + this.insertedFootnotes = insertedFootnotes; this.footnoteListIndex = footnoteListIndex; this.footnoteElementIndex = footnoteElementIndex; } @@ -172,7 +177,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { */ protected class BestPageRecords extends BestRecords { - private int[] bestFootnotesLength = new int[4]; + private int[] bestInsertedFootnotesLength = new int[4]; + private int[] bestTotalFootnotesLength = new int[4]; private int[] bestFootnoteListIndex = new int[4]; private int[] bestFootnoteElementIndex = new int[4]; @@ -182,13 +188,18 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { super.addRecord(demerits, node, adjust, availableShrink, availableStretch, difference, fitness); - bestFootnotesLength[fitness] = insertedFootnotesLength; + bestInsertedFootnotesLength[fitness] = insertedFootnotesLength; + bestTotalFootnotesLength[fitness] = totalFootnotesLength; bestFootnoteListIndex[fitness] = footnoteListIndex; bestFootnoteElementIndex[fitness] = footnoteElementIndex; } - public int getFootnotesLength(int fitness) { - return bestFootnotesLength[fitness]; + public int getInsertedFootnotesLength(int fitness) { + return bestInsertedFootnotesLength[fitness]; + } + + public int getTotalFootnotesLength(int fitness) { + return bestTotalFootnotesLength[fitness]; } public int getFootnoteListIndex(int fitness) { @@ -287,7 +298,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { int difference, double totalDemerits, KnuthNode previous) { return new KnuthPageNode(position, line, fitness, totalWidth, totalStretch, totalShrink, - insertedFootnotesLength, footnoteListIndex, footnoteElementIndex, + insertedFootnotesLength, totalFootnotesLength, + footnoteListIndex, footnoteElementIndex, adjustRatio, availableShrink, availableStretch, difference, totalDemerits, previous); } @@ -298,7 +310,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { int totalWidth, int totalStretch, int totalShrink) { return new KnuthPageNode(position, line, fitness, totalWidth, totalStretch, totalShrink, - ((BestPageRecords) best).getFootnotesLength(fitness), + ((BestPageRecords) best).getInsertedFootnotesLength(fitness), + ((BestPageRecords) best).getTotalFootnotesLength(fitness), ((BestPageRecords) best).getFootnoteListIndex(fitness), ((BestPageRecords) best).getFootnoteElementIndex(fitness), best.getAdjust(fitness), best.getAvailableShrink(fitness), @@ -405,6 +418,12 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { resetFootnotes(((KnuthBlockBox) resetElement).getElementLists()); } } + assert restartingNode instanceof KnuthPageNode; + KnuthPageNode restartingPageNode = (KnuthPageNode) restartingNode; + footnoteElementIndex = restartingPageNode.footnoteElementIndex; + footnoteListIndex = restartingPageNode.footnoteListIndex; + totalFootnotesLength = restartingPageNode.totalFootnotes; + insertedFootnotesLength = restartingPageNode.insertedFootnotes; } return returnValue; } @@ -413,13 +432,6 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { for (int i = 0; i < elementLists.size(); i++) { ListUtil.removeLast(footnotesList); ListUtil.removeLast(lengthList); - - // update totalFootnotesLength - if (!lengthList.isEmpty()) { - totalFootnotesLength = ListUtil.getLast(lengthList); - } else { - totalFootnotesLength = 0; - } } // update footnotesPending; if (footnotesList.size() == 0) { @@ -502,7 +514,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { } if (footnotesPending) { // compute the total length of the footnotes not yet inserted - int allFootnotes = totalFootnotesLength - pageNode.totalFootnotes; + int allFootnotes = totalFootnotesLength - pageNode.insertedFootnotes; if (allFootnotes > 0) { // this page contains some footnote citations // add the footnote separator width @@ -511,7 +523,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // there is enough space to insert all footnotes: // add the whole allFootnotes length actualWidth += allFootnotes; - insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes; + insertedFootnotesLength = pageNode.insertedFootnotes + allFootnotes; footnoteListIndex = footnotesList.size() - 1; footnoteElementIndex = getFootnoteList(footnoteListIndex).size() - 1; @@ -528,7 +540,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // this is the first feasible break; in this case it is allowed // to break and defer, if necessary, old and new footnotes actualWidth += footnoteSplit; - insertedFootnotesLength = pageNode.totalFootnotes + footnoteSplit; + insertedFootnotesLength = pageNode.insertedFootnotes + footnoteSplit; // footnoteListIndex has been set in getFootnoteSplit() // footnoteElementIndex has been set in getFootnoteSplit() } else { @@ -538,7 +550,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // that cannot be broken: // add the whole allFootnotes length, so this breakpoint will be discarded actualWidth += allFootnotes; - insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes; + insertedFootnotesLength = pageNode.insertedFootnotes + allFootnotes; footnoteListIndex = footnotesList.size() - 1; footnoteElementIndex = getFootnoteList(footnoteListIndex).size() - 1; @@ -569,7 +581,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { private boolean canDeferOldFootnotes(KnuthPageNode node, int contentElementIndex) { return (noBreakBetween(node.position, contentElementIndex) && deferredFootnotes(node.footnoteListIndex, - node.footnoteElementIndex, node.totalFootnotes)); + node.footnoteElementIndex, node.insertedFootnotes)); } /** @@ -649,7 +661,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { boolean canDeferOldFootnotes) { return getFootnoteSplit(activeNode.footnoteListIndex, activeNode.footnoteElementIndex, - activeNode.totalFootnotes, + activeNode.insertedFootnotes, availableLength, canDeferOldFootnotes); } @@ -714,10 +726,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { int prevIndex = -1; int index = -1; - while (!(somethingAdded && splitLength > availableLength)) { - if (!somethingAdded) { - somethingAdded = true; - } else { + while (splitLength <= availableLength) { + if (somethingAdded) { prevSplitLength = splitLength; prevIndex = index; } @@ -733,6 +743,10 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // element is a box splitLength += element.getWidth(); boxPreceding = true; + if (splitLength > prevSplitLength) { + // and it is non-empty + somethingAdded = true; + } } else if (element.isGlue()) { // element is a glue if (boxPreceding) { @@ -749,6 +763,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { index = noteListIterator.previousIndex(); break; } + boxPreceding = false; } } } @@ -758,7 +773,6 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // page here // if prevSplitLength is > 0 we can insert some footnote content in this page // and insert the remaining in the following one - //TODO: check this conditional, as the first one is always false...? if (!somethingAdded) { // there was not enough space to add a piece of the first new footnote // this is not a good break @@ -781,7 +795,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { if (difference > 0) { int maxAdjustment = totalStretch - activeNode.totalStretch; // add the footnote separator stretch if some footnote content will be added - if (((KnuthPageNode) activeNode).totalFootnotes < totalFootnotesLength) { + if (((KnuthPageNode) activeNode).insertedFootnotes < totalFootnotesLength) { maxAdjustment += footnoteSeparatorLength.getStretch(); } if (maxAdjustment > 0) { @@ -792,7 +806,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { } else if (difference < 0) { int maxAdjustment = totalShrink - activeNode.totalShrink; // add the footnote separator shrink if some footnote content will be added - if (((KnuthPageNode) activeNode).totalFootnotes < totalFootnotesLength) { + if (((KnuthPageNode) activeNode).insertedFootnotes < totalFootnotesLength) { maxAdjustment += footnoteSeparatorLength.getShrink(); } if (maxAdjustment > 0) { @@ -866,7 +880,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { for (KnuthPageNode node = (KnuthPageNode) getNode(i); node != null; node = (KnuthPageNode) node.next) { - if (node.totalFootnotes < totalFootnotesLength) { + if (node.insertedFootnotes < totalFootnotesLength) { // layout remaining footnote bodies createFootnotePages(node); } @@ -876,7 +890,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { private void createFootnotePages(KnuthPageNode lastNode) { - insertedFootnotesLength = lastNode.totalFootnotes; + insertedFootnotesLength = lastNode.insertedFootnotes; footnoteListIndex = lastNode.footnoteListIndex; footnoteElementIndex = lastNode.footnoteElementIndex; int availableBPD = getLineWidth(lastNode.line); @@ -902,7 +916,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // cannot add any content: create a new node and start again KnuthPageNode node = (KnuthPageNode) createNode(lastNode.position, prevNode.line + 1, 1, - insertedFootnotesLength - prevNode.totalFootnotes, + insertedFootnotesLength - prevNode.insertedFootnotes, 0, 0, 0, 0, 0, 0, 0, prevNode); @@ -916,7 +930,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // create the last node KnuthPageNode node = (KnuthPageNode) createNode(lastNode.position, prevNode.line + 1, 1, - totalFootnotesLength - prevNode.totalFootnotes, 0, 0, + totalFootnotesLength - prevNode.insertedFootnotes, 0, 0, 0, 0, 0, 0, 0, prevNode); addNode(node.line, node); |