From b497601af9af4d41ebc4b6d65df2a36b8ae5a2aa Mon Sep 17 00:00:00 2001 From: Luis Bernardo Date: Tue, 25 Nov 2014 13:50:30 +0000 Subject: [PATCH] make floats and footnotes play nice together git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_BasicSideFloats@1641619 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/layoutmgr/PageBreaker.java | 53 +++++++++ .../fop/layoutmgr/PageBreakingAlgorithm.java | 71 +++++++++--- .../layoutmgr/PageSequenceLayoutManager.java | 12 ++ .../standard-testcases/float_7.xml | 107 ++++++++++++++++++ 4 files changed, 228 insertions(+), 15 deletions(-) create mode 100644 test/layoutengine/standard-testcases/float_7.xml diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index 206aac83c..ba676ab89 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -56,6 +56,19 @@ public class PageBreaker extends AbstractBreaker { private int floatHeight; private int floatYOffset; + private List relayedFootnotesList; + private List relayedLengthList; + private int relayedTotalFootnotesLength; + private int relayedInsertedFootnotesLength; + private boolean relayedFootnotesPending; + private boolean relayedNewFootnotes; + private int relayedFirstNewFootnoteIndex; + private int relayedFootnoteListIndex; + private int relayedFootnoteElementIndex = -1; + private MinOptMax relayedFootnoteSeparatorLength; + private int previousFootnoteListIndex = -2; + private int previousFootnoteElementIndex = -2; + /** * The FlowLayoutManager object, which processes * the single fo:flow of the fo:page-sequence @@ -814,6 +827,10 @@ public class PageBreaker extends AbstractBreaker { int effectiveFloatHeight = alg.getFloatHeight(); pslm.recordEndOfFloat(effectiveFloatHeight); } + if (alg.handlingFloat()) { + PageSequenceLayoutManager pslm = (PageSequenceLayoutManager) getTopLevelLM(); + alg.relayFootnotes(pslm); + } } else { // no content for this part handleEmptyContent(); @@ -821,4 +838,40 @@ public class PageBreaker extends AbstractBreaker { pageBreakHandled = true; } + + public void holdFootnotes(List fl, List ll, int tfl, int ifl, boolean fp, boolean nf, int fnfi, int fli, + int fei, MinOptMax fsl, int pfli, int pfei) { + relayedFootnotesList = fl; + relayedLengthList = ll; + relayedTotalFootnotesLength = tfl; + relayedInsertedFootnotesLength = ifl; + relayedFootnotesPending = fp; + relayedNewFootnotes = nf; + relayedFirstNewFootnoteIndex = fnfi; + relayedFootnoteListIndex = fli; + relayedFootnoteElementIndex = fei; + relayedFootnoteSeparatorLength = fsl; + previousFootnoteListIndex = pfli; + previousFootnoteElementIndex = pfei; + } + + public void retrieveFootones(PageBreakingAlgorithm alg) { + if (relayedFootnotesList != null && relayedFootnotesList.size() > 0) { + alg.loadFootnotes(relayedFootnotesList, relayedLengthList, relayedTotalFootnotesLength, + relayedInsertedFootnotesLength, relayedFootnotesPending, relayedNewFootnotes, + relayedFirstNewFootnoteIndex, relayedFootnoteListIndex, relayedFootnoteElementIndex, + relayedFootnoteSeparatorLength, previousFootnoteListIndex, + previousFootnoteElementIndex); + relayedFootnotesList = null; + relayedLengthList = null; + relayedTotalFootnotesLength = 0; + relayedInsertedFootnotesLength = 0; + relayedFootnotesPending = false; + relayedNewFootnotes = false; + relayedFirstNewFootnoteIndex = 0; + relayedFootnoteListIndex = 0; + relayedFootnoteElementIndex = -1; + relayedFootnoteSeparatorLength = null; + } + } } diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index dc3cc591a..008ec2265 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -103,10 +103,12 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { // just one float for now... private boolean handlingStartOfFloat; private boolean handlingEndOfFloat; - private int floatYOffset; private int floatHeight; private KnuthNode bestFloatEdgeNode; private FloatPosition floatPosition; + private int previousFootnoteListIndex = -2; + private int previousFootnoteElementIndex = -2; + private boolean relayingFootnotes; /** * Construct a page breaking algorithm. @@ -246,11 +248,14 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { footnoteElementIndex = -1; if (topLevelLM instanceof PageSequenceLayoutManager) { PageSequenceLayoutManager pslm = (PageSequenceLayoutManager) topLevelLM; + if (pslm.handlingStartOfFloat() || pslm.handlingEndOfFloat()) { + pslm.retrieveFootnotes(this); + } if (pslm.handlingStartOfFloat()) { floatHeight = Math.min(pslm.getFloatHeight(), lineWidth - pslm.getFloatYOffset()); } if (pslm.handlingEndOfFloat()) { - totalWidth += pslm.getOffsetDueToFloat(); + totalWidth += pslm.getOffsetDueToFloat() + insertedFootnotesLength; } } } @@ -1088,17 +1093,6 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { difference = 0; } } - // compute the indexes of the first footnote list and the first element in that list - int firstListIndex = ((KnuthPageNode) bestActiveNode.previous).footnoteListIndex; - int firstElementIndex = ((KnuthPageNode) bestActiveNode.previous).footnoteElementIndex; - if (footnotesList != null - && firstElementIndex == getFootnoteList(firstListIndex).size() - 1) { - // advance to the next list - firstListIndex++; - firstElementIndex = 0; - } else { - firstElementIndex++; - } // add nodes at the beginning of the list, as they are found // backwards, from the last one to the first one @@ -1109,6 +1103,24 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { if (handlingFloat() && floatPosition == null) { floatPosition = new FloatPosition(this.topLevelLM, bestActiveNode.position, ratio, difference); } else { + boolean useRelayedFootnotes = relayingFootnotes && bestActiveNode.previous.position == 0; + // compute the indexes of the first footnote list and the first element in that list + int firstListIndex = (useRelayedFootnotes) ? previousFootnoteListIndex + : ((KnuthPageNode) bestActiveNode.previous).footnoteListIndex; + int firstElementIndex = (useRelayedFootnotes) ? previousFootnoteElementIndex + : ((KnuthPageNode) bestActiveNode.previous).footnoteElementIndex; + if (useRelayedFootnotes) { + previousFootnoteListIndex = -2; + previousFootnoteElementIndex = -2; + relayingFootnotes = false; + } + if (footnotesList != null && firstElementIndex == getFootnoteList(firstListIndex).size() - 1) { + // advance to the next list + firstListIndex++; + firstElementIndex = 0; + } else { + firstElementIndex++; + } insertPageBreakAsFirst(new PageBreakPosition(this.topLevelLM, bestActiveNode.position, firstListIndex, firstElementIndex, ((KnuthPageNode) bestActiveNode).footnoteListIndex, ((KnuthPageNode) bestActiveNode).footnoteElementIndex, ratio, difference)); @@ -1266,13 +1278,14 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { protected void createForcedNodes(KnuthNode node, int line, int elementIdx, int difference, double r, double demerits, int fitnessClass, int availableShrink, int availableStretch, int newWidth, int newStretch, int newShrink) { - super.createForcedNodes(node, line, elementIdx, difference, r, demerits, fitnessClass, - availableShrink, availableStretch, newWidth, newStretch, newShrink); if (handlingFloat()) { if (bestFloatEdgeNode == null || demerits <= bestFloatEdgeNode.totalDemerits) { bestFloatEdgeNode = createNode(elementIdx, line + 1, fitnessClass, newWidth, newStretch, newShrink, r, availableShrink, availableStretch, difference, demerits, node); } + } else { + super.createForcedNodes(node, line, elementIdx, difference, r, demerits, fitnessClass, + availableShrink, availableStretch, newWidth, newStretch, newShrink); } } @@ -1319,4 +1332,32 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { handlingEndOfFloat = false; handlingStartOfFloat = false; } + + public void loadFootnotes(List fl, List ll, int tfl, int ifl, boolean fp, boolean nf, int fnfi, int fli, + int fei, MinOptMax fsl, int pfli, int pfei) { + footnotesList = fl; + lengthList = ll; + totalFootnotesLength = tfl; + insertedFootnotesLength = ifl; + footnotesPending = fp; + newFootnotes = nf; + firstNewFootnoteIndex = fnfi; + footnoteListIndex = fli; + footnoteElementIndex = fei; + footnoteSeparatorLength = fsl; + previousFootnoteListIndex = pfli; + previousFootnoteElementIndex = pfei; + relayingFootnotes = !(previousFootnoteListIndex == -2 && previousFootnoteElementIndex == -2); + } + + public void relayFootnotes(PageSequenceLayoutManager pslm) { + if (!relayingFootnotes) { + previousFootnoteListIndex = ((KnuthPageNode) bestFloatEdgeNode.previous).footnoteListIndex; + previousFootnoteElementIndex = ((KnuthPageNode) bestFloatEdgeNode.previous).footnoteElementIndex; + } + pslm.holdFootnotes(footnotesList, lengthList, totalFootnotesLength, insertedFootnotesLength, + footnotesPending, newFootnotes, firstNewFootnoteIndex, footnoteListIndex, + footnoteElementIndex, footnoteSeparatorLength, previousFootnoteListIndex, + previousFootnoteElementIndex); + } } diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java index 5cc2423a7..20c4616bd 100644 --- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java @@ -36,6 +36,7 @@ import org.apache.fop.fo.pagination.PageSequenceMaster; import org.apache.fop.fo.pagination.SideRegion; import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.layoutmgr.inline.ContentLayoutManager; +import org.apache.fop.traits.MinOptMax; /** * LayoutManager for a PageSequence. This class is instantiated by @@ -345,4 +346,15 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager flowIPD -= startIntrusionAdjustment + endIntrusionAdjustment; return flowIPD; } + + public void holdFootnotes(List fl, List ll, int tfl, int ifl, boolean fp, boolean nf, int fnfi, int fli, + int fei, MinOptMax fsl, int pfli, int pfei) { + if (fl != null && fl.size() > 0) { + pageBreaker.holdFootnotes(fl, ll, tfl, ifl, fp, nf, fnfi, fli, fei, fsl, pfli, pfei); + } + } + + public void retrieveFootnotes(PageBreakingAlgorithm alg) { + pageBreaker.retrieveFootones(alg); + } } diff --git a/test/layoutengine/standard-testcases/float_7.xml b/test/layoutengine/standard-testcases/float_7.xml new file mode 100644 index 000000000..6e51ea946 --- /dev/null +++ b/test/layoutengine/standard-testcases/float_7.xml @@ -0,0 +1,107 @@ + + + + + +

+ This test checks floats. +

+
+ + + + + + + + + + + Footnote in normal block before a float. + 1) + + + 1) The footnote from the normal block before the float. + + . + + + + + (a) + + + + Test for float and footnote inside a list. Test for float and footnote inside a list. Test for float and footnote inside a list. (see box) + + + + +The former dean's house at the University of Wisconsin (this is the alt text of the image in the Wikipedia page) + + + + + Test for float and footnote inside a list. Test for float and footnote inside a list. + + + + + + (b) + + + + Footnote in list that is being wrapped around a float. + 2) + + + 2) The footnote from the list that is being wrapped around a float. + + . + Test for float and footnote inside a list. Test for float and footnote inside a list. Test for float and footnote inside a list. Test for float and footnote inside a list. Test for float and footnote inside a list. + + + + + + Footnote in normal block after the float. + 3) + + + 3) The footnote from the normal block after the float. + + . + + +Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. Some filler text. + + + + + + + + + + + + + + +
-- 2.39.5