ASF Bugzilla – Attachment 18637 Details for
Bug 39777
[PATCH] GSoC: floats implementation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
The very same patch, with some english corrections as suggested by Simon Pepping
patchBeforeFloats-2.diff (text/plain), 114.60 KB, created by
Vincent Hennebert
on 2006-07-25 08:32:46 UTC
(
hide
)
Description:
The very same patch, with some english corrections as suggested by Simon Pepping
Filename:
MIME Type:
Creator:
Vincent Hennebert
Created:
2006-07-25 08:32:46 UTC
Size:
114.60 KB
patch
obsolete
>Index: src/java/org/apache/fop/layoutmgr/breaking/OutOfLineRecord.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/breaking/OutOfLineRecord.java (révision 0) >+++ src/java/org/apache/fop/layoutmgr/breaking/OutOfLineRecord.java (révision 0) >@@ -0,0 +1,600 @@ >+/* >+ * Copyright 2004-2006 The Apache Software Foundation. >+ * >+ * Licensed under the Apache License, Version 2.0 (the "License"); >+ * you may not use this file except in compliance with the License. >+ * You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.fop.layoutmgr.breaking; >+ >+import java.util.ArrayList; >+import java.util.LinkedList; >+import java.util.List; >+import java.util.ListIterator; >+ >+import org.apache.fop.layoutmgr.KnuthElement; >+import org.apache.fop.layoutmgr.PageBreakingAlgorithm; >+import org.apache.fop.layoutmgr.SpaceResolver; >+import org.apache.fop.layoutmgr.PageBreakingAlgorithm.KnuthPageNode; >+import org.apache.fop.traits.MinOptMax; >+ >+/** >+ * Helper class for dealing with out-of-line objects (before-floats and footnotes) when >+ * breaking text into pages. It stores the necessary informations to place out-of-line >+ * objects, and provides methods to manipulate them. >+ * >+ * @see PageBreakingAlgorithm >+ */ >+public class OutOfLineRecord { >+ >+ /** >+ * Stores informations about how many out-of-line objects have already been handled. >+ */ >+ public static class ProgressInfo { >+ >+ /** Cumulated BPD length of all out-of-line objects inserted so far. */ >+ private int alreadyInsertedLength = 0; >+ >+ /** Index of the last inserted out-of-line object. */ >+ private int lastInsertedIndex = -1; >+ >+ /** >+ * Index of the last inserted Knuth element of the last inserted out-of-line >+ * object. Currently only used for footnotes, as before-floats may not be split on >+ * several pages. Might be useful when later dealing with floats that cannot even >+ * be put on a page alone, however. >+ */ >+ private int lastElementOfLastInsertedIndex = -1; >+ >+ /** >+ * Initializes this record, as if no out-of-line object were handled yet. >+ */ >+ private void initialize() { >+ alreadyInsertedLength = 0; >+ lastInsertedIndex = -1; >+ lastElementOfLastInsertedIndex = -1; >+ } >+ >+ /** >+ * @return a copy of this record >+ */ >+ public ProgressInfo copy() { >+ ProgressInfo info = new ProgressInfo(); >+ info.alreadyInsertedLength = alreadyInsertedLength; >+ info.lastInsertedIndex = lastInsertedIndex; >+ info.lastElementOfLastInsertedIndex = lastElementOfLastInsertedIndex; >+ return info; >+ } >+ >+ /** >+ * Returns the cumulated length of all already typeset out-of-line objects. >+ * @return the total length in the block-progression-direction >+ */ >+ public int getAlreadyInsertedLength() { >+ return alreadyInsertedLength; >+ } >+ >+ /** >+ * Returns the index of the last element of the last already typeset out-of-line >+ * object. >+ * @return the index of the last placed KnuthElement >+ */ >+ public int getLastElementOfLastInsertedIndex() { >+ return lastElementOfLastInsertedIndex; >+ } >+ >+ /** >+ * @return the index of the last already typeset out-of-line object. >+ */ >+ public int getLastInsertedIndex() { >+ return lastInsertedIndex; >+ } >+ >+ public String toString() { >+ return "length=" + alreadyInsertedLength >+ + ", index=" + lastInsertedIndex >+ + ", elt=" + lastElementOfLastInsertedIndex; >+ } >+ } >+ >+ /** >+ * Sequences of KnuthElement corresponding to already encountered out-of-line objects. >+ * This is a List of List of KnuthElement. >+ */ >+ private List knuthSequences = null; >+ >+ /** >+ * Each element of this list corresponds to the cumulated length in the BPD of all the >+ * out-of-line objects up to the given index. This is a List of Integer. >+ * >+ * @see OutOfLineRecord#knuthSequences >+ */ >+ private List cumulativeLengths = null; >+ >+ /** >+ * True if new out-of-line objects are cited in the sequence of Knuth elements since >+ * the last encountered legal breakpoint. >+ * >+ * @see OutOfLineRecord#newSinceLastBreakpoint() >+ */ >+ private boolean newSinceLastBreakpoint = false; >+ >+ /** >+ * Index of the first newly encountered out-of-line object since the last legal >+ * breakpoint. >+ * >+ * @see OutOfLineRecord#knuthSequences >+ */ >+ private int firstNewIndex = 0; >+ >+ /** >+ * Dimension in the BPD of the separator between the out-of-line area and the main >+ * area. >+ */ >+ private MinOptMax separatorLength = null; >+ >+ /** >+ * Record of already handled out-of-line objects. >+ * >+ * @see ProgressInfo >+ */ >+ private ProgressInfo progressInfo; >+ >+ public OutOfLineRecord(MinOptMax separatorLength) { >+ this.separatorLength = separatorLength; >+ this.progressInfo = new ProgressInfo(); >+ } >+ >+ /** >+ * Initializes this record, as if no out-of-line object were handled yet. >+ */ >+ public void initialize() { >+ knuthSequences = null; >+ cumulativeLengths = null; >+ newSinceLastBreakpoint = false; >+ firstNewIndex = 0; >+ progressInfo.initialize(); >+ } >+ >+ /** >+ * @return the informations about already handled out-of-line objects >+ */ >+ public ProgressInfo getProgress() { >+ return this.progressInfo; >+ } >+ >+ /** >+ * @return the length in the BPD of the separator between the out-of-line area and the >+ * main area. >+ */ >+ public MinOptMax getSeparatorLength() { >+ return separatorLength; >+ } >+ >+ /** >+ * @return the total length of already encountered out-of-line objects >+ */ >+ public int getTotalLength() { >+ if (cumulativeLengths == null || cumulativeLengths.size() == 0) { >+ return 0; >+ } else { >+ return ((Integer) cumulativeLengths.get(cumulativeLengths.size() - 1)).intValue(); >+ } >+ } >+ >+ /** >+ * @return true if out-of-line objects have already been encountered (but not >+ * necessarily typeset yet) >+ */ >+ public boolean existing() { >+ return (knuthSequences != null && knuthSequences.size() > 0); >+ } >+ >+ public void resetNewSinceLastBreakpoint() { >+ newSinceLastBreakpoint = false; >+ } >+ >+ /** >+ * @return true if new out-of-line objects are cited in the sequence of Knuth >+ * elements since the last encountered legal breakpoint. >+ */ >+ public boolean newSinceLastBreakpoint() { >+ return newSinceLastBreakpoint; >+ } >+ >+ /** >+ * Records one or more newly encountered out-of-line objects. >+ * @param elementLists the list of corresponding Knuth sequences >+ */ >+ public void add(List elementLists) { >+ // Initialize stuff if necessary >+ if (knuthSequences == null) { >+ knuthSequences = new ArrayList(); >+ cumulativeLengths = new ArrayList(); >+ } >+ if (!newSinceLastBreakpoint) { >+ newSinceLastBreakpoint = true; >+ firstNewIndex = knuthSequences.size(); >+ } >+ // compute the total length of the footnotes >+ ListIterator elementListsIterator = elementLists.listIterator(); >+ while (elementListsIterator.hasNext()) { >+ LinkedList noteList = (LinkedList) elementListsIterator.next(); >+ >+ //Space resolution (Note: this does not respect possible stacking constraints >+ //between footnotes!) >+ SpaceResolver.resolveElementList(noteList); >+ >+ int noteLength = 0; >+ knuthSequences.add(noteList); >+ ListIterator noteListIterator = noteList.listIterator(); >+ while (noteListIterator.hasNext()) { >+ KnuthElement element = (KnuthElement) noteListIterator.next(); >+ if (element.isBox() || element.isGlue()) { >+ noteLength += element.getW(); >+ } >+ } >+ cumulativeLengths.add(new Integer(getTotalLength() + noteLength)); >+ } >+ } >+ >+ /** >+ * Sets the progress informations to the given values. Called whenever a new active >+ * node is considered; the informations regarding already handled out-of-line objects >+ * must be set to the active node's values in order to know from where to start the >+ * placement of further objects. >+ * >+ * @param info progress informations of the currently considered active node >+ */ >+ public void setProgress(ProgressInfo info) { >+ this.progressInfo.alreadyInsertedLength = info.alreadyInsertedLength; >+ this.progressInfo.lastElementOfLastInsertedIndex = info.lastElementOfLastInsertedIndex; >+ this.progressInfo.lastInsertedIndex = info.lastInsertedIndex; >+ } >+ >+ /* Unless I'm wrong, newOnThisPagePlusPiecesFromPrevious always implies >+ * notAllInserted. And if A => B, then A && B <=> B >+ * So this code may be simplified, see deferred() below >+ */ >+ /** >+// * Returns true if their are (pieces of) footnotes to be typeset on the >+// * current page. >+// * @param listIndex index of the last inserted footnote for the >+// * currently considered active node >+// * @param elementIndex index of the last element of the last inserted footnote >+// * @param length total length of all footnotes inserted so far >+// */ >+// public boolean deferredFootnotes(ProgressInfo progressInfo) { >+// boolean newOnThisPagePlusPiecesFromPrevious = >+// newSinceLastBreakpoint() >+// && firstNewIndex != 0 >+// && (progressInfo.lastInsertedIndex < firstNewIndex - 1 >+// || progressInfo.lastElementOfLastInsertedIndex < >+// ((LinkedList) knuthSequences.get(progressInfo.lastInsertedIndex)).size() - 1); >+// boolean notAllInserted = progressInfo.alreadyInsertedLength < getTotalLength(); >+// return notAllInserted; >+// } >+ >+ /** >+ * @return <code>true</code> if some out-of-line objects have not already been >+ * typeset. >+ */ >+ public boolean deferred() { >+ return progressInfo.alreadyInsertedLength < getTotalLength(); >+ } >+ >+ /** >+ * @return the number of not yet typeset out-of-line objects. >+ */ >+ public int getNbOfDeferred() { >+ return knuthSequences.size() - 1 - progressInfo.lastInsertedIndex; >+ } >+ >+ /** >+ * @return <code>true</code> if the last typeset out-of-line object must be split on >+ * several pages. >+ */ >+ public boolean isSplit() { >+ return (progressInfo.lastElementOfLastInsertedIndex >+ < ((LinkedList) knuthSequences.get(progressInfo.lastInsertedIndex)).size() - 1); >+ } >+ >+ /** >+ * Returns the out-of-line object corresponding to the given index. >+ * @param index index of the object >+ * @return a List of KnuthElement corresponding to the object, or <code>null</code> if >+ * it does not exist >+ */ >+ public List getSequence(int index) { >+ /*TODO vh: bof */ >+ if (knuthSequences == null) { >+ return null; >+ } else { >+ return (List) knuthSequences.get(index); >+ } >+ } >+ >+ /** >+ * Tries to split the flow of footnotes to put one part on the current page. >+ * @param prevNodeProgress informations about footnotes already inserted on the >+ * previous page >+ * @param availableLength available space for footnotes on this page >+ * @param canDeferOldFootnotes >+ * @return the length of footnotes which could be inserted on this page >+ */ >+ public int getFootnoteSplit(ProgressInfo prevNodeProgress, >+ int availableLength, boolean canDeferOldFootnotes) { >+ if (availableLength <= 0) { >+ progressInfo.alreadyInsertedLength = prevNodeProgress.getAlreadyInsertedLength(); >+ return 0; >+ } else { >+ // the split should contain a piece of the last footnote >+ // together with all previous, not yet inserted footnotes; >+ // but if this is not possible, try adding as much content as possible >+ int splitLength = 0; >+ ListIterator noteListIterator = null; >+ KnuthElement element = null; >+ boolean somethingAdded = false; >+ >+ // prevNodeProgress.lastInsertedIndex and >+ // prevNodeProgress.lastElementOfLastInsertedIndex points to the last footnote element >+ // already placed in a page: advance to the next element >+ int listIndex = prevNodeProgress.lastInsertedIndex; >+ int elementIndex = prevNodeProgress.lastElementOfLastInsertedIndex; >+ if (listIndex == -1 >+ || elementIndex == ((LinkedList) knuthSequences.get(listIndex)).size() - 1) { >+ listIndex++; >+ elementIndex = 0; >+ } else { >+ elementIndex++; >+ } >+ >+ // try adding whole notes >+ // if there are more than 1 footnote to insert >+ if (knuthSequences.size() - 1 > listIndex) { >+ // add the previous footnotes: these cannot be broken or deferred >+ if (!canDeferOldFootnotes >+ && newSinceLastBreakpoint() >+ && firstNewIndex > 0) { >+ splitLength = ((Integer) cumulativeLengths.get(firstNewIndex - 1)).intValue() >+ - prevNodeProgress.alreadyInsertedLength; >+ listIndex = firstNewIndex; >+ elementIndex = 0; >+ } >+ // try adding the new footnotes >+ while (((Integer) cumulativeLengths.get(listIndex)).intValue() >+ - prevNodeProgress.alreadyInsertedLength <= availableLength) { >+ splitLength = ((Integer) cumulativeLengths.get(listIndex)).intValue() >+ - prevNodeProgress.alreadyInsertedLength; >+ somethingAdded = true; >+ listIndex++; >+ elementIndex = 0; >+ } >+ // as this method is called only if it is not possible to insert >+ // all footnotes, at this point listIndex and elementIndex points to >+ // an existing element, the next one we will try to insert >+ } >+ >+ // try adding a split of the next note >+ noteListIterator = ((List) knuthSequences.get(listIndex)).listIterator(elementIndex); >+ >+ int prevSplitLength = 0; >+ int prevIndex = -1; >+ int index = -1; >+ >+ while (!somethingAdded || splitLength <= availableLength) { >+ if (!somethingAdded) { >+ somethingAdded = true; >+ } else { >+ prevSplitLength = splitLength; >+ prevIndex = index; >+ } >+ // get a sub-sequence from the note element list >+ boolean bPrevIsBox = false; >+ while (noteListIterator.hasNext()) { >+ // as this method is called only if it is not possible to insert >+ // all footnotes, and we have already tried (and failed) to insert >+ // this whole footnote, the while loop will never reach the end >+ // of the note sequence >+ element = (KnuthElement) noteListIterator.next(); >+ if (element.isBox()) { >+ // element is a box >+ splitLength += element.getW(); >+ bPrevIsBox = true; >+ } else if (element.isGlue()) { >+ // element is a glue >+ if (bPrevIsBox) { >+ // end of the sub-sequence >+ index = noteListIterator.previousIndex(); >+ break; >+ } >+ bPrevIsBox = false; >+ splitLength += element.getW(); >+ } else { >+ // element is a penalty >+ if (element.getP() < KnuthElement.INFINITE) { >+ // end of the sub-sequence >+ index = noteListIterator.previousIndex(); >+ break; >+ } >+ } >+ } >+ } >+ // if prevSplitLength is 0, this means that the available length isn't enough >+ // to insert even the smallest split of the last footnote, so we cannot end a >+ // page here >+ // if prevSplitLength is > 0 we can insert some footnote content in this page >+ // and insert the remaining in the following one >+ if (!somethingAdded) { >+ // there was not enough space to add a piece of the first new footnote >+ // this is not a good break >+ prevSplitLength = 0; >+ } else if (prevSplitLength > 0) { >+ // prevIndex is -1 if we have added only some whole footnotes >+ progressInfo.lastInsertedIndex = (prevIndex != -1) ? listIndex : listIndex - 1; >+ progressInfo.lastElementOfLastInsertedIndex = (prevIndex != -1) >+ ? prevIndex >+ : ((LinkedList) knuthSequences.get(progressInfo.lastInsertedIndex)).size() - 1; >+ } >+ progressInfo.alreadyInsertedLength >+ = prevNodeProgress.getAlreadyInsertedLength() + prevSplitLength; >+ return prevSplitLength; >+ } >+ } >+ >+ /** >+ * Tries to split the flow of floats to put some floats on the current page. >+ * @param prevProgress floats already inserted on the previous page >+ * @param availableLength available space for floats >+ * @return the length of floats which could be placed on the current page >+ */ >+ public int getFloatSplit(ProgressInfo prevProgress, int availableLength) { >+ /* >+ * Normally this method is called only when there is some place for >+ * floats => availableLength > 0 >+ */ >+ int splitLength = 0; >+ int listIndex = prevProgress.lastInsertedIndex + 1; >+ >+ while (listIndex < knuthSequences.size() >+ && ((Integer) cumulativeLengths.get(listIndex)).intValue() >+ - prevProgress.alreadyInsertedLength <= availableLength) { >+ splitLength = ((Integer) cumulativeLengths.get(listIndex)).intValue() >+ - prevProgress.alreadyInsertedLength; >+ listIndex++; >+ } >+ progressInfo.lastInsertedIndex = listIndex - 1; >+ progressInfo.alreadyInsertedLength = prevProgress.alreadyInsertedLength + splitLength; >+ return splitLength; >+ } >+ >+ /** >+ * Places on the current page all of the out-of-line objects not yet inserted. >+ */ >+ public void insertAll() { >+ progressInfo.alreadyInsertedLength = getTotalLength(); >+ progressInfo.lastInsertedIndex = knuthSequences.size() - 1; >+ progressInfo.lastElementOfLastInsertedIndex >+ = ((List) knuthSequences.get(progressInfo.lastInsertedIndex)).size() - 1; >+ } >+ >+ /** >+ * When restarting the algorithm from a given point, reset the informations about >+ * out-of-line objects to the values at that point. >+ * @param elementLists out-of-line sequences which are met after the restarting point, >+ * and thus must be removed from the list of already encoutered objects. >+ */ >+ public void reset(List elementLists) { >+ for (int i = 0; i < elementLists.size(); i++) { >+ knuthSequences.remove(knuthSequences.size() - 1); >+ cumulativeLengths.remove(cumulativeLengths.size() - 1); >+ } >+ } >+ >+ /** >+ * When the whole normal flow has been typeset and there are still footnotes to be >+ * placed, creates as many pages as necessary to place them. >+ */ >+ public void createFootnotePages(KnuthPageNode lastNode, PageBreakingAlgorithm algo, int lineWidth) { >+ progressInfo.alreadyInsertedLength = lastNode.footnotesProgress.getAlreadyInsertedLength(); >+ progressInfo.lastInsertedIndex = lastNode.footnotesProgress.getLastInsertedIndex(); >+ progressInfo.lastElementOfLastInsertedIndex = lastNode.footnotesProgress.getLastElementOfLastInsertedIndex(); >+ int availableBPD = lineWidth; >+ int split = 0; >+ KnuthPageNode prevNode = lastNode; >+ >+ // create pages containing the remaining footnote bodies >+ while (progressInfo.alreadyInsertedLength < getTotalLength()) { >+ // try adding some more content >+ if (((Integer) cumulativeLengths.get(progressInfo.lastInsertedIndex)).intValue() - progressInfo.alreadyInsertedLength >+ <= availableBPD) { >+ // add a whole footnote >+ availableBPD -= ((Integer) cumulativeLengths.get(progressInfo.lastInsertedIndex)).intValue() >+ - progressInfo.alreadyInsertedLength; >+ progressInfo.alreadyInsertedLength = ((Integer)cumulativeLengths.get(progressInfo.lastInsertedIndex)).intValue(); >+ progressInfo.lastElementOfLastInsertedIndex >+ = ((LinkedList)knuthSequences.get(progressInfo.lastInsertedIndex)).size() - 1; >+ } else if ((split = getFootnoteSplit(progressInfo, availableBPD, true)) >+ > 0) { >+ // add a piece of a footnote >+ availableBPD -= split; >+ // footnoteListIndex has already been set in getFootnoteSplit() >+ // footnoteElementIndex has already been set in getFootnoteSplit() >+ } else { >+ // cannot add any content: create a new node and start again >+ KnuthPageNode node = (KnuthPageNode) >+ algo.createNode(lastNode.position, prevNode.line + 1, 1, >+ progressInfo.alreadyInsertedLength - prevNode.footnotesProgress.getAlreadyInsertedLength(), >+ 0, 0, >+ 0, 0, 0, >+ 0, 0, prevNode); >+ algo.addNode(node.line, node); >+ algo.removeNode(prevNode.line, prevNode); >+ >+ prevNode = node; >+ availableBPD = lineWidth; >+ } >+ } >+ // create the last node >+ KnuthPageNode node = (KnuthPageNode) >+ algo.createNode(lastNode.position, prevNode.line + 1, 1, >+ getTotalLength() - prevNode.footnotesProgress.getAlreadyInsertedLength(), 0, 0, >+ 0, 0, 0, >+ 0, 0, prevNode); >+ algo.addNode(node.line, node); >+ algo.removeNode(prevNode.line, prevNode); >+ } >+ >+ /* TODO vh: won't work when there are also footnotes. To be merged with createFootnotePages */ >+ public void createFloatPages(KnuthPageNode lastNode, PageBreakingAlgorithm algo, int lineWidth) { >+ progressInfo.alreadyInsertedLength = lastNode.floatsProgress.getAlreadyInsertedLength(); >+ progressInfo.lastInsertedIndex = lastNode.floatsProgress.getLastInsertedIndex(); >+ int availableBPD = lineWidth; >+ KnuthPageNode prevNode = lastNode; >+ >+ // create pages containing the remaining float bodies >+ while (progressInfo.alreadyInsertedLength < getTotalLength()) { >+ // try adding some more content >+ if (((Integer) cumulativeLengths.get(progressInfo.lastInsertedIndex + 1)).intValue() - progressInfo.alreadyInsertedLength >+ <= availableBPD) { >+ // add a whole float >+ progressInfo.lastInsertedIndex++; >+ availableBPD -= ((Integer) cumulativeLengths.get(progressInfo.lastInsertedIndex)).intValue() >+ - progressInfo.alreadyInsertedLength; >+ progressInfo.alreadyInsertedLength = ((Integer)cumulativeLengths.get(progressInfo.lastInsertedIndex)).intValue(); >+ } else { >+ // cannot add any content: create a new node and start again >+ KnuthPageNode node = (KnuthPageNode) >+ algo.createNode(lastNode.position, prevNode.line + 1, 1, >+ progressInfo.alreadyInsertedLength - prevNode.floatsProgress.getAlreadyInsertedLength(), >+ 0, 0, >+ 0, 0, 0, >+ 0, prevNode.totalDemerits + (progressInfo.lastInsertedIndex - prevNode.floatsProgress.lastInsertedIndex) * 10000, prevNode); >+ algo.addNode(node.line, node); >+ algo.removeNode(prevNode.line, prevNode); >+ >+ prevNode = node; >+ availableBPD = lineWidth; >+ } >+ } >+ // create the last node >+ KnuthPageNode node = (KnuthPageNode) >+ algo.createNode(lastNode.position, prevNode.line + 1, 1, >+ getTotalLength() - prevNode.floatsProgress.getAlreadyInsertedLength(), 0, 0, >+ 0, 0, 0, >+ 0, prevNode.totalDemerits + (progressInfo.lastInsertedIndex - prevNode.floatsProgress.lastInsertedIndex) * 10000, prevNode); >+ algo.addNode(node.line, node); >+ algo.removeNode(prevNode.line, prevNode); >+ } >+} >Index: src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java (copie de travail) >@@ -36,7 +36,7 @@ > super(body); > } > >- /** @see org.apache.fop.layoutmgr.LayoutManager */ >+ /** @see org.apache.fop.layoutmgr.LayoutManager#addAreas(PositionIterator, LayoutContext) */ > public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { > LayoutManager childLM = null; > LayoutManager lastLM = null; >Index: src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/BalancingColumnBreakingAlgorithm.java (copie de travail) >@@ -38,10 +38,11 @@ > PageSequenceLayoutManager.PageProvider pageProvider, > int alignment, int alignmentLast, > MinOptMax footnoteSeparatorLength, >+ MinOptMax floatSeparatorLength, > boolean partOverflowRecovery, > int columnCount) { > super(topLevelLM, pageProvider, alignment, alignmentLast, >- footnoteSeparatorLength, partOverflowRecovery, false, false); >+ footnoteSeparatorLength, floatSeparatorLength, partOverflowRecovery, false, false); > this.columnCount = columnCount; > this.considerTooShort = true; //This is important! > } >Index: src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java (copie de travail) >@@ -185,7 +185,8 @@ > * @see org.apache.fop.layoutmgr.LayoutManager#addChildArea(Area) > */ > public void addChildArea(Area childArea) { >- if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator")) { >+ if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator") >+ || getStaticContentFO().getFlowName().equals("xsl-before-float-separator")) { > targetBlock.addBlock((Block)childArea); > } else { > targetRegion.addBlock((Block)childArea); >@@ -196,7 +197,8 @@ > * @see org.apache.fop.layoutmgr.LayoutManager#getParentArea(Area) > */ > public Area getParentArea(Area childArea) { >- if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator")) { >+ if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator") >+ || getStaticContentFO().getFlowName().equals("xsl-before-float-separator")) { > return targetBlock; > } else { > return targetRegion; >@@ -213,7 +215,8 @@ > boolean autoHeight = false; > StaticContentBreaker breaker; > >- if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator")) { >+ if (getStaticContentFO().getFlowName().equals("xsl-footnote-separator") >+ || getStaticContentFO().getFlowName().equals("xsl-before-float-separator")) { > targetIPD = targetBlock.getIPD(); > targetBPD = targetBlock.getBPD(); > if (targetBPD == 0) { >Index: src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java (copie de travail) >@@ -33,9 +33,20 @@ > * it isn't possible to get the opt value stored in a MinOptMax object. > */ > private int bpd; >- private LinkedList footnoteList; >- /** List of Knuth elements. This is a list of LinkedList elements. */ >- private LinkedList elementLists = null; >+ /** FootnoteBodyLayoutManagers corresponding to the footnotes cited on this line. */ >+ private LinkedList footnoteLMList; >+ /** FloatBodyLayoutManagers corresponding to the floats cited on this line. */ >+ private LinkedList floatLMList; >+ /** >+ * The Knuth sequences corresponding to the footnotes cited on this line. This is a List >+ * of List of KnuthElement objects. >+ */ >+ private LinkedList footnoteElementLists = null; >+ /** >+ * The Knuth sequences corresponding to the floats cited on this line. This is a List >+ * of List of KnuthElement objects. >+ */ >+ private LinkedList floatElementLists = null; > > /** > * Creates a new box. >@@ -49,59 +60,99 @@ > super(w, pos, bAux); > ipdRange = (MinOptMax) range.clone(); > bpd = bpdim; >- footnoteList = new LinkedList(); >+ footnoteLMList = new LinkedList(); >+ floatLMList = new LinkedList(); > } > > /** > * Creates a new box. > * @param w block progression dimension of this box >- * @param list footnotes cited by elements in this box. The list contains the >- * corresponding FootnoteBodyLayoutManagers >+ * @param footnoteLMList footnotes cited by elements in this box. The list contains >+ * the corresponding FootnoteBodyLayoutManagers >+ * @param floatLMList floats cited by elements in this box. The list contains the >+ * corresponding FloatBodyLayoutManagers > * @param pos the Position stored in this box > * @param bAux is this box auxiliary? > */ >- public KnuthBlockBox(int w, LinkedList list, Position pos, boolean bAux) { >+ public KnuthBlockBox(int w, >+ LinkedList footnoteLMList, >+ LinkedList floatLMList, >+ Position pos, >+ boolean bAux) { > super(w, pos, bAux); > ipdRange = new MinOptMax(0); > bpd = 0; >- footnoteList = new LinkedList(list); >+ this.footnoteLMList = new LinkedList(footnoteLMList); >+ this.floatLMList = new LinkedList(floatLMList); > } > > /** > * @return the LMs for the footnotes cited in this box. > */ > public LinkedList getFootnoteBodyLMs() { >- return footnoteList; >+ return footnoteLMList; > } > > /** >+ * @return the LMs for the floats cited in this box. >+ */ >+ public LinkedList getFloatBodyLMs() { >+ return floatLMList; >+ } >+ >+ /** > * @return true if this box contains footnote citations. > */ >- public boolean hasAnchors() { >- return (footnoteList.size() > 0); >+ public boolean hasFootnoteAnchors() { >+ return (footnoteLMList.size() > 0); > } > > /** >- * Adds the given list of Knuth elements to this box' list of elements. >- * @param list elements corresponding to a footnote body >+ * @return true if this box contains float citations. > */ >- public void addElementList(LinkedList list) { >- if (elementLists == null) { >- elementLists = new LinkedList(); >+ public boolean hasFloatAnchors() { >+ return (floatLMList.size() > 0); >+ } >+ >+ /** >+ * Adds a footnote to this box's list of footnotes. >+ * @param list KnuthElement instances corresponding to the footnote body >+ */ >+ public void addFootnoteElementList(LinkedList list) { >+ if (footnoteElementLists == null) { >+ footnoteElementLists = new LinkedList(); > } >- elementLists.add(list); >+ footnoteElementLists.add(list); > } > > /** >- * Returns the list of Knuth sequences registered by this box. >- * @return a list of KnuthElement sequences corresponding to footnotes cited in this >- * box >+ * Returns the list of footnotes cited by this box. >+ * @return a list of KnuthElement sequences corresponding to the footnote bodies > */ >- public LinkedList getElementLists() { >- return elementLists; >+ public LinkedList getFootnoteElementLists() { >+ return footnoteElementLists; > } > > /** >+ * Adds a float to this box's list of floats. >+ * @param list KnuthElement instances corresponding to the float body >+ */ >+ public void addFloatElementList(LinkedList list) { >+ if (floatElementLists == null) { >+ floatElementLists = new LinkedList(); >+ } >+ floatElementLists.add(list); >+ } >+ >+ /** >+ * Returns the list of floats cited by this box. >+ * @return a list of KnuthElement sequences corresponding to the float bodies >+ */ >+ public LinkedList getFloatElementLists() { >+ return floatElementLists; >+ } >+ >+ /** > * @return the inline progression dimension of this box. > */ > public MinOptMax getIPDRange() { >Index: src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java (copie de travail) >@@ -27,6 +27,7 @@ > import org.apache.commons.logging.Log; > import org.apache.commons.logging.LogFactory; > >+import org.apache.fop.fo.Constants; > import org.apache.fop.fo.FONode; > import org.apache.fop.fo.FOText; > import org.apache.fop.fo.FObjMixed; >@@ -36,6 +37,7 @@ > import org.apache.fop.fo.flow.BlockContainer; > import org.apache.fop.fo.flow.Character; > import org.apache.fop.fo.flow.ExternalGraphic; >+import org.apache.fop.fo.flow.Float; > import org.apache.fop.fo.flow.Footnote; > import org.apache.fop.fo.flow.Inline; > import org.apache.fop.fo.flow.InlineLevel; >@@ -68,6 +70,7 @@ > import org.apache.fop.layoutmgr.inline.CharacterLayoutManager; > import org.apache.fop.layoutmgr.inline.ContentLayoutManager; > import org.apache.fop.layoutmgr.inline.ExternalGraphicLayoutManager; >+import org.apache.fop.layoutmgr.inline.FloatLayoutManager; > import org.apache.fop.layoutmgr.inline.FootnoteLayoutManager; > import org.apache.fop.layoutmgr.inline.ICLayoutManager; > import org.apache.fop.layoutmgr.inline.InlineLayoutManager; >@@ -108,6 +111,7 @@ > makers.put(BidiOverride.class, new BidiOverrideLayoutManagerMaker()); > makers.put(Inline.class, new InlineLayoutManagerMaker()); > makers.put(Footnote.class, new FootnodeLayoutManagerMaker()); >+ makers.put(Float.class, new FloatLayoutManagerMaker()); > makers.put(InlineContainer.class, > new InlineContainerLayoutManagerMaker()); > makers.put(BasicLink.class, new BasicLinkLayoutManagerMaker()); >@@ -268,6 +272,16 @@ > } > } > >+ public static class FloatLayoutManagerMaker extends Maker { >+ public void make(FONode node, List lms) { >+ if (((Float) node).getFloat() == Constants.EN_NONE) { >+ lms.add(new FloatBodyLayoutManager((Float) node)); >+ } else { >+ lms.add(new FloatLayoutManager((Float) node)); >+ } >+ } >+ } >+ > public static class FootnodeLayoutManagerMaker extends Maker { > public void make(FONode node, List lms) { > lms.add(new FootnoteLayoutManager((Footnote) node)); >Index: src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java (copie de travail) >@@ -18,9 +18,7 @@ > > package org.apache.fop.layoutmgr; > >-import java.util.ArrayList; > import java.util.LinkedList; >-import java.util.ListIterator; > > import org.apache.commons.logging.Log; > import org.apache.commons.logging.LogFactory; >@@ -28,10 +26,11 @@ > import org.apache.fop.fo.FONode; > import org.apache.fop.fo.FObj; > import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition; >+import org.apache.fop.layoutmgr.breaking.OutOfLineRecord; > > import org.apache.fop.traits.MinOptMax; > >-class PageBreakingAlgorithm extends BreakingAlgorithm { >+public class PageBreakingAlgorithm extends BreakingAlgorithm { > > /** the logger for the class */ > protected static Log classLog = LogFactory.getLog(PageBreakingAlgorithm.class); >@@ -41,42 +40,14 @@ > /** List of PageBreakPosition elements. */ > private LinkedList pageBreaks = null; > >- /** Footnotes which are cited between the currently considered active node (previous >- * break) and the current considered break. Its type is >- * List<List<KnuthElement>>, it contains the sequences of KnuthElement >- * representing the footnotes bodies. >- */ >- private ArrayList footnotesList = null; >- /** Cumulated bpd of unhandled footnotes. */ >- private ArrayList lengthList = null; >- /** Length of all the footnotes which will be put on the current page. */ >- private int totalFootnotesLength = 0; >- /** >- * Length of all the footnotes which have already been inserted, up to the currently >- * considered element. That is, footnotes from the currently considered page plus >- * footnotes from its preceding pages. >- */ >- private int insertedFootnotesLength = 0; >- /** True if footnote citations have been met since the beginning of the page sequence. */ >- private boolean footnotesPending = false; >- /** >- * True if the elements met after the previous break point contain footnote citations. >- */ >- private boolean newFootnotes = false; >- /** >- * Index of the first footnote met after the previous break point. >- */ >- private int firstNewFootnoteIndex = 0; >- /** Index of the last footnote inserted on the current page. */ >- private int footnoteListIndex = 0; >- /** Index of the last element of the last footnote inserted on the current page. */ >- private int footnoteElementIndex = -1; >+ private OutOfLineRecord footnotes; >+ private OutOfLineRecord floats; > > // demerits for a page break that splits a footnote > private int splitFootnoteDemerits = 5000; > // demerits for a page break that defers a whole footnote to the following page > private int deferredFootnoteDemerits = 10000; >- private MinOptMax footnoteSeparatorLength = null; >+ private int deferredFloatDemerits = 10000; > > // the method noBreakBetween(int, int) uses these variables > // to store parameters and result of the last call, in order >@@ -94,7 +65,7 @@ > public PageBreakingAlgorithm(LayoutManager topLevelLM, > PageSequenceLayoutManager.PageProvider pageProvider, > int alignment, int alignmentLast, >- MinOptMax footnoteSeparatorLength, >+ MinOptMax footnoteSeparatorLength, MinOptMax floatSeparatorLength, > boolean partOverflowRecovery, boolean autoHeight, > boolean favorSinglePart) { > super(alignment, alignmentLast, true, partOverflowRecovery, 0); >@@ -102,7 +73,8 @@ > this.topLevelLM = topLevelLM; > this.pageProvider = pageProvider; > best = new BestPageRecords(); >- this.footnoteSeparatorLength = (MinOptMax) footnoteSeparatorLength.clone(); >+ footnotes = new OutOfLineRecord((MinOptMax) footnoteSeparatorLength.clone()); >+ floats = new OutOfLineRecord((MinOptMax) floatSeparatorLength.clone()); > // add some stretch, to avoid a restart for every page containing footnotes > if (footnoteSeparatorLength.min == footnoteSeparatorLength.max) { > footnoteSeparatorLength.max += 10000; >@@ -115,29 +87,23 @@ > * This class represents a feasible breaking point > * with extra information about footnotes. > */ >- protected class KnuthPageNode extends KnuthNode { >+ public class KnuthPageNode extends KnuthNode { > >- /** Additional length due to footnotes. */ >- public int totalFootnotes; >+ public OutOfLineRecord.ProgressInfo footnotesProgress; >+ public OutOfLineRecord.ProgressInfo floatsProgress; > >- /** Index of the last inserted footnote. */ >- public int footnoteListIndex; >- >- /** Index of the last inserted element of the last inserted footnote. */ >- public int footnoteElementIndex; >- > public KnuthPageNode(int position, int line, int fitness, > int totalWidth, int totalStretch, int totalShrink, >- int totalFootnotes, int footnoteListIndex, int footnoteElementIndex, >+ OutOfLineRecord.ProgressInfo footnotesProgress, >+ OutOfLineRecord.ProgressInfo floatsProgress, > double adjustRatio, int availableShrink, int availableStretch, > int difference, double totalDemerits, KnuthNode previous) { > super(position, line, fitness, > totalWidth, totalStretch, totalShrink, > adjustRatio, availableShrink, availableStretch, > difference, totalDemerits, previous); >- this.totalFootnotes = totalFootnotes; >- this.footnoteListIndex = footnoteListIndex; >- this.footnoteElementIndex = footnoteElementIndex; >+ this.footnotesProgress = footnotesProgress.copy(); >+ this.floatsProgress = floatsProgress.copy(); > } > > } >@@ -148,48 +114,55 @@ > */ > protected class BestPageRecords extends BestRecords { > >- private int[] bestFootnotesLength = new int[4]; >- private int[] bestFootnoteListIndex = new int[4]; >- private int[] bestFootnoteElementIndex = new int[4]; >- >+ private OutOfLineRecord.ProgressInfo[] bestFootnotesProgress >+ = new OutOfLineRecord.ProgressInfo[4]; >+ private OutOfLineRecord.ProgressInfo[] bestFloatsProgress >+ = new OutOfLineRecord.ProgressInfo[4]; >+ > public void addRecord(double demerits, KnuthNode node, double adjust, > int availableShrink, int availableStretch, > int difference, int fitness) { > super.addRecord(demerits, node, adjust, > availableShrink, availableStretch, > difference, fitness); >- bestFootnotesLength[fitness] = insertedFootnotesLength; >- bestFootnoteListIndex[fitness] = footnoteListIndex; >- bestFootnoteElementIndex[fitness] = footnoteElementIndex; >+ bestFootnotesProgress[fitness] = footnotes.getProgress().copy(); >+ bestFloatsProgress[fitness] = floats.getProgress().copy(); > } > > public int getFootnotesLength(int fitness) { >- return bestFootnotesLength[fitness]; >+ return bestFootnotesProgress[fitness].getAlreadyInsertedLength(); > } > > public int getFootnoteListIndex(int fitness) { >- return bestFootnoteListIndex[fitness]; >+ return bestFootnotesProgress[fitness].getLastInsertedIndex(); > } > > public int getFootnoteElementIndex(int fitness) { >- return bestFootnoteElementIndex[fitness]; >+ return bestFootnotesProgress[fitness].getLastElementOfLastInsertedIndex(); > } >+ >+ public OutOfLineRecord.ProgressInfo getFootnoteProgress(int fitness) { >+ return bestFootnotesProgress[fitness]; >+ } >+ >+ public OutOfLineRecord.ProgressInfo getFloatProgress(int fitness) { >+ return bestFloatsProgress[fitness]; >+ } > } > > protected void initialize() { > super.initialize(); >- insertedFootnotesLength = 0; >- footnoteListIndex = 0; >- footnoteElementIndex = -1; >+ footnotes.initialize(); >+ floats.initialize(); > } > >- protected KnuthNode createNode(int position, int line, int fitness, >+ public KnuthNode createNode(int position, int line, int fitness, > int totalWidth, int totalStretch, int totalShrink, > double adjustRatio, int availableShrink, int availableStretch, > int difference, double totalDemerits, KnuthNode previous) { > return new KnuthPageNode(position, line, fitness, > totalWidth, totalStretch, totalShrink, >- insertedFootnotesLength, footnoteListIndex, footnoteElementIndex, >+ footnotes.getProgress(), floats.getProgress(), > adjustRatio, availableShrink, availableStretch, > difference, totalDemerits, previous); > } >@@ -198,9 +171,8 @@ > int totalWidth, int totalStretch, int totalShrink) { > return new KnuthPageNode(position, line, fitness, > totalWidth, totalStretch, totalShrink, >- ((BestPageRecords) best).getFootnotesLength(fitness), >- ((BestPageRecords) best).getFootnoteListIndex(fitness), >- ((BestPageRecords) best).getFootnoteElementIndex(fitness), >+ ((BestPageRecords) best).getFootnoteProgress(fitness), >+ ((BestPageRecords) best).getFloatProgress(fitness), > best.getAdjust(fitness), best.getAvailableShrink(fitness), > best.getAvailableStretch(fitness), best.getDifference(fitness), > best.getDemerits(fitness), best.getNode(fitness)); >@@ -213,174 +185,171 @@ > */ > protected void handleBox(KnuthBox box) { > if (box instanceof KnuthBlockBox >- && ((KnuthBlockBox) box).hasAnchors()) { >- handleFootnotes(((KnuthBlockBox) box).getElementLists()); >- if (!newFootnotes) { >- newFootnotes = true; >- firstNewFootnoteIndex = footnotesList.size() - 1; >- } >+ && ((KnuthBlockBox) box).hasFootnoteAnchors()) { >+ footnotes.add(((KnuthBlockBox) box).getFootnoteElementLists()); > } >- } >- >- /** >- * Handles the footnotes cited inside a block-level box. Updates footnotesList and the >- * value of totalFootnotesLength with the lengths of the given footnotes. >- * @param elementLists list of KnuthElement sequences corresponding to the footnotes >- * bodies >- */ >- private void handleFootnotes(LinkedList elementLists) { >- // initialization >- if (!footnotesPending) { >- footnotesPending = true; >- footnotesList = new ArrayList(); >- lengthList = new ArrayList(); >- totalFootnotesLength = 0; >+ if (box instanceof KnuthBlockBox >+ && ((KnuthBlockBox) box).hasFloatAnchors()) { >+ floats.add(((KnuthBlockBox) box).getFloatElementLists()); > } >- if (!newFootnotes) { >- newFootnotes = true; >- firstNewFootnoteIndex = footnotesList.size(); >- } >- >- // compute the total length of the footnotes >- ListIterator elementListsIterator = elementLists.listIterator(); >- while (elementListsIterator.hasNext()) { >- LinkedList noteList = (LinkedList) elementListsIterator.next(); >- >- //Space resolution (Note: this does not respect possible stacking constraints >- //between footnotes!) >- SpaceResolver.resolveElementList(noteList); >- >- int noteLength = 0; >- footnotesList.add(noteList); >- ListIterator noteListIterator = noteList.listIterator(); >- while (noteListIterator.hasNext()) { >- KnuthElement element = (KnuthElement) noteListIterator.next(); >- if (element.isBox() || element.isGlue()) { >- noteLength += element.getW(); >- } >- } >- int prevLength = (lengthList.size() == 0 >- ? 0 >- : ((Integer) lengthList.get(lengthList.size() - 1)).intValue()); >- lengthList.add(new Integer(prevLength + noteLength)); >- totalFootnotesLength += noteLength; >- } > } > >+ > protected int restartFrom(KnuthNode restartingNode, int currentIndex) { > int returnValue = super.restartFrom(restartingNode, currentIndex); >- newFootnotes = false; >- if (footnotesPending) { >+ footnotes.resetNewSinceLastBreakpoint(); >+ floats.resetNewSinceLastBreakpoint(); >+ if (footnotes.existing() || floats.existing()) { > // remove from footnotesList the note lists that will be met > // after the restarting point > for (int j = currentIndex; j >= restartingNode.position; j--) { > KnuthElement resettedElement = getElement(j); > if (resettedElement instanceof KnuthBlockBox >- && ((KnuthBlockBox) resettedElement).hasAnchors()) { >- resetFootnotes(((KnuthBlockBox) resettedElement).getElementLists()); >+ && ((KnuthBlockBox) resettedElement).hasFootnoteAnchors()) { >+ footnotes.reset(((KnuthBlockBox) resettedElement).getFootnoteElementLists()); > } >+ if (resettedElement instanceof KnuthBlockBox >+ && ((KnuthBlockBox) resettedElement).hasFloatAnchors()) { >+ floats.reset(((KnuthBlockBox) resettedElement).getFloatElementLists());//TODO >+ } > } > } > return returnValue; > } > >- private void resetFootnotes(LinkedList elementLists) { >- for (int i = 0; i < elementLists.size(); i++) { >- LinkedList removedList = (LinkedList) footnotesList.remove(footnotesList.size() - 1); >- lengthList.remove(lengthList.size() - 1); >- >- // update totalFootnotesLength >- if (lengthList.size() > 0) { >- totalFootnotesLength = ((Integer) lengthList.get(lengthList.size() - 1)).intValue(); >- } else { >- totalFootnotesLength = 0; >- } >- } >- // update footnotesPending; >- if (footnotesList.size() == 0) { >- footnotesPending = false; >- } >- } >- > protected void considerLegalBreak(KnuthElement element, int elementIdx) { > super.considerLegalBreak(element, elementIdx); >- newFootnotes = false; >+ footnotes.resetNewSinceLastBreakpoint(); >+ floats.resetNewSinceLastBreakpoint(); > } > > protected int computeDifference(KnuthNode activeNode, KnuthElement element, > int elementIndex) { > KnuthPageNode pageNode = (KnuthPageNode) activeNode; > int actualWidth = totalWidth - pageNode.totalWidth; >- int footnoteSplit; >- boolean canDeferOldFootnotes; > if (element.isPenalty()) { > actualWidth += element.getW(); > } >- if (footnotesPending) { >+ if (footnotes.existing()) { >+ footnotes.setProgress(pageNode.footnotesProgress); > // compute the total length of the footnotes not yet inserted >- int allFootnotes = totalFootnotesLength - pageNode.totalFootnotes; >+ int allFootnotes = footnotes.getTotalLength() >+ - pageNode.footnotesProgress.getAlreadyInsertedLength(); > if (allFootnotes > 0) { > // this page contains some footnote citations > // add the footnote separator width >- actualWidth += footnoteSeparatorLength.opt; >+ actualWidth += footnotes.getSeparatorLength().opt; > if (actualWidth + allFootnotes <= getLineWidth()) { > // there is enough space to insert all footnotes: > // add the whole allFootnotes length > actualWidth += allFootnotes; >- insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes; >- footnoteListIndex = footnotesList.size() - 1; >- footnoteElementIndex = ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1; >- } else if (((canDeferOldFootnotes = checkCanDeferOldFootnotes(pageNode, elementIndex)) >- || newFootnotes) >- && (footnoteSplit = getFootnoteSplit(pageNode, getLineWidth() - actualWidth, >- canDeferOldFootnotes)) > 0) { >- // it is allowed to break or even defer footnotes if either: >- // - there are new footnotes in the last piece of content, and >- // there is space to add at least a piece of the first one >- // - or the previous page break deferred some footnote lines, and >- // 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; >- // footnoteListIndex has been set in getFootnoteSplit() >- // footnoteElementIndex has been set in getFootnoteSplit() >+ footnotes.insertAll(); > } else { >- // there is no space to add the smallest piece of footnote, >- // or we are trying to add a piece of content with no footnotes and >- // it does not fit in the page, because of previous footnote bodies >- // that cannot be broken: >- // add the whole allFootnotes length, so this breakpoint will be discarded >- actualWidth += allFootnotes; >- insertedFootnotesLength = pageNode.totalFootnotes + allFootnotes; >- footnoteListIndex = footnotesList.size() - 1; >- footnoteElementIndex = ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1; >+ boolean canDeferOldFootnotes = checkCanDeferOldOutOfLines(footnotes, >+ pageNode.position, elementIndex); >+ int footnoteSplit; >+ if ((canDeferOldFootnotes || footnotes.newSinceLastBreakpoint()) >+ && (footnoteSplit = footnotes.getFootnoteSplit( >+ pageNode.footnotesProgress, >+ getLineWidth() - actualWidth, canDeferOldFootnotes)) > 0) { >+ // it is allowed to break or even defer footnotes if either: >+ // - there are new footnotes in the last piece of content, and >+ // there is space to add at least a piece of the first one >+ // - or the previous page break deferred some footnote lines, and >+ // this is the first feasible break; in this case it is allowed >+ // to break and defer, if necessary, old and new footnotes >+ actualWidth += footnoteSplit; >+ } else { >+ // there is no space to add the smallest piece of footnote, >+ // or we are trying to add a piece of content with no footnotes and >+ // it does not fit in the page, because of previous footnote bodies >+ // that cannot be broken: >+ // add the whole allFootnotes length, so this breakpoint will be discarded >+ actualWidth += allFootnotes; >+ footnotes.insertAll(); >+ } > } >- } else { >- // all footnotes have already been placed on previous pages >+ } // else: all footnotes have already been placed on previous pages >+ } >+ if (floats.existing()) { >+ floats.setProgress(pageNode.floatsProgress); >+ // compute the total length of the floats not yet inserted >+ int allFloats = floats.getTotalLength() >+ - pageNode.floatsProgress.getAlreadyInsertedLength(); >+ if (allFloats > 0 >+ && getLineWidth() - actualWidth - floats.getSeparatorLength().opt > 0) { >+ // this page contains some float citations >+ // add the float separator width >+ int split = floats.getFloatSplit(pageNode.floatsProgress, >+ getLineWidth() - actualWidth - floats.getSeparatorLength().opt); >+ if (split > 0) { >+ actualWidth += floats.getSeparatorLength().opt + split; >+ } > } >- } else { >- // there are no footnotes > } >+ /* Another algorithm exactly mimicing the handling of footnotes: it should force >+ * more floats to be on the same page as their citations, at the price of more >+ * underfull pages (thus a higher total number of pages). If the current method >+ * works well enough, we may keep it. >+ */ >+// if (floats.existing()) { >+// floats.setProgress(pageNode.floatsProgress); >+// // compute the total length of the floats not yet inserted >+// int allFloats = floats.getTotalLength() >+// - pageNode.floatsProgress.getAlreadyInsertedLength(); >+// if (allFloats > 0) { >+// // this page contains some float citations >+// // add the float separator width >+// actualWidth += floats.getSeparatorLength().opt; >+// if (actualWidth + allFloats <= getLineWidth()) { >+// // there is enough space to insert all floats: >+// // add the whole allFloats length >+// actualWidth += allFloats; >+// floats.insertAll(); >+// } else { >+// boolean canDeferOldFloats = checkCanDeferOldOutOfLines(floats, >+// pageNode.position, elementIndex); >+// int floatSplit; >+// if ((canDeferOldFloats || floats.newSinceLastBreakpoint()) >+// && (floatSplit = floats.getFloatSplit( >+// pageNode.floatsProgress, >+// getLineWidth() - actualWidth)) > 0) { >+// actualWidth += floatSplit; >+// } else { >+// actualWidth += allFloats; >+// floats.insertAll(); >+// } >+// } >+// } // else: all floats have already been placed on previous pages >+// } > return getLineWidth(activeNode.line) - actualWidth; > } > >- /** Checks whether footnotes from preceding pages may be deferred to the page after >- * the given element. >- * @param node active node for the preceding page break >- * @param contentElementIndex index of the Knuth element considered for the >- * current page break >+ /** >+ * Checks whether out-of-line objects from preceding pages may be deferred >+ * to the page after the given element. >+ * >+ * @param outOfLine informations about the out-of-line objects >+ * @param activeNodePosition index in the Knuth sequence of the currently considered >+ * active node >+ * @param contentElementIndex index in the Knuth sequence of the currently considered >+ * legal breakpoint >+ * @return <code>true</code> if it is allowed to defer some out-of-line objects on >+ * following pages > */ >- private boolean checkCanDeferOldFootnotes(KnuthPageNode node, int contentElementIndex) { >- return (noBreakBetween(node.position, contentElementIndex) >- && deferredFootnotes(node.footnoteListIndex, node.footnoteElementIndex, node.totalFootnotes)); >+ private boolean checkCanDeferOldOutOfLines(OutOfLineRecord outOfLine, >+ int activeNodePosition, >+ int contentElementIndex) { >+ return (noBreakBetween(activeNodePosition, contentElementIndex) >+ && outOfLine.deferred()); > } > > /** >- * Returns true if there may be no breakpoint between the two given elements. >+ * Returns true if there is no legal breakpoint between the two given elements. > * @param prevBreakIndex index of the element from the currently considered active > * node > * @param breakIndex index of the currently considered breakpoint >- * @return true if no element between the two can be a breakpoint >+ * @return true if no element between the two is a legal breakpoint > */ > private boolean noBreakBetween(int prevBreakIndex, int breakIndex) { > // this method stores the parameters and the return value from previous calls >@@ -425,164 +394,18 @@ > return storedValue; > } > >- /** >- * Returns true if their are (pieces of) footnotes to be typeset on the current page. >- * @param listIndex index of the last inserted footnote for the currently considered >- * active node >- * @param elementIndex index of the last element of the last inserted footnote >- * @param length total length of all footnotes inserted so far >- */ >- private boolean deferredFootnotes(int listIndex, int elementIndex, int length) { >- return ((newFootnotes >- && firstNewFootnoteIndex != 0 >- && (listIndex < firstNewFootnoteIndex - 1 >- || elementIndex < ((LinkedList) footnotesList.get(listIndex)).size() - 1)) >- || length < totalFootnotesLength); >- } >- >- /** >- * Tries to split the flow of footnotes to put one part on the current page. >- * @param activeNode currently considered previous page break >- * @param availableLength available space for footnotes >- * @param canDeferOldFootnotes >- */ >- private int getFootnoteSplit(KnuthPageNode activeNode, int availableLength, boolean canDeferOldFootnotes) { >- return getFootnoteSplit(activeNode.footnoteListIndex, >- activeNode.footnoteElementIndex, >- activeNode.totalFootnotes, >- availableLength, canDeferOldFootnotes); >- } >- >- /** >- * Tries to split the flow of footnotes to put one part on the current page. >- * @param prevListIndex index of the last footnote on the previous page >- * @param prevElementIndex index of the last element of the last footnote >- * @param prevLength total length of footnotes inserted so far >- * @param availableLength available space for footnotes on this page >- * @param canDeferOldFootnotes >- */ >- private int getFootnoteSplit(int prevListIndex, int prevElementIndex, int prevLength, >- int availableLength, boolean canDeferOldFootnotes) { >- if (availableLength <= 0) { >- return 0; >- } else { >- // the split should contain a piece of the last footnote >- // together with all previous, not yet inserted footnotes; >- // but if this is not possible, try adding as much content as possible >- int splitLength = 0; >- ListIterator noteListIterator = null; >- KnuthElement element = null; >- boolean somethingAdded = false; >- >- // prevListIndex and prevElementIndex points to the last footnote element >- // already placed in a page: advance to the next element >- int listIndex = prevListIndex; >- int elementIndex = prevElementIndex; >- if (elementIndex == ((LinkedList) footnotesList.get(listIndex)).size() - 1) { >- listIndex++; >- elementIndex = 0; >- } else { >- elementIndex++; >- } >- >- // try adding whole notes >- if (footnotesList.size() - 1 > listIndex) { >- // add the previous footnotes: these cannot be broken or deferred >- if (!canDeferOldFootnotes >- && newFootnotes >- && firstNewFootnoteIndex > 0) { >- splitLength = ((Integer) lengthList.get(firstNewFootnoteIndex - 1)).intValue() >- - prevLength; >- listIndex = firstNewFootnoteIndex; >- elementIndex = 0; >- } >- // try adding the new footnotes >- while (((Integer) lengthList.get(listIndex)).intValue() - prevLength >- <= availableLength) { >- splitLength = ((Integer) lengthList.get(listIndex)).intValue() >- - prevLength; >- somethingAdded = true; >- listIndex++; >- elementIndex = 0; >- } >- // as this method is called only if it is not possible to insert >- // all footnotes, at this point listIndex and elementIndex points to >- // an existing element, the next one we will try to insert >- } >- >- // try adding a split of the next note >- noteListIterator = ((LinkedList) footnotesList.get(listIndex)).listIterator(elementIndex); >- >- int prevSplitLength = 0; >- int prevIndex = -1; >- int index = -1; >- >- while (!(somethingAdded && splitLength > availableLength)) { >- if (!somethingAdded) { >- somethingAdded = true; >- } else { >- prevSplitLength = splitLength; >- prevIndex = index; >- } >- // get a sub-sequence from the note element list >- boolean bPrevIsBox = false; >- while (noteListIterator.hasNext()) { >- // as this method is called only if it is not possible to insert >- // all footnotes, and we have already tried (and failed) to insert >- // this whole footnote, the while loop will never reach the end >- // of the note sequence >- element = (KnuthElement) noteListIterator.next(); >- if (element.isBox()) { >- // element is a box >- splitLength += element.getW(); >- bPrevIsBox = true; >- } else if (element.isGlue()) { >- // element is a glue >- if (bPrevIsBox) { >- // end of the sub-sequence >- index = noteListIterator.previousIndex(); >- break; >- } >- bPrevIsBox = false; >- splitLength += element.getW(); >- } else { >- // element is a penalty >- if (element.getP() < KnuthElement.INFINITE) { >- // end of the sub-sequence >- index = noteListIterator.previousIndex(); >- break; >- } >- } >- } >- } >- // if prevSplitLength is 0, this means that the available length isn't enough >- // to insert even the smallest split of the last footnote, so we cannot end a >- // page here >- // if prevSplitLength is > 0 we can insert some footnote content in this page >- // and insert the remaining in the following one >- if (!somethingAdded) { >- // there was not enough space to add a piece of the first new footnote >- // this is not a good break >- prevSplitLength = 0; >- } else if (prevSplitLength > 0) { >- // prevIndex is -1 if we have added only some whole footnotes >- footnoteListIndex = (prevIndex != -1) ? listIndex : listIndex - 1; >- footnoteElementIndex = (prevIndex != -1) >- ? prevIndex >- : ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1; >- } >- return prevSplitLength; >- } >- } >- > protected double computeAdjustmentRatio(KnuthNode activeNode, int difference) { > // compute the adjustment ratio > 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) { >- maxAdjustment += footnoteSeparatorLength.max - footnoteSeparatorLength.opt; >+ if (((KnuthPageNode) activeNode).footnotesProgress.getAlreadyInsertedLength() < footnotes.getTotalLength()) { >+ maxAdjustment += footnotes.getSeparatorLength().max - footnotes.getSeparatorLength().opt; > } >+ // add the float separator stretch if some float content will be added >+ if (((KnuthPageNode) activeNode).floatsProgress.getAlreadyInsertedLength() < floats.getTotalLength()) { >+ maxAdjustment += floats.getSeparatorLength().max - floats.getSeparatorLength().opt; >+ } > if (maxAdjustment > 0) { > return (double) difference / maxAdjustment; > } else { >@@ -591,9 +414,13 @@ > } 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) { >- maxAdjustment += footnoteSeparatorLength.opt - footnoteSeparatorLength.min; >+ if (((KnuthPageNode) activeNode).footnotesProgress.getAlreadyInsertedLength() < footnotes.getTotalLength()) { >+ maxAdjustment += footnotes.getSeparatorLength().opt - footnotes.getSeparatorLength().min; > } >+ // add the float separator shrink if some float content will be added >+ if (((KnuthPageNode) activeNode).floatsProgress.getAlreadyInsertedLength() < floats.getTotalLength()) { >+ maxAdjustment += floats.getSeparatorLength().opt - floats.getSeparatorLength().min; >+ } > if (maxAdjustment > 0) { > return (double) difference / maxAdjustment; > } else { >@@ -609,6 +436,19 @@ > double demerits = 0; > // compute demerits > double f = Math.abs(r); >+ /* If the adjustment ratio is too high, the demerits will be "almost infinite" >+ * (10^22). Adding demerits for a deferred float (10000) thus won't change the >+ * demerits value. We may end up with two breakpoints with the same demerits, >+ * whereas in one case there are deferred floats and not in the other case. The >+ * case with no deferred floats is still preferable, so we must have the >+ * possibility to distinguish it. By forcing f to 1 it becomes possible to make >+ * the difference when there are deferred floats. >+ * TODO vh: use threshold instead of 1 (currently threshold == 1 but it might be >+ * configurable) >+ */ >+ if (f > 1) { >+ f = 1; >+ } > f = 1 + 100 * f * f * f; > if (element.isPenalty() && element.getP() >= 0) { > f += element.getP(); >@@ -632,18 +472,15 @@ > demerits += incompatibleFitnessDemerit; > } > >- if (footnotesPending) { >- if (footnoteListIndex < footnotesList.size() - 1) { >- // add demerits for the deferred footnotes >- demerits += (footnotesList.size() - 1 - footnoteListIndex) >- * deferredFootnoteDemerits; >- } >- if (footnoteElementIndex >- < ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1) { >- // add demerits for the footnote split between pages >+ if (footnotes.existing()) { >+ demerits += footnotes.getNbOfDeferred() * deferredFootnoteDemerits; >+ if (footnotes.isSplit()) { > demerits += splitFootnoteDemerits; > } > } >+ if (floats.existing()) { >+ demerits += floats.getNbOfDeferred() * deferredFloatDemerits; >+ } > demerits += activeNode.totalDemerits; > return demerits; > } >@@ -653,66 +490,19 @@ > for (KnuthPageNode node = (KnuthPageNode) getNode(i); > node != null; > node = (KnuthPageNode) node.next) { >- if (node.totalFootnotes < totalFootnotesLength) { >+ if (node.footnotesProgress.getAlreadyInsertedLength() >+ < footnotes.getTotalLength()) { > // layout remaining footnote bodies >- createFootnotePages(node); >+ footnotes.createFootnotePages(node, this, getLineWidth()); > } >+ if (node.floatsProgress.getAlreadyInsertedLength() < floats.getTotalLength()) { >+ // layout remaining float bodies >+ floats.createFloatPages(node, this, getLineWidth()); >+ } > } > } > } > >- private void createFootnotePages(KnuthPageNode lastNode) { >- insertedFootnotesLength = lastNode.totalFootnotes; >- footnoteListIndex = lastNode.footnoteListIndex; >- footnoteElementIndex = lastNode.footnoteElementIndex; >- int availableBPD = getLineWidth(); >- int split = 0; >- KnuthPageNode prevNode = lastNode; >- >- // create pages containing the remaining footnote bodies >- while (insertedFootnotesLength < totalFootnotesLength) { >- // try adding some more content >- if (((Integer) lengthList.get(footnoteListIndex)).intValue() - insertedFootnotesLength >- <= availableBPD) { >- // add a whole footnote >- availableBPD -= ((Integer) lengthList.get(footnoteListIndex)).intValue() >- - insertedFootnotesLength; >- insertedFootnotesLength = ((Integer)lengthList.get(footnoteListIndex)).intValue(); >- footnoteElementIndex >- = ((LinkedList)footnotesList.get(footnoteListIndex)).size() - 1; >- } else if ((split = getFootnoteSplit(footnoteListIndex, footnoteElementIndex, >- insertedFootnotesLength, availableBPD, true)) >- > 0) { >- // add a piece of a footnote >- availableBPD -= split; >- insertedFootnotesLength += split; >- // footnoteListIndex has already been set in getFootnoteSplit() >- // footnoteElementIndex has already been set in getFootnoteSplit() >- } else { >- // cannot add any content: create a new node and start again >- KnuthPageNode node = (KnuthPageNode) >- createNode(lastNode.position, prevNode.line + 1, 1, >- insertedFootnotesLength - prevNode.totalFootnotes, >- 0, 0, >- 0, 0, 0, >- 0, 0, prevNode); >- addNode(node.line, node); >- removeNode(prevNode.line, prevNode); >- >- prevNode = node; >- availableBPD = getLineWidth(); >- } >- } >- // create the last node >- KnuthPageNode node = (KnuthPageNode) >- createNode(lastNode.position, prevNode.line + 1, 1, >- totalFootnotesLength - prevNode.totalFootnotes, 0, 0, >- 0, 0, 0, >- 0, 0, prevNode); >- addNode(node.line, node); >- removeNode(prevNode.line, prevNode); >- } >- > /** > * @return a list of PageBreakPosition elements > */ >@@ -781,16 +571,25 @@ > } > } > // 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 == ((LinkedList) footnotesList.get(firstListIndex)).size() - 1) { >+ int firstFootnoteListIndex = ((KnuthPageNode) bestActiveNode.previous). >+ footnotesProgress.getLastInsertedIndex(); >+ int firstFootnoteElementIndex = ((KnuthPageNode) bestActiveNode.previous). >+ footnotesProgress.getLastElementOfLastInsertedIndex(); >+ if (firstFootnoteListIndex == -1) { >+ firstFootnoteListIndex++; >+ firstFootnoteElementIndex = 0; >+ } else if (footnotes.getSequence(firstFootnoteListIndex) != null >+ && firstFootnoteElementIndex == ((LinkedList) footnotes. >+ getSequence(firstFootnoteListIndex)).size() - 1) { > // advance to the next list >- firstListIndex++; >- firstElementIndex = 0; >+ firstFootnoteListIndex++; >+ firstFootnoteElementIndex = 0; > } else { >- firstElementIndex++; >+ firstFootnoteElementIndex++; > } >+ // compute the indexes of the first float list >+ int firstFloatListIndex = ((KnuthPageNode) bestActiveNode.previous). >+ floatsProgress.getLastInsertedIndex() + 1; > > // add nodes at the beginning of the list, as they are found > // backwards, from the last one to the first one >@@ -800,9 +599,12 @@ > } > insertPageBreakAsFirst(new PageBreakPosition(this.topLevelLM, > bestActiveNode.position, >- firstListIndex, firstElementIndex, >- ((KnuthPageNode) bestActiveNode).footnoteListIndex, >- ((KnuthPageNode) bestActiveNode).footnoteElementIndex, >+ firstFootnoteListIndex, firstFootnoteElementIndex, >+ ((KnuthPageNode) bestActiveNode).footnotesProgress.getLastInsertedIndex(), >+ ((KnuthPageNode) bestActiveNode).footnotesProgress. >+ getLastElementOfLastInsertedIndex(), >+ firstFloatListIndex, >+ ((KnuthPageNode) bestActiveNode).floatsProgress.getLastInsertedIndex(), > ratio, difference)); > } > >@@ -829,9 +631,13 @@ > } > > public LinkedList getFootnoteList(int index) { >- return (LinkedList) footnotesList.get(index); >+ return (LinkedList) footnotes.getSequence(index); > } >- >+ >+ public LinkedList getFloatList(int index) { >+ return (LinkedList) floats.getSequence(index); >+ } >+ > /** @return the associated top-level formatting object. */ > public FObj getFObj() { > return topLevelLM.getFObj(); >Index: src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java (copie de travail) >@@ -26,6 +26,7 @@ > import org.apache.fop.area.AreaTreeHandler; > import org.apache.fop.area.AreaTreeModel; > import org.apache.fop.area.Block; >+import org.apache.fop.area.BeforeFloat; > import org.apache.fop.area.Footnote; > import org.apache.fop.area.PageViewport; > import org.apache.fop.area.LineArea; >@@ -88,7 +89,8 @@ > private int startPageNum = 0; > private int currentPageNum = 0; > >- private Block separatorArea = null; >+ private Block footnoteSeparatorArea = null; >+ private Block floatSeparatorArea = null; > > /** > * Constructor >@@ -179,6 +181,7 @@ > private boolean needColumnBalancing; > > private StaticContentLayoutManager footnoteSeparatorLM = null; >+ private StaticContentLayoutManager floatSeparatorLM = null; > > public PageBreaker(PageSequenceLayoutManager pslm) { > this.pslm = pslm; >@@ -241,38 +244,61 @@ > } > > // scan contentList, searching for footnotes >- boolean bFootnotesPresent = false; >+ boolean footnotesPresent = false; >+ boolean floatsPresent = false; > if (contentList != null) { > ListIterator contentListIterator = contentList.listIterator(); > while (contentListIterator.hasNext()) { > ListElement element = (ListElement) contentListIterator.next(); >- if (element instanceof KnuthBlockBox >- && ((KnuthBlockBox) element).hasAnchors()) { >- // element represents a line with footnote citations >- bFootnotesPresent = true; >- LayoutContext footnoteContext = new LayoutContext(context); >- footnoteContext.setStackLimit(context.getStackLimit()); >- footnoteContext.setRefIPD(getCurrentPV() >- .getRegionReference(Constants.FO_REGION_BODY).getIPD()); >- LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs(); >- ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator(); >- // store the lists of elements representing the footnote bodies >- // in the box representing the line containing their references >- while (footnoteBodyIterator.hasNext()) { >- FootnoteBodyLayoutManager fblm >- = (FootnoteBodyLayoutManager) footnoteBodyIterator.next(); >- fblm.setParent(childFLM); >- fblm.initialize(); >- ((KnuthBlockBox) element).addElementList( >- fblm.getNextKnuthElements(footnoteContext, alignment)); >+ if (element instanceof KnuthBlockBox) { >+ if (((KnuthBlockBox) element).hasFootnoteAnchors()) { >+ // element represents a line with footnote citations >+ footnotesPresent = true; >+ LayoutContext footnoteContext = new LayoutContext(context); >+ footnoteContext.setStackLimit(context.getStackLimit()); >+ footnoteContext.setRefIPD(getCurrentPV() >+ .getRegionReference(Constants.FO_REGION_BODY).getIPD()); >+ LinkedList footnoteBodyLMs >+ = ((KnuthBlockBox) element).getFootnoteBodyLMs(); >+ ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator(); >+ // store the lists of elements representing the footnote bodies >+ // in the box representing the line containing their references >+ while (footnoteBodyIterator.hasNext()) { >+ FootnoteBodyLayoutManager fblm >+ = (FootnoteBodyLayoutManager) footnoteBodyIterator.next(); >+ fblm.setParent(childFLM); >+ fblm.initialize(); >+ ((KnuthBlockBox) element).addFootnoteElementList( >+ fblm.getNextKnuthElements(footnoteContext, alignment)); >+ } > } >+ if (((KnuthBlockBox) element).hasFloatAnchors()) { >+ // element represents a line with float citations >+ floatsPresent = true; >+ LayoutContext floatContext = new LayoutContext(context); >+ floatContext.setStackLimit(context.getStackLimit()); >+ floatContext.setRefIPD(getCurrentPV() >+ .getRegionReference(Constants.FO_REGION_BODY).getIPD()); >+ LinkedList floatBodyLMs = ((KnuthBlockBox) element).getFloatBodyLMs(); >+ ListIterator floatBodyIterator = floatBodyLMs.listIterator(); >+ // store the lists of elements representing the footnote bodies >+ // in the box representing the line containing their references >+ while (floatBodyIterator.hasNext()) { >+ FloatBodyLayoutManager fblm >+ = (FloatBodyLayoutManager) floatBodyIterator.next(); >+ fblm.setParent(childFLM); >+ fblm.initialize(); >+ ((KnuthBlockBox) element).addFloatElementList( >+ fblm.getNextKnuthElements(floatContext, alignment)); >+ } >+ } > } > } > } > > // handle the footnote separator > StaticContent footnoteSeparator; >- if (bFootnotesPresent >+ if (footnotesPresent > && (footnoteSeparator = pageSeq.getStaticContent( > "xsl-footnote-separator")) != null) { > // the footnote separator can contain page-dependent content such as >@@ -283,17 +309,42 @@ > // always the same > > // create a Block area that will contain the separator areas >- separatorArea = new Block(); >- separatorArea.setIPD(pslm.getCurrentPV() >+ footnoteSeparatorArea = new Block(); >+ footnoteSeparatorArea.setIPD(pslm.getCurrentPV() > .getRegionReference(Constants.FO_REGION_BODY).getIPD()); > // create a StaticContentLM for the footnote separator > footnoteSeparatorLM = (StaticContentLayoutManager) > getLayoutManagerMaker().makeStaticContentLayoutManager( >- pslm, footnoteSeparator, separatorArea); >+ pslm, footnoteSeparator, footnoteSeparatorArea); > footnoteSeparatorLM.doLayout(); > >- footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD()); >+ footnoteSeparatorLength = new MinOptMax(footnoteSeparatorArea.getBPD()); > } >+ >+ // handle the float separator >+ StaticContent floatSeparator; >+ if (floatsPresent >+ && (floatSeparator = pageSeq.getStaticContent( >+ "xsl-before-float-separator")) != null) { >+ // the float 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 >+ floatSeparatorArea = new Block(); >+ floatSeparatorArea.setIPD(pslm.getCurrentPV() >+ .getRegionReference(Constants.FO_REGION_BODY).getIPD()); >+ // create a StaticContentLM for the float separator >+ floatSeparatorLM = (StaticContentLayoutManager) >+ getLayoutManagerMaker().makeStaticContentLayoutManager( >+ pslm, floatSeparator, floatSeparatorArea); >+ floatSeparatorLM.doLayout(); >+ >+ floatSeparatorLength = new MinOptMax(floatSeparatorArea.getBPD()); >+ } > return contentList; > } > >@@ -311,15 +362,28 @@ > StaticContent footnoteSeparator = pageSeq.getStaticContent( > "xsl-footnote-separator"); > // create a Block area that will contain the separator areas >- separatorArea = new Block(); >- separatorArea.setIPD( >+ footnoteSeparatorArea = new Block(); >+ footnoteSeparatorArea.setIPD( > getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD()); > // create a StaticContentLM for the footnote separator > footnoteSeparatorLM = (StaticContentLayoutManager) > getLayoutManagerMaker().makeStaticContentLayoutManager( >- pslm, footnoteSeparator, separatorArea); >+ pslm, footnoteSeparator, footnoteSeparatorArea); > footnoteSeparatorLM.doLayout(); > } >+ if (floatSeparatorLM != null) { >+ StaticContent floatSeparator = pageSeq.getStaticContent( >+ "xsl-before-float-separator"); >+ // create a Block area that will contain the separator areas >+ floatSeparatorArea = new Block(); >+ floatSeparatorArea.setIPD( >+ getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD()); >+ // create a StaticContentLM for the float separator >+ floatSeparatorLM = (StaticContentLayoutManager) >+ getLayoutManagerMaker().makeStaticContentLayoutManager( >+ pslm, floatSeparator, floatSeparatorArea); >+ floatSeparatorLM.doLayout(); >+ } > > childFLM.addAreas(posIter, context); > } >@@ -373,7 +437,7 @@ > getTopLevelLM(), > getPageProvider(), > alg.getAlignment(), alg.getAlignmentLast(), >- footnoteSeparatorLength, >+ footnoteSeparatorLength, floatSeparatorLength, > isPartOverflowRecoveryActivated(), false, false); > //alg.setConstantLineWidth(flowBPD); > int iOptPageCount = algRestart.findBreakingPoints(effectiveList, >@@ -432,7 +496,7 @@ > PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm( > getTopLevelLM(), > getPageProvider(), >- alignment, Constants.EN_START, footnoteSeparatorLength, >+ alignment, Constants.EN_START, footnoteSeparatorLength, floatSeparatorLength, > isPartOverflowRecoveryActivated(), > getCurrentPV().getBodyRegion().getColumnCount()); > //alg.setConstantLineWidth(flowBPD); >@@ -487,6 +551,26 @@ > } > > protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) { >+ // add float areas >+ if (pbp.floatFirstListIndex <= pbp.floatLastListIndex) { >+ // call addAreas() for each FloatBodyLM >+ for (int i = pbp.floatFirstListIndex; i <= pbp.floatLastListIndex; i++) { >+ LinkedList elementList = alg.getFloatList(i); >+ int firstIndex = 0; >+ int lastIndex = elementList.size() - 1; >+ >+ SpaceResolver.performConditionalsNotification(elementList, >+ firstIndex, lastIndex, -1); >+ LayoutContext childLC = new LayoutContext(0); >+ AreaAdditionUtil.addAreas(null, >+ new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1), >+ childLC); >+ } >+ // set the offset from the top margin >+ BeforeFloat parentArea >+ = (BeforeFloat) getCurrentPV().getBodyRegion().getBeforeFloat(); >+ parentArea.setSeparator(floatSeparatorArea); >+ } > // add footnote areas > if (pbp.footnoteFirstListIndex < pbp.footnoteLastListIndex > || pbp.footnoteFirstElementIndex <= pbp.footnoteLastElementIndex) { >@@ -507,12 +591,13 @@ > } > // set the offset from the top margin > Footnote parentArea = (Footnote) getCurrentPV().getBodyRegion().getFootnote(); >- int topOffset = (int) getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD(); >- if (separatorArea != null) { >- topOffset -= separatorArea.getBPD(); >+ int topOffset = (int) getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD() >+ - ((BeforeFloat) getCurrentPV().getBodyRegion().getBeforeFloat()).getBPD(); >+ if (footnoteSeparatorArea != null) { >+ topOffset -= footnoteSeparatorArea.getBPD(); > } > parentArea.setTop(topOffset); >- parentArea.setSeparator(separatorArea); >+ parentArea.setSeparator(footnoteSeparatorArea); > } > getCurrentPV().getCurrentSpan().notifyFlowsFinished(); > } >Index: src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java (copie de travail) >@@ -19,6 +19,7 @@ > package org.apache.fop.layoutmgr.inline; > > import org.apache.fop.layoutmgr.inline.AlignmentContext; >+import org.apache.fop.layoutmgr.FloatBodyLayoutManager; > import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager; > import org.apache.fop.layoutmgr.KnuthBox; > import org.apache.fop.layoutmgr.Position; >@@ -26,6 +27,7 @@ > public class KnuthInlineBox extends KnuthBox { > > private FootnoteBodyLayoutManager footnoteBodyLM = null; >+ private FloatBodyLayoutManager floatBodyLM = null; > private AlignmentContext alignmentContext = null; > > /** >@@ -63,16 +65,43 @@ > } > > /** >- * @return true if this box holds a reference to a FootnoteBodyLM >+ * @param fblm the FloatBodyLM this box must hold a reference to > */ >+ public void setFloatBodyLM(FloatBodyLayoutManager fblm) { >+ floatBodyLM = fblm; >+ } >+ >+ /** >+ * @return the FloatBodyLM this box holds a reference to >+ */ >+ public FloatBodyLayoutManager getFloatBodyLM() { >+ return floatBodyLM; >+ } >+ >+ /** >+ * @return true if this box holds a reference to an out-of-line object >+ */ > public boolean isAnchor() { >+ return (footnoteBodyLM != null || floatBodyLM != null); >+ } >+ >+ /** >+ * @return <code>true</code> if this box holds a reference to a footnote >+ */ >+ public boolean isFootnoteAnchor() { > return (footnoteBodyLM != null); > } >- >- >+ >+ /** >+ * @return <code>true</code> if this box holds a reference to a before-float >+ */ >+ public boolean isFloatAnchor() { >+ return (floatBodyLM != null); >+ } >+ > /** @see java.lang.Object#toString() */ > public String toString() { > StringBuffer sb = new StringBuffer(super.toString()); > return sb.toString(); > } >-} >\ No newline at end of file >+} >Index: src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (copie de travail) >@@ -1093,14 +1093,20 @@ > // create a list of the FootnoteBodyLM handling footnotes > // whose citations are in this line > LinkedList footnoteList = new LinkedList(); >+ LinkedList floatList = new LinkedList(); > ListIterator elementIterator = seq.listIterator(startIndex); > while (elementIterator.nextIndex() <= endIndex) { > KnuthElement element = (KnuthElement) elementIterator.next(); > if (element instanceof KnuthInlineBox > && ((KnuthInlineBox) element).isAnchor()) { >- footnoteList.add(((KnuthInlineBox) element).getFootnoteBodyLM()); >+ if (((KnuthInlineBox) element).isFootnoteAnchor()) { >+ footnoteList.add(((KnuthInlineBox) element).getFootnoteBodyLM()); >+ } else { >+ floatList.add(((KnuthInlineBox) element).getFloatBodyLM()); >+ } > } else if (element instanceof KnuthBlockBox) { > footnoteList.addAll(((KnuthBlockBox) element).getFootnoteBodyLMs()); >+ floatList.addAll(((KnuthBlockBox) element).getFloatBodyLMs()); > } > } > startIndex = endIndex + 1; >@@ -1108,7 +1114,7 @@ > = (LineBreakPosition) llPoss.getChosenPosition(i); > returnList.add(new KnuthBlockBox > (lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter, >- footnoteList, lbp, false)); >+ footnoteList, floatList, lbp, false)); > /* // add stretch and shrink to the returnlist > if (!seq.isInlineSequence() > && lbp.availableStretch != 0 || lbp.availableShrink != 0) { >Index: src/java/org/apache/fop/layoutmgr/inline/FloatLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/inline/FloatLayoutManager.java (révision 0) >+++ src/java/org/apache/fop/layoutmgr/inline/FloatLayoutManager.java (révision 0) >@@ -0,0 +1,125 @@ >+/* >+ * Copyright 1999-2005 The Apache Software Foundation. >+ * >+ * Licensed under the Apache License, Version 2.0 (the "License"); >+ * you may not use this file except in compliance with the License. >+ * You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.fop.layoutmgr.inline; >+ >+import java.util.LinkedList; >+import java.util.List; >+ >+import org.apache.fop.fo.flow.Float; >+import org.apache.fop.layoutmgr.AbstractLayoutManager; >+import org.apache.fop.layoutmgr.FloatBodyLayoutManager; >+import org.apache.fop.layoutmgr.InlineKnuthSequence; >+import org.apache.fop.layoutmgr.KnuthElement; >+import org.apache.fop.layoutmgr.KnuthSequence; >+import org.apache.fop.layoutmgr.LayoutContext; >+import org.apache.fop.layoutmgr.Position; >+ >+/** >+ * Layout manager for fo:float. >+ */ >+public class FloatLayoutManager extends AbstractLayoutManager >+ implements InlineLevelLayoutManager { >+ >+ private Float floatNode; >+ private FloatBodyLayoutManager bodyLM; >+ /** Represents the float citation **/ >+ private KnuthElement forcedAnchor; >+ >+ /** >+ * Create a new float layout manager. >+ * @param node float to create the layout manager for >+ */ >+ public FloatLayoutManager(Float node) { >+ super(node); >+ floatNode = node; >+ } >+ >+ /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */ >+ public void initialize() { >+ // create a FloatBodyLM handling the fo:float-body child of fo:float >+ bodyLM = new FloatBodyLayoutManager(floatNode); >+ } >+ >+ /** @see org.apache.fop.layoutmgr.LayoutManager */ >+ public LinkedList getNextKnuthElements(LayoutContext context, >+ int alignment) { >+ // this is the only method that must be implemented: >+ // all other methods will never be called, as the returned elements >+ // contain Positions created by the citationLM, so its methods will >+ // be called instead >+ >+ bodyLM.setParent(this); >+ bodyLM.initialize(); >+ >+ // get Knuth elements representing the float citation >+ LinkedList returnedList = new LinkedList(); >+ //Inline part of the float is empty. Need to send back an auxiliary >+ //zero-width, zero-height inline box so the float gets painted. >+ KnuthSequence seq = new InlineKnuthSequence(); >+ //Need to use an aux. box, otherwise, the line height can't be forced to zero height. >+ forcedAnchor = new KnuthInlineBox(0, null, null, true); >+ ((KnuthInlineBox) forcedAnchor).setFloatBodyLM(bodyLM); >+ seq.add(forcedAnchor); >+ returnedList.add(seq); >+ setFinished(true); >+ >+ return returnedList; >+ } >+ >+ /** @see org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager */ >+ public List addALetterSpaceTo(List oldList) { >+ log.warn("null implementation of addALetterSpaceTo() called!"); >+ return oldList; >+ } >+ >+ /** >+ * Remove the word space represented by the given elements >+ * >+ * @param oldList the elements representing the word space >+ */ >+ public void removeWordSpace(List oldList) { >+ // do nothing >+ log.warn(this.getClass().getName() + " should not receive a call to removeWordSpace(list)"); >+ } >+ >+ /** @see org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager */ >+ public void getWordChars(StringBuffer sbChars, Position pos) { >+ log.warn("null implementation of getWordChars() called!"); >+ } >+ >+ /** @see org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager */ >+ public void hyphenate(Position pos, HyphContext hc) { >+ log.warn("null implementation of hyphenate called!"); >+ } >+ >+ /** @see org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager */ >+ public boolean applyChanges(List oldList) { >+ log.warn("null implementation of applyChanges() called!"); >+ return false; >+ } >+ >+ /** >+ * @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(java.util.List, int) >+ */ >+ public LinkedList getChangedKnuthElements(List oldList, >+ int alignment) { >+ log.warn("null implementation of getChangeKnuthElement() called!"); >+ return null; >+ } >+} >Index: src/java/org/apache/fop/layoutmgr/AbstractBreaker.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/AbstractBreaker.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/AbstractBreaker.java (copie de travail) >@@ -42,17 +42,22 @@ > int footnoteFirstElementIndex; > int footnoteLastListIndex; > int footnoteLastElementIndex; >+ int floatFirstListIndex; >+ int floatLastListIndex; > > PageBreakPosition(LayoutManager lm, int iBreakIndex, >- int ffli, int ffei, int flli, int flei, >+ int fofli, int fofei, int folli, int folei, >+ int flfli, int fllli, > double bpdA, int diff) { > super(lm, iBreakIndex); > bpdAdjust = bpdA; > difference = diff; >- footnoteFirstListIndex = ffli; >- footnoteFirstElementIndex = ffei; >- footnoteLastListIndex = flli; >- footnoteLastElementIndex = flei; >+ footnoteFirstListIndex = fofli; >+ footnoteFirstElementIndex = fofei; >+ footnoteLastListIndex = folli; >+ footnoteLastElementIndex = folei; >+ floatFirstListIndex = flfli; >+ floatLastListIndex = fllli; > } > } > >@@ -162,6 +167,7 @@ > private int alignmentLast; > > protected MinOptMax footnoteSeparatorLength = new MinOptMax(0); >+ protected MinOptMax floatSeparatorLength = new MinOptMax(0); > > protected abstract int getCurrentDisplayAlign(); > protected abstract boolean hasMoreContent(); >@@ -310,7 +316,7 @@ > + "), flow BPD =" + flowBPD); > PageBreakingAlgorithm alg = new PageBreakingAlgorithm(getTopLevelLM(), > getPageProvider(), >- alignment, alignmentLast, footnoteSeparatorLength, >+ alignment, alignmentLast, footnoteSeparatorLength, floatSeparatorLength, > isPartOverflowRecoveryActivated(), autoHeight, isSinglePartFavored()); > int iOptPageCount; > >Index: src/java/org/apache/fop/layoutmgr/FloatBodyLayoutManager.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/FloatBodyLayoutManager.java (révision 0) >+++ src/java/org/apache/fop/layoutmgr/FloatBodyLayoutManager.java (révision 0) >@@ -0,0 +1,92 @@ >+/* >+ * Copyright 1999-2006 The Apache Software Foundation. >+ * >+ * Licensed under the Apache License, Version 2.0 (the "License"); >+ * you may not use this file except in compliance with the License. >+ * You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+/* $Id$ */ >+ >+package org.apache.fop.layoutmgr; >+ >+import java.util.LinkedList; >+ >+import org.apache.fop.area.Area; >+import org.apache.fop.fo.flow.Float; >+ >+/** >+ * LayoutManager for the out-of-line area generated by fo:float nodes. >+ * @see org.apache.fop.layoutmgr.inline.FloatLayoutManager >+ */ >+public class FloatBodyLayoutManager extends BlockStackingLayoutManager { >+ >+ public FloatBodyLayoutManager(Float node) { >+ super(node); >+ } >+ >+ /** @see org.apache.fop.layoutmgr.LayoutManager#addAreas(PositionIterator, LayoutContext) >+ * @deprecated */ >+ public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { >+ LayoutManager childLM = null; >+ LayoutManager lastLM = null; >+ LayoutContext lc = new LayoutContext(0); >+ >+ // "unwrap" the NonLeafPositions stored in parentIter >+ // and put them in a new list; >+ LinkedList positionList = new LinkedList(); >+ Position pos; >+ while (parentIter.hasNext()) { >+ pos = (Position) parentIter.next(); >+ //log.trace("pos = " + pos.getClass().getName() + "; " + pos); >+ Position innerPosition = pos; >+ if (pos instanceof NonLeafPosition) { >+ innerPosition = ((NonLeafPosition) pos).getPosition(); >+ if (innerPosition.getLM() == this) { >+ // pos was created by this LM and was inside a penalty >+ // allowing or forbidding a page break >+ // nothing to do >+ //log.trace(" penalty"); >+ } else { >+ // innerPosition was created by another LM >+ positionList.add(innerPosition); >+ lastLM = innerPosition.getLM(); >+ //log.trace(" " + innerPosition.getClass().getName()); >+ } >+ } >+ } >+ >+ // the Positions in positionList were inside the elements >+ // created by the LineLM >+ StackingIter childPosIter = new StackingIter(positionList.listIterator()); >+ >+ while ((childLM = childPosIter.getNextChildLM()) != null) { >+ // set last area flag >+ lc.setFlags(LayoutContext.LAST_AREA, >+ (layoutContext.isLastArea() && childLM == lastLM)); >+ // Add the line areas to Area >+ childLM.addAreas(childPosIter, lc); >+ } >+ } >+ >+ /** @see org.apache.fop.layoutmgr.LayoutManager#addChildArea(org.apache.fop.area.Area) */ >+ public void addChildArea(Area childArea) { >+ int floatProperty = ((Float) getFObj()).getFloat(); >+ if (floatProperty == EN_BEFORE) { >+ childArea.setAreaClass(Area.CLASS_BEFORE_FLOAT); >+ } else if (floatProperty == EN_START || floatProperty == EN_END) { >+ childArea.setAreaClass(Area.CLASS_SIDE_FLOAT); >+ } else { >+ childArea.setAreaClass(Area.CLASS_NORMAL); >+ } >+ parentLM.addChildArea(childArea); >+ } >+} >Index: src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java (copie de travail) >@@ -147,6 +147,7 @@ > // from prevBox to the new box > KnuthInlineBox newBox = (KnuthInlineBox) getLast(); > newBox.setFootnoteBodyLM(((KnuthInlineBox) prevBox).getFootnoteBodyLM()); >+ newBox.setFloatBodyLM(((KnuthInlineBox) prevBox).getFloatBodyLM()); > } > } > >Index: src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java >=================================================================== >--- src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java (révision 423415) >+++ src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java (copie de travail) >@@ -991,7 +991,7 @@ > * @param line number of the line ending at the node's corresponding breakpoint > * @param node the active node to add > */ >- protected void addNode(int line, KnuthNode node) { >+ public void addNode(int line, KnuthNode node) { > int headIdx = line * 2; > if (headIdx >= activeLines.length) { > KnuthNode[] oldList = activeLines; >@@ -1015,7 +1015,7 @@ > * @param line number of the line ending at the node's corresponding breakpoint > * @param node the node to deactivate > */ >- protected void removeNode(int line, KnuthNode node) { >+ public void removeNode(int line, KnuthNode node) { > int headIdx = line * 2; > KnuthNode n = getNode(line); > if (n != node) { >Index: src/java/org/apache/fop/fo/FONode.java >=================================================================== >--- src/java/org/apache/fop/fo/FONode.java (révision 423415) >+++ src/java/org/apache/fop/fo/FONode.java (copie de travail) >@@ -174,13 +174,14 @@ > > /** > * Checks to make sure, during SAX processing of input document, that the >- * incoming node is valid for the this (parent) node (e.g., checking to >+ * incoming node is a valid child of this node (e.g., checking to > * see that fo:table is not an immediate child of fo:root) > * called within FObj constructor > * @param loc location in the FO source file > * @param namespaceURI namespace of incoming node >- * @param localName (e.g. "table" for "fo:table") >- * @throws ValidationException if incoming node not valid for parent >+ * @param localName name of the incoming node (e.g. "table" for "fo:table") >+ * @throws ValidationException if incoming node is note a valid child of >+ * this node > */ > protected void validateChildNode(Locator loc, String namespaceURI, String localName) > throws ValidationException { >Index: src/java/org/apache/fop/fo/flow/Float.java >=================================================================== >--- src/java/org/apache/fop/fo/flow/Float.java (révision 423415) >+++ src/java/org/apache/fop/fo/flow/Float.java (copie de travail) >@@ -36,20 +36,23 @@ > private int clear; > // End of property values > >- static boolean notImplementedWarningGiven = false; > > /** > * @see org.apache.fop.fo.FONode#FONode(FONode) > */ > public Float(FONode parent) { > super(parent); >- >- if (!notImplementedWarningGiven) { >- getLogger().warn("fo:float is not yet implemented."); >- notImplementedWarningGiven = true; >- } > } > >+ >+ public int getClear() { >+ return clear; >+ } >+ >+ public int getFloat() { >+ return float_; >+ } >+ > /** > * @see org.apache.fop.fo.FObj#bind(PropertyList) > */ >Index: src/java/org/apache/fop/area/BeforeFloat.java >=================================================================== >--- src/java/org/apache/fop/area/BeforeFloat.java (révision 423415) >+++ src/java/org/apache/fop/area/BeforeFloat.java (copie de travail) >@@ -53,17 +53,22 @@ > * > * @return the height of the before float including separator > */ >- public int getBPD() { >- int h = super.getBPD(); >- if (separator != null) { >- h += separator.getBPD(); >- } >- return h; >- } >+// public int getBPD() { >+// int h = super.getBPD(); >+// if (separator != null) { >+// h += separator.getBPD(); >+// } >+// return h; >+// } > >- /** @see org.apache.fop.area.BlockParent#isEmpty() */ >- public boolean isEmpty() { >- return true; // before floats are not yet implemented >+ /** >+ * Add a block area as child to the footnote area >+ * >+ * @param child the block area. >+ */ >+ public void addBlock(Block child) { >+ addChildArea(child); >+ this.setBPD(this.getBPD() + child.getBPD()); > } > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 39777
:
18447
|
18456
|
18617
| 18637 |
18644
|
18666