You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by vh...@apache.org on 2006/11/13 10:39:22 UTC

svn commit: r474218 [4/5] - in /xmlgraphics/fop/branches/Temp_Floats: ./ src/documentation/content/xdocs/trunk/ src/foschema/ src/java-1.4/org/apache/fop/image/ src/java/org/apache/fop/fo/ src/java/org/apache/fop/fo/expr/ src/java/org/apache/fop/fo/flo...

Added: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/FootnotesRecord.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/FootnotesRecord.java?view=auto&rev=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/FootnotesRecord.java (added)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/FootnotesRecord.java Mon Nov 13 01:39:19 2006
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.fop.layoutmgr.PageBreakingAlgorithm;
+import org.apache.fop.layoutmgr.PageBreakingAlgorithm.KnuthPageNode;
+import org.apache.fop.traits.MinOptMax;
+
+/**
+ * A class that handles the placement of footnotes. Stores informations about
+ * existing footnotes, already placed ones, split footnotes, etc.
+ */
+public class FootnotesRecord extends OutOfLineRecord {
+
+    /**
+     * Progress informations for footnotes. When building pages, footnotes content will
+     * be put one unbreakable part at a time.
+     */
+    public class FootnotesProgress extends ProgressInfo {
+
+        /**
+         * Creates and initializes a new record.
+         */
+        public FootnotesProgress() {
+            super();
+        }
+
+        /**
+         * Creates a copy of the given record.
+         *
+         * @param footnotesProgress original progress information
+         */
+        public FootnotesProgress(FootnotesProgress footnotesProgress) {
+            super(footnotesProgress);
+        }
+
+        /**
+         * Checks whether there is some not yet typeset footnote content.
+         *
+         * @return <code>true</code> if the end of the footnote element list has not been
+         * reached yet
+         */
+        private boolean hasNext() {
+            return knuthSequences.size() > 0
+                    && (lastInsertedIndex < knuthSequences.size() - 1 || !endOfOutOfLine());
+        }
+
+        /**
+         * Insert footnote content on the current page up to the next legal break. This
+         * may be within a footnote or at the end of one.
+         */
+        private void next() {
+            if (lastInsertedIndex < 0 || endOfOutOfLine()) {
+                // Go to the next footnote
+                lastInsertedIndex++;
+                lastElementOfLastInsertedIndex = -1;
+                nbSplit = 1;
+            } else {  // We are still inside a footnote
+                nextInsideBreak();
+            }
+        }
+
+        /**
+         * If the last footnote of the previous page was split, places at least one more
+         * chunk of it on the current page. This would look very weird if the rest of a
+         * footnote split on one page would appear only two pages further. So this is
+         * necessary to put at least one chunk on the current page. If this leads to an
+         * unfeasible page, then the previous page will never appear in the optimal page
+         * layout anyway.
+         */
+        public void handleSplit() {
+            if (isLastSplit()) {
+                next();
+                addSeparator();
+            }
+        }
+
+        /**
+         * If the current page is a float-only page, handles the splitting of the last
+         * footnote of the previous page. Usually by adding at least a chunk of it on the
+         * current page, unless footnotes are not allowed on float-only pages (TODO this
+         * may lead to weird results (footnote continued only two pages further)).
+         *
+         * @param mode one of {@link PageBreakingAlgorithm#FLOAT_PAGE_MODE} or {@link
+         * PageBreakingAlgorithm#FLUSH_MODE}
+         * @param activeNodeRecorder
+         * @param normalContentProgress information about normal content already typeset
+         * @param beforeFloatsProgress information about before-floats already typeset
+         * @param previousNode node ending the previous page
+         */
+        public void handleSplit(int mode,
+                         PageBreakingAlgorithm.ActiveNodeRecorder activeNodeRecorder,
+                         PageBreakingAlgorithm.NormalContentProgressInfo normalContentProgress,
+                         BeforeFloatsRecord.BeforeFloatsProgress beforeFloatsProgress,
+                         KnuthPageNode previousNode) {
+            if (isLastSplit()) {
+                if (mode == PageBreakingAlgorithm.FLOAT_PAGE_MODE) {
+                    if (PageBreakingAlgorithm.FOOTNOTES_ALLOWED_ON_FLOAT_PAGES) {
+                        next();
+                        addSeparator();
+                        if (PageBreakingAlgorithm.FOOTNOTES_ONLY_PAGES_ALLOWED) {
+                            activeNodeRecorder.handleNode(mode, normalContentProgress,
+                                    this, beforeFloatsProgress, previousNode);
+                        }
+                    }
+                } else {  // mode == PageBreakingAlgorithm.FLUSH_MODE
+                    next();
+                    addSeparator();
+                    activeNodeRecorder.handleNode(mode, normalContentProgress,
+                            this, beforeFloatsProgress, previousNode);
+                }
+            }
+        }
+
+        /**
+         * Considers the placement of footnotes on the current page.
+         *
+         * @param mode one of {@link PageBreakingAlgorithm#NORMAL_MODE}, {@link
+         * PageBreakingAlgorithm#FLOAT_PAGE_MODE} or {@link
+         * PageBreakingAlgorithm#FLUSH_MODE}
+         * @param activeNodeRecorder
+         * @param normalContentProgress information about normal content already typeset
+         * @param beforeFloatsProgress information about before-floats already typeset
+         * @param previousNode node ending the previous page
+         */
+        public void consider(int mode,
+                             PageBreakingAlgorithm.ActiveNodeRecorder activeNodeRecorder,
+                             PageBreakingAlgorithm.NormalContentProgressInfo normalContentProgress,
+                             BeforeFloatsRecord.BeforeFloatsProgress beforeFloatsProgress,
+                             KnuthPageNode previousNode) {
+            beforeFloatsProgress.consider(mode, activeNodeRecorder,
+                    normalContentProgress, this, previousNode);
+            if (alreadyInserted.getLength() == 0) {
+                addSeparator();
+            }
+            switch (mode) {
+            case PageBreakingAlgorithm.NORMAL_MODE:
+                while (hasNext()) {
+                    next();
+                    if (!activeNodeRecorder.handleNode(mode, normalContentProgress,
+                            this, beforeFloatsProgress, previousNode)) {
+                        break;
+                    }
+                    beforeFloatsProgress.consider(mode, activeNodeRecorder,
+                            normalContentProgress, this, previousNode);
+                }
+                break;
+            case PageBreakingAlgorithm.FLOAT_PAGE_MODE:
+                if (PageBreakingAlgorithm.FOOTNOTES_ALLOWED_ON_FLOAT_PAGES) {
+                    while (hasNext()) {
+                        next();
+                        if (PageBreakingAlgorithm.FOOTNOTES_ONLY_PAGES_ALLOWED) {
+                            if (!activeNodeRecorder.handleNode(mode, normalContentProgress,
+                                    this, beforeFloatsProgress, previousNode)) {
+                                break;
+                            }
+                        }
+                        beforeFloatsProgress.consider(mode, activeNodeRecorder,
+                                normalContentProgress, this, previousNode);
+                    }
+                }
+                break;
+            case PageBreakingAlgorithm.FLUSH_MODE:
+                while (hasNext()) {
+                    next();
+                    if (!activeNodeRecorder.handleNode(mode, normalContentProgress,
+                            this, beforeFloatsProgress, previousNode)) {
+                        break;
+                    }
+                    beforeFloatsProgress.consider(mode, activeNodeRecorder,
+                            normalContentProgress, this, previousNode);
+                }
+                break;
+            }
+        }
+    }
+
+    /**
+     * Creates a new record for handling footnotes.
+     *
+     * @param footnoteSeparator dimensions of the separator between the normal content and
+     * the footnote area
+     */
+    public FootnotesRecord(MinOptMax footnoteSeparator) {
+        super(footnoteSeparator);
+    }
+}

Added: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/LineBreakPosition.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/LineBreakPosition.java?view=auto&rev=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/LineBreakPosition.java (added)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/LineBreakPosition.java Mon Nov 13 01:39:19 2006
@@ -0,0 +1,51 @@
+package org.apache.fop.layoutmgr.breaking;
+
+import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.LeafPosition;
+
+/**
+ * Private class to store information about inline breaks.
+ * Each value holds the start and end indexes into a List of
+ * inline break positions.
+ */
+public class LineBreakPosition extends LeafPosition {
+    /*
+     * TODO vh: fields temporarily made public to ease the moving of
+     * LineBreakPosition from a LineLayoutManager inner class to a top-level
+     * class.
+     */
+    public int iParIndex; // index of the Paragraph this Position refers to
+    public int iStartIndex; //index of the first element this Position refers to
+    public int availableShrink;
+    public int availableStretch;
+    public int difference;
+    public double dAdjust; // Percentage to adjust (stretch or shrink)
+    public double ipdAdjust; // Percentage to adjust (stretch or shrink)
+    public int startIndent;
+    public int lineHeight;
+    public int lineWidth;
+    public int spaceBefore;
+    public int spaceAfter;
+    public int baseline;
+
+    LineBreakPosition(LayoutManager lm, int index, int iStartIndex, int iBreakIndex,
+                      int shrink, int stretch, int diff,
+                      double ipdA, double adjust, int ind,
+                      int lh, int lw, int sb, int sa, int bl) {
+        super(lm, iBreakIndex);
+        availableShrink = shrink;
+        availableStretch = stretch;
+        difference = diff;
+        iParIndex = index;
+        this.iStartIndex = iStartIndex;
+        ipdAdjust = ipdA;
+        dAdjust = adjust;
+        startIndent = ind;
+        lineHeight = lh;
+        lineWidth = lw;
+        spaceBefore = sb;
+        spaceAfter = sa;
+        baseline = bl;
+    }
+    
+}
\ No newline at end of file

Added: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/LineBreakingAlgorithm.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/LineBreakingAlgorithm.java?view=auto&rev=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/LineBreakingAlgorithm.java (added)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/LineBreakingAlgorithm.java Mon Nov 13 01:39:19 2006
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ListIterator;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.flow.Block;
+import org.apache.fop.layoutmgr.BreakingAlgorithm;
+import org.apache.fop.layoutmgr.KnuthElement;
+import org.apache.fop.layoutmgr.KnuthSequence;
+import org.apache.fop.layoutmgr.inline.AlignmentContext;
+import org.apache.fop.layoutmgr.inline.KnuthInlineBox;
+import org.apache.fop.layoutmgr.inline.LineLayoutManager;
+import org.apache.fop.layoutmgr.inline.LineLayoutManager.Paragraph;
+
+public class LineBreakingAlgorithm extends BreakingAlgorithm {
+    private LineLayoutManager thisLLM;
+    private int pageAlignment;
+    private int activePossibility;
+    private int addedPositions;
+    private int textIndent;
+    private int fillerMinWidth;
+    private int lineHeight;
+    private int lead;
+    private int follow;
+//    private int maxDiff;
+    private static final double MAX_DEMERITS = 10e6;
+
+    public LineBreakingAlgorithm (int pageAlign,
+                                  int textAlign, int textAlignLast,
+                                  int indent, int fillerWidth,
+                                  int lh, int ld, int fl, boolean first,
+                                  int maxFlagCount, LineLayoutManager llm) {
+        super(textAlign, textAlignLast, first, false, maxFlagCount);
+        pageAlignment = pageAlign;
+        textIndent = indent;
+        fillerMinWidth = fillerWidth;
+        lineHeight = lh;
+        lead = ld;
+        follow = fl;
+        thisLLM = llm;
+        activePossibility = -1;
+//        maxDiff = fobj.getWidows() >= fobj.getOrphans() 
+//                ? fobj.getWidows()
+//                : fobj.getOrphans();
+    }
+
+    public void updateData1(int lineCount, double demerits) {
+        thisLLM.getLineLayouts().addPossibility(lineCount, demerits);
+        log.trace("Layout possibility in " + lineCount + " lines; break at position:");
+    }
+
+    public void updateData2(KnuthNode bestActiveNode,
+                            KnuthSequence par,
+                            int total) {
+        // compute indent and adjustment ratio, according to
+        // the value of text-align and text-align-last
+        int indent = 0;
+        int difference = bestActiveNode.difference;
+        int textAlign = (bestActiveNode.line < total) ? alignment : alignmentLast;
+        indent += (textAlign == Constants.EN_CENTER)
+                  ? difference / 2 : (textAlign == Constants.EN_END) ? difference : 0;
+        indent += (bestActiveNode.line == 1 && bFirst && thisLLM.isFirstInBlock()) ? textIndent : 0;
+        double ratio = (textAlign == Constants.EN_JUSTIFY
+            || difference < 0 && -difference <= bestActiveNode.availableShrink)
+                    ? bestActiveNode.adjustRatio : 0;
+
+        // add nodes at the beginning of the list, as they are found
+        // backwards, from the last one to the first one
+
+        // the first time this method is called, initialize activePossibility
+        if (activePossibility == -1) {
+            activePossibility = 0;
+            addedPositions = 0;
+        }
+
+        if (addedPositions == thisLLM.getLineLayouts().getLineCount(activePossibility)) {
+            activePossibility++;
+            addedPositions = 0;
+        }
+
+        if (difference + bestActiveNode.availableShrink < 0) {
+            if (log.isWarnEnabled()) {
+                log.warn(FONode.decorateWithContextInfo(
+                        "Line " + (addedPositions + 1) 
+                        + " of a paragraph overflows the available area.", thisLLM.getFObj()));
+            }
+        }
+        
+        //log.debug("LLM> (" + (thisLLM.getLineLayouts().getLineNumber(activePossibility) - addedPositions) 
+        //    + ") difference = " + difference + " ratio = " + ratio);
+        thisLLM.getLineLayouts().addBreakPosition(makeLineBreakPosition(par,
+               (bestActiveNode.line > 1 ? bestActiveNode.previous.position + 1 : 0),
+               bestActiveNode.position,
+               bestActiveNode.availableShrink - (addedPositions > 0 
+                   ? 0 : ((Paragraph)par).getLineFiller().opt - ((Paragraph)par).getLineFiller().min), 
+               bestActiveNode.availableStretch, 
+               difference, ratio, indent), activePossibility);
+        addedPositions++;
+    }
+
+    /* reset activePossibility, as if breakpoints have not yet been computed
+     */
+    public void resetAlgorithm() {
+        activePossibility = -1;
+    }
+
+    private LineBreakPosition makeLineBreakPosition(KnuthSequence par,
+                                                    int firstElementIndex,
+                                                    int lastElementIndex,
+                                                    int availableShrink, 
+                                                    int availableStretch, 
+                                                    int difference,
+                                                    double ratio,
+                                                    int indent) {
+        // line height calculation - spaceBefore may differ from spaceAfter
+        // by 1mpt due to rounding
+        int spaceBefore = (lineHeight - lead - follow) / 2;
+        int spaceAfter = lineHeight - lead - follow - spaceBefore;
+        // height before the main baseline
+        int lineLead = lead;
+        // maximum follow 
+        int lineFollow = follow;
+        // true if this line contains only zero-height, auxiliary boxes
+        // and the actual line width is 0; in this case, the line "collapses"
+        // i.e. the line area will have bpd = 0
+        boolean bZeroHeightLine = (difference == thisLLM.getLineWidth());
+
+        // if line-stacking-strategy is "font-height", the line height
+        // is not affected by its content
+        if (((Block) thisLLM.getFObj()).getLineStackingStrategy() != Constants.EN_FONT_HEIGHT) {
+            ListIterator inlineIterator
+                = par.listIterator(firstElementIndex);
+            AlignmentContext lastAC = null;
+            int maxIgnoredHeight = 0; // See spec 7.13
+            for (int j = firstElementIndex;
+                 j <= lastElementIndex;
+                 j++) {
+                KnuthElement element = (KnuthElement) inlineIterator.next();
+                if (element instanceof KnuthInlineBox ) {
+                    AlignmentContext ac = ((KnuthInlineBox) element).getAlignmentContext();
+                    if (ac != null && lastAC != ac) {
+                        if (!ac.usesInitialBaselineTable()
+                            || ac.getAlignmentBaselineIdentifier() != Constants.EN_BEFORE_EDGE
+                               && ac.getAlignmentBaselineIdentifier() != Constants.EN_AFTER_EDGE) {
+                            int alignmentOffset = ac.getTotalAlignmentBaselineOffset();
+                            if (alignmentOffset + ac.getAltitude() > lineLead) {
+                                lineLead = alignmentOffset + ac.getAltitude();
+                            }
+                            if (ac.getDepth() - alignmentOffset > lineFollow)  {
+                                lineFollow = ac.getDepth() - alignmentOffset;
+                            }
+                        } else {
+                            if (ac.getHeight() > maxIgnoredHeight) {
+                                maxIgnoredHeight = ac.getHeight();
+                            }
+                        }
+                        lastAC = ac;
+                    }
+                    if (bZeroHeightLine
+                        && (!element.isAuxiliary() || ac != null && ac.getHeight() > 0)) {
+                        bZeroHeightLine = false;
+                    }
+                }
+            }
+
+            if (lineFollow < maxIgnoredHeight - lineLead) {
+                lineFollow = maxIgnoredHeight - lineLead;
+            }
+        }
+
+        thisLLM.setConstantLineHeight(lineLead + lineFollow);
+
+        if (bZeroHeightLine) {
+            return new LineBreakPosition(thisLLM,
+                                         thisLLM.getKnuthParagraphs().indexOf(par),
+                                         firstElementIndex, lastElementIndex,
+                                         availableShrink, availableStretch,
+                                         difference, ratio, 0, indent,
+                                         0, thisLLM.getLineWidth(), 0, 0, 0);
+        } else {
+            return new LineBreakPosition(thisLLM,
+                                         thisLLM.getKnuthParagraphs().indexOf(par),
+                                         firstElementIndex, lastElementIndex,
+                                         availableShrink, availableStretch,
+                                         difference, ratio, 0, indent,
+                                         lineLead + lineFollow, 
+                                         thisLLM.getLineWidth(), spaceBefore, spaceAfter,
+                                         lineLead);
+        }
+    }
+
+    public int findBreakingPoints(Paragraph par, /*int lineWidth,*/
+                                  double threshold, boolean force,
+                                  int allowedBreaks) {
+        return super.findBreakingPoints(par, /*lineWidth,*/ 
+                threshold, force, allowedBreaks);
+    }
+
+    protected int filterActiveNodes() {
+        KnuthNode bestActiveNode = null;
+
+        if (pageAlignment == Constants.EN_JUSTIFY) {
+            // leave all active nodes and find the optimum line number
+            //log.debug("LBA.filterActiveNodes> " + activeNodeCount + " layouts");
+            for (int i = startLine; i < endLine; i++) {
+                for (KnuthNode node = getNode(i); node != null; node = node.next) {
+                    //log.debug("                       + lines = " + node.line + " demerits = " + node.totalDemerits);
+                    bestActiveNode = compareNodes(bestActiveNode, node);
+                }
+            }
+
+            // scan the node set once again and remove some nodes
+            //log.debug("LBA.filterActiveList> layout selection");
+            for (int i = startLine; i < endLine; i++) {
+                for (KnuthNode node = getNode(i); node != null; node = node.next) {
+                    //if (Math.abs(node.line - bestActiveNode.line) > maxDiff) {
+                    //if (false) {
+                    if (node.line != bestActiveNode.line
+                        && node.totalDemerits > MAX_DEMERITS) {
+                        //log.debug("                     XXX lines = " + node.line + " demerits = " + node.totalDemerits);
+                        deactivateNode(node);
+                    } else {
+                        //log.debug("                      ok lines = " + node.line + " demerits = " + node.totalDemerits);
+                    }
+                }
+            }
+        } else {
+            // leave only the active node with fewest total demerits
+            for (int i = startLine; i < endLine; i++) {
+                for (KnuthNode node = getNode(i); node != null; node = node.next) {
+                    bestActiveNode = compareNodes(bestActiveNode, node);
+                    if (node != bestActiveNode) {
+                        deactivateNode(node);
+                    }
+                }
+            }
+        }
+        return bestActiveNode.line;
+    }
+}
\ No newline at end of file

Modified: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/OutOfLineRecord.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/OutOfLineRecord.java?view=diff&rev=474218&r1=474217&r2=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/OutOfLineRecord.java (original)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/breaking/OutOfLineRecord.java Mon Nov 13 01:39:19 2006
@@ -20,295 +20,292 @@
 package org.apache.fop.layoutmgr.breaking;
 
 import java.util.ArrayList;
-import java.util.LinkedList;
+import java.util.Iterator;
 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.
+     * During page breaking, records which out-of-line objects have already been handled,
+     * and how much of them are placed on the current page.
      */
-    public static class ProgressInfo {
-
-        /** Cumulated BPD length of all out-of-line objects inserted so far. */
-        private int alreadyInsertedLength = 0;
+    class ProgressInfo {
 
         /** Index of the last inserted out-of-line object. */
-        private int lastInsertedIndex = -1;
+        int lastInsertedIndex;
 
         /**
          * 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.
+         * object.
          */
-        private int lastElementOfLastInsertedIndex = -1;
-        
+        int lastElementOfLastInsertedIndex;
+
         /**
-         * Initializes this record, as if no out-of-line object were handled yet.
+         * Amount of out-of-lines put on the current page.
          */
-        private void initialize() {
-            alreadyInsertedLength = 0;
-            lastInsertedIndex = -1;
-            lastElementOfLastInsertedIndex = -1;
+        ElasticLength alreadyInserted = new ElasticLength();
+
+        /**
+         * Number of times the last out-of-line is split. The initial value is 1, and is
+         * reset each time the end of an out-of-line is reached. The purpose is to compute
+         * additional demerits for split out-of-lines.
+         */
+        int nbSplit;
+
+        /**
+         * Creates and initializes a new record.
+         *
+         * @see OutOfLineRecord#initialize()
+         */
+        ProgressInfo() {
+            initialize();
         }
 
         /**
-         * @return a copy of this record
+         * Creates a copy of the given record.
+         *
+         * @param progressInfo original record
          */
-        public ProgressInfo copy() {
-            ProgressInfo info = new ProgressInfo();
-            info.alreadyInsertedLength = alreadyInsertedLength;
-            info.lastInsertedIndex = lastInsertedIndex;
-            info.lastElementOfLastInsertedIndex = lastElementOfLastInsertedIndex;
-            return info;
+        ProgressInfo(ProgressInfo progressInfo) {
+            this.lastInsertedIndex = progressInfo.lastInsertedIndex;
+            this.lastElementOfLastInsertedIndex = progressInfo.lastElementOfLastInsertedIndex;
+            this.alreadyInserted.set(progressInfo.alreadyInserted);
+            this.nbSplit = progressInfo.nbSplit;
         }
 
         /**
-         * Returns the cumulated length of all already typeset out-of-line objects.
-         * @return the total length in the block-progression-direction
+         * Returns the amount of out-of-lines inserted on the current page.
+         *
+         * @return the amount of out-of-lines inserted on the current page
          */
-        public int getAlreadyInsertedLength() {
-            return alreadyInsertedLength;
+        public ElasticLength getInserted() {
+            return alreadyInserted;
         }
 
         /**
-         * Returns the index of the last element of the last already typeset out-of-line
-         * object.
-         * @return the index of the last placed KnuthElement
+         * Returns the number of times the last out-of-line is split.
+         *
+         * @return the number of times the last out-of-line is split
+         */
+        public int getNbSplit() {
+            return nbSplit;
+        }
+
+        /**
+         * Returns the index of the last element of the last inserted out-of-line.
+         *
+         * @return the index of the last element of the last inserted out-of-line
          */
         public int getLastElementOfLastInsertedIndex() {
             return lastElementOfLastInsertedIndex;
         }
 
         /**
-         * @return the index of the last already typeset out-of-line object.
+         * Returns the index of the last inserted out-of-line.
+         *
+         * @return the index of the last inserted out-of-line
          */
         public int getLastInsertedIndex() {
             return lastInsertedIndex;
         }
 
-        public String toString() {
-            return "length=" + alreadyInsertedLength
-                    + ", index=" + lastInsertedIndex
-                    + ", elt=" + lastElementOfLastInsertedIndex;
+        /**
+         * Initializes this record such that no out-of-line has been inserted yet.
+         */
+        public void initialize() {
+            lastInsertedIndex = -1;
+            lastElementOfLastInsertedIndex = -1;
+            alreadyInserted.reset();
+            nbSplit = 1;
         }
-    }
-
-    /**
-     * 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;
+        /**
+         * Records progress status for out-of-lines up to the previous page.
+         *
+         * @param info progress informations for the previous page
+         */
+        public void setPrevious(ProgressInfo info) {
+            lastInsertedIndex = info.lastInsertedIndex;
+            lastElementOfLastInsertedIndex = info.lastElementOfLastInsertedIndex;
+            if (lastInsertedIndex >= 0) {
+                List lastOutOfLine = ((List) knuthSequences.get(lastInsertedIndex));
+                // If the last out-of-line was split, go just before the first next box
+                while (lastElementOfLastInsertedIndex < lastOutOfLine.size() - 2
+                        && !((KnuthElement) lastOutOfLine.get(lastElementOfLastInsertedIndex + 1)).isBox()) {
+                    lastElementOfLastInsertedIndex++;
+                }
+                if (lastElementOfLastInsertedIndex < lastOutOfLine.size() - 1) {
+                    // We haven't reached the end of the out-of-line yet
+                    nbSplit = info.nbSplit + 1;
+                } else {
+                    nbSplit = 1;
+                }
+            }
+            alreadyInserted.reset();
+        }
 
-    /**
-     * 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;
+        /**
+         * Checks whether there are still out-of-line objects to be placed.
+         *
+         * @return <code>true</code> if not all out-of-lines have been placed yet,
+         * otherwise <code>false</code>
+         */
+        public boolean remaining() {
+            return (lastInsertedIndex < knuthSequences.size() - 1) || isLastSplit();
+        }
 
-    /**
-     * Index of the first newly encountered out-of-line object since the last legal
-     * breakpoint.
-     * 
-     * @see OutOfLineRecord#knuthSequences
-     */
-    private int firstNewIndex = 0;
+        /**
+         * Returns the number of still to-be-placed out-of-lines.
+         * @return the number of not yet typeset out-of-line objects.
+         */
+        public int getNbOfDeferred() {
+            return knuthSequences.size() - 1 - lastInsertedIndex;
+        }
 
-    /**
-     * Dimension in the BPD of the separator between the out-of-line area and the main
-     * area.
-     */
-    private MinOptMax separatorLength = null;
+        /**
+         * Checks whether the end of the current out-of-line has been reached.
+         *
+         * @return <code>true</code> if the whole out-of-line has been placed, otherwise
+         * <code>false</code>
+         */
+        boolean endOfOutOfLine() {
+            return lastElementOfLastInsertedIndex
+                    >= ((List) knuthSequences.get(lastInsertedIndex)).size() - 1;
+        }
 
-    /**
-     * Record of already handled out-of-line objects.
-     * 
-     * @see ProgressInfo
-     */
-    private ProgressInfo progressInfo;
+        /**
+         * Checks whether the last out-of-line placed on the current page must be split or
+         * not.
+         *
+         * @return <code>true</code> if the last typeset out-of-line object must be split on
+         * several pages.
+         */
+        public boolean isLastSplit() {
+            return lastInsertedIndex >= 0 && !endOfOutOfLine();
+        }
 
-    public OutOfLineRecord(MinOptMax separatorLength) {
-        this.separatorLength = separatorLength;
-        this.progressInfo = new ProgressInfo();
-    }
+        /**
+         * Adds the dimensions of the separator between the out-of-line area and the main
+         * content to the amount of out-of-lines already placed on the current page.
+         */
+        public void addSeparator() {
+            alreadyInserted.add(separator);
+        }
 
-    /**
-     * 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();
-    }
+        /**
+         * Places on the current page out-of-line content up to the next legal break in the current
+         * out-of-line. This method is meant to be called by subclasses of this class, not
+         * by external classes even in the same package.
+         * <p><strong>Pre-condition:</strong> it is supposed that we are <em>inside</em>
+         * the out-of-line, and that we haven't reached its end yet.
+         */
+        void nextInsideBreak() {
+            List knuthSequence = (List) knuthSequences.get(lastInsertedIndex);
+            Iterator elementIter = knuthSequence.listIterator(lastElementOfLastInsertedIndex + 1);
+            boolean prevIsBox = false;
+            do {
+                lastElementOfLastInsertedIndex++;
+                KnuthElement element = (KnuthElement) elementIter.next();
+                if (element.isBox()) {
+                    alreadyInserted.add(0, element.getW(), 0);
+                    prevIsBox = true;
+                } else if (element.isGlue()) {
+                    if (prevIsBox) {
+                        break;
+                    }
+                    alreadyInserted.add(element.getZ(), element.getW(), element.getY());
+                    prevIsBox = false;
+                } else {
+                    if (element.getP() < KnuthElement.INFINITE) {
+                        alreadyInserted.add(0, element.getW(), 0);
+                        break;
+                    }
+                    prevIsBox = false;
+                }
+            } while (lastElementOfLastInsertedIndex < knuthSequence.size() - 1);
+            if (lastElementOfLastInsertedIndex == knuthSequence.size() - 1) {
+                nbSplit = 0;
+            }
+        }
 
-    /**
-     * @return the informations about already handled out-of-line objects
-     */
-    public ProgressInfo getProgress() {
-        return this.progressInfo;
+        public String toString() {
+            return "index=" + lastInsertedIndex
+                    + ", elt=" + lastElementOfLastInsertedIndex
+                    + ", inserted=" + alreadyInserted
+                    + ", splits=" + nbSplit;
+        }
     }
 
     /**
-     * @return the length in the BPD of the separator between the out-of-line area and the
-     * main area.
+     * Sequences of KnuthElement corresponding to already encountered out-of-line objects.
+     * This is a List of List of KnuthElement.
      */
-    public MinOptMax getSeparatorLength() {
-        return separatorLength;
-    }
+    List knuthSequences = new ArrayList();
 
     /**
-     * @return the total length of already encountered out-of-line objects
+     * Dimension in the BPD of the separator between the out-of-line area and the main
+     * area.
      */
-    public int getTotalLength() {
-        if (cumulativeLengths == null || cumulativeLengths.size() == 0) {
-            return 0;
-        } else {
-            return ((Integer) cumulativeLengths.get(cumulativeLengths.size() - 1)).intValue(); 
-        }
-    }
+    private ElasticLength separator = null;
 
     /**
-     * @return true if out-of-line objects have already been encountered (but not
-     * necessarily typeset yet)
+     * Creates a new record for a given type of out-of-lines.
+     *
+     * @param separator dimensions of the separator between the out-of-line area and the
+     * main area
      */
-    public boolean existing() {
-        return (knuthSequences != null && knuthSequences.size() > 0);
-    }
-
-    public void resetNewSinceLastBreakpoint() {
-        newSinceLastBreakpoint = false;
+    public OutOfLineRecord(MinOptMax separator) {
+        this.separator = new ElasticLength(separator.opt - separator.min,
+                                           separator.opt,
+                                           separator.max - separator.opt);
     }
 
     /**
-     * @return true if new out-of-line objects are cited in the sequence of Knuth
-     * elements since the last encountered legal breakpoint.
+     * Initializes this record, as if no out-of-line object were handled yet.
      */
-    public boolean newSinceLastBreakpoint() {
-        return newSinceLastBreakpoint;
+    public void initialize() {
+        knuthSequences = new ArrayList();
     }
 
     /**
      * Records one or more newly encountered out-of-line objects.
-     * @param elementLists the list of corresponding Knuth sequences
+     *
+     * @param elementLists the list of corresponding Knuth sequences. This is a
+     * List&lt;List&lt;KnuthElement&gt;&gt;.
      */
     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;
-    }
+            List knuthSequence = (List) elementListsIterator.next();
 
-    /* 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;
-//  }
+            // Space resolution (Note: this does not respect possible stacking constraints
+            // /between/ out-of-lines!)
+            SpaceResolver.resolveElementList(knuthSequence);
 
-    /**
-     * @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;
+            knuthSequences.add(knuthSequence);
+        }
     }
 
     /**
-     * @return <code>true</code> if the last typeset out-of-line object must be split on
-     * several pages.
+     * Returns <code>true</code> if out-of-lines have already been encountered.
+     *
+     * @return <code>true</code> if out-of-lines are recorded, possibly not yet typeset
      */
-    public boolean isSplit() {
-        return (progressInfo.lastElementOfLastInsertedIndex 
-                < ((LinkedList) knuthSequences.get(progressInfo.lastInsertedIndex)).size() - 1);
+    public boolean existing() {
+        return knuthSequences.size() > 0;
     }
 
     /**
@@ -318,284 +315,19 @@
      * 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;
-        }
+        return (List) knuthSequences.get(index);
     }
 
-    /**
-     * 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.
+     * and thus must be removed from the list of already encountered 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);
     }
 }

Modified: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java?view=diff&rev=474218&r1=474217&r2=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java Mon Nov 13 01:39:19 2006
@@ -47,6 +47,8 @@
 import org.apache.fop.layoutmgr.Position;
 import org.apache.fop.layoutmgr.PositionIterator;
 import org.apache.fop.layoutmgr.SpaceSpecifier;
+import org.apache.fop.layoutmgr.breaking.LineBreakPosition;
+import org.apache.fop.layoutmgr.breaking.LineBreakingAlgorithm;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.LineArea;
 import org.apache.fop.area.inline.InlineArea;
@@ -100,49 +102,6 @@
         }
     }
     
-    /**
-     * Private class to store information about inline breaks.
-     * Each value holds the start and end indexes into a List of
-     * inline break positions.
-     */
-    private static class LineBreakPosition extends LeafPosition {
-        private int iParIndex; // index of the Paragraph this Position refers to
-        private int iStartIndex; //index of the first element this Position refers to
-        private int availableShrink;
-        private int availableStretch;
-        private int difference;
-        private double dAdjust; // Percentage to adjust (stretch or shrink)
-        private double ipdAdjust; // Percentage to adjust (stretch or shrink)
-        private int startIndent;
-        private int lineHeight;
-        private int lineWidth;
-        private int spaceBefore;
-        private int spaceAfter;
-        private int baseline;
-
-        LineBreakPosition(LayoutManager lm, int index, int iStartIndex, int iBreakIndex,
-                          int shrink, int stretch, int diff,
-                          double ipdA, double adjust, int ind,
-                          int lh, int lw, int sb, int sa, int bl) {
-            super(lm, iBreakIndex);
-            availableShrink = shrink;
-            availableStretch = stretch;
-            difference = diff;
-            iParIndex = index;
-            this.iStartIndex = iStartIndex;
-            ipdAdjust = ipdA;
-            dAdjust = adjust;
-            startIndent = ind;
-            lineHeight = lh;
-            lineWidth = lw;
-            spaceBefore = sb;
-            spaceAfter = sa;
-            baseline = bl;
-        }
-        
-    }
-
-
     private int textAlignment = EN_JUSTIFY;
     private int textAlignmentLast;
     private int effectiveAlignment;
@@ -195,7 +154,7 @@
     }
 
     // this class represents a paragraph
-    private class Paragraph extends InlineKnuthSequence {
+    public class Paragraph extends InlineKnuthSequence {
         /** Number of elements to ignore at the beginning of the list. */ 
         private int ignoreAtStart = 0;
         /** Number of elements to ignore at the end of the list. */
@@ -221,6 +180,10 @@
             lastLineEndIndent = endIndent;
         }
 
+        public MinOptMax getLineFiller() {
+            return lineFiller;
+        }
+
         public void startParagraph(int lw) {
             lineWidth = lw;
             startSequence();
@@ -307,233 +270,6 @@
         }
     }
 
-    private class LineBreakingAlgorithm extends BreakingAlgorithm {
-        private LineLayoutManager thisLLM;
-        private int pageAlignment;
-        private int activePossibility;
-        private int addedPositions;
-        private int textIndent;
-        private int fillerMinWidth;
-        private int lineHeight;
-        private int lead;
-        private int follow;
-        private int maxDiff;
-        private static final double MAX_DEMERITS = 10e6;
-
-        public LineBreakingAlgorithm (int pageAlign,
-                                      int textAlign, int textAlignLast,
-                                      int indent, int fillerWidth,
-                                      int lh, int ld, int fl, boolean first,
-                                      int maxFlagCount, LineLayoutManager llm) {
-            super(textAlign, textAlignLast, first, false, maxFlagCount);
-            pageAlignment = pageAlign;
-            textIndent = indent;
-            fillerMinWidth = fillerWidth;
-            lineHeight = lh;
-            lead = ld;
-            follow = fl;
-            thisLLM = llm;
-            activePossibility = -1;
-            maxDiff = fobj.getWidows() >= fobj.getOrphans() 
-                    ? fobj.getWidows()
-                    : fobj.getOrphans();
-        }
-
-        public void updateData1(int lineCount, double demerits) {
-            lineLayouts.addPossibility(lineCount, demerits);
-            log.trace("Layout possibility in " + lineCount + " lines; break at position:");
-        }
-
-        public void updateData2(KnuthNode bestActiveNode,
-                                KnuthSequence par,
-                                int total) {
-            // compute indent and adjustment ratio, according to
-            // the value of text-align and text-align-last
-            int indent = 0;
-            int difference = bestActiveNode.difference;
-            int textAlign = (bestActiveNode.line < total) ? alignment : alignmentLast;
-            indent += (textAlign == Constants.EN_CENTER)
-                      ? difference / 2 : (textAlign == Constants.EN_END) ? difference : 0;
-            indent += (bestActiveNode.line == 1 && bFirst && isFirstInBlock) ? textIndent : 0;
-            double ratio = (textAlign == Constants.EN_JUSTIFY
-                || difference < 0 && -difference <= bestActiveNode.availableShrink)
-                        ? bestActiveNode.adjustRatio : 0;
-
-            // add nodes at the beginning of the list, as they are found
-            // backwards, from the last one to the first one
-
-            // the first time this method is called, initialize activePossibility
-            if (activePossibility == -1) {
-                activePossibility = 0;
-                addedPositions = 0;
-            }
-
-            if (addedPositions == lineLayouts.getLineCount(activePossibility)) {
-                activePossibility++;
-                addedPositions = 0;
-            }
-
-            if (difference + bestActiveNode.availableShrink < 0) {
-                if (log.isWarnEnabled()) {
-                    log.warn(FONode.decorateWithContextInfo(
-                            "Line " + (addedPositions + 1) 
-                            + " of a paragraph overflows the available area.", getFObj()));
-                }
-            }
-            
-            //log.debug("LLM> (" + (lineLayouts.getLineNumber(activePossibility) - addedPositions) 
-            //    + ") difference = " + difference + " ratio = " + ratio);
-            lineLayouts.addBreakPosition(makeLineBreakPosition(par,
-                   (bestActiveNode.line > 1 ? bestActiveNode.previous.position + 1 : 0),
-                   bestActiveNode.position,
-                   bestActiveNode.availableShrink - (addedPositions > 0 
-                       ? 0 : ((Paragraph)par).lineFiller.opt - ((Paragraph)par).lineFiller.min), 
-                   bestActiveNode.availableStretch, 
-                   difference, ratio, indent), activePossibility);
-            addedPositions++;
-        }
-
-        /* reset activePossibility, as if breakpoints have not yet been computed
-         */
-        public void resetAlgorithm() {
-            activePossibility = -1;
-        }
-
-        private LineBreakPosition makeLineBreakPosition(KnuthSequence par,
-                                                        int firstElementIndex,
-                                                        int lastElementIndex,
-                                                        int availableShrink, 
-                                                        int availableStretch, 
-                                                        int difference,
-                                                        double ratio,
-                                                        int indent) {
-            // line height calculation - spaceBefore may differ from spaceAfter
-            // by 1mpt due to rounding
-            int spaceBefore = (lineHeight - lead - follow) / 2;
-            int spaceAfter = lineHeight - lead - follow - spaceBefore;
-            // height before the main baseline
-            int lineLead = lead;
-            // maximum follow 
-            int lineFollow = follow;
-            // true if this line contains only zero-height, auxiliary boxes
-            // and the actual line width is 0; in this case, the line "collapses"
-            // i.e. the line area will have bpd = 0
-            boolean bZeroHeightLine = (difference == iLineWidth);
-
-            // if line-stacking-strategy is "font-height", the line height
-            // is not affected by its content
-            if (fobj.getLineStackingStrategy() != EN_FONT_HEIGHT) {
-                ListIterator inlineIterator
-                    = par.listIterator(firstElementIndex);
-                AlignmentContext lastAC = null;
-                int maxIgnoredHeight = 0; // See spec 7.13
-                for (int j = firstElementIndex;
-                     j <= lastElementIndex;
-                     j++) {
-                    KnuthElement element = (KnuthElement) inlineIterator.next();
-                    if (element instanceof KnuthInlineBox ) {
-                        AlignmentContext ac = ((KnuthInlineBox) element).getAlignmentContext();
-                        if (ac != null && lastAC != ac) {
-                            if (!ac.usesInitialBaselineTable()
-                                || ac.getAlignmentBaselineIdentifier() != EN_BEFORE_EDGE
-                                   && ac.getAlignmentBaselineIdentifier() != EN_AFTER_EDGE) {
-                                int alignmentOffset = ac.getTotalAlignmentBaselineOffset();
-                                if (alignmentOffset + ac.getAltitude() > lineLead) {
-                                    lineLead = alignmentOffset + ac.getAltitude();
-                                }
-                                if (ac.getDepth() - alignmentOffset > lineFollow)  {
-                                    lineFollow = ac.getDepth() - alignmentOffset;
-                                }
-                            } else {
-                                if (ac.getHeight() > maxIgnoredHeight) {
-                                    maxIgnoredHeight = ac.getHeight();
-                                }
-                            }
-                            lastAC = ac;
-                        }
-                        if (bZeroHeightLine
-                            && (!element.isAuxiliary() || ac != null && ac.getHeight() > 0)) {
-                            bZeroHeightLine = false;
-                        }
-                    }
-                }
-
-                if (lineFollow < maxIgnoredHeight - lineLead) {
-                    lineFollow = maxIgnoredHeight - lineLead;
-                }
-            }
-
-            constantLineHeight = lineLead + lineFollow;
-
-            if (bZeroHeightLine) {
-                return new LineBreakPosition(thisLLM,
-                                             knuthParagraphs.indexOf(par),
-                                             firstElementIndex, lastElementIndex,
-                                             availableShrink, availableStretch,
-                                             difference, ratio, 0, indent,
-                                             0, iLineWidth, 0, 0, 0);
-            } else {
-                return new LineBreakPosition(thisLLM,
-                                             knuthParagraphs.indexOf(par),
-                                             firstElementIndex, lastElementIndex,
-                                             availableShrink, availableStretch,
-                                             difference, ratio, 0, indent,
-                                             lineLead + lineFollow, 
-                                             iLineWidth, spaceBefore, spaceAfter,
-                                             lineLead);
-            }
-        }
-
-        public int findBreakingPoints(Paragraph par, /*int lineWidth,*/
-                                      double threshold, boolean force,
-                                      int allowedBreaks) {
-            return super.findBreakingPoints(par, /*lineWidth,*/ 
-                    threshold, force, allowedBreaks);
-        }
-
-        protected int filterActiveNodes() {
-            KnuthNode bestActiveNode = null;
-
-            if (pageAlignment == EN_JUSTIFY) {
-                // leave all active nodes and find the optimum line number
-                //log.debug("LBA.filterActiveNodes> " + activeNodeCount + " layouts");
-                for (int i = startLine; i < endLine; i++) {
-                    for (KnuthNode node = getNode(i); node != null; node = node.next) {
-                        //log.debug("                       + lines = " + node.line + " demerits = " + node.totalDemerits);
-                        bestActiveNode = compareNodes(bestActiveNode, node);
-                    }
-                }
-
-                // scan the node set once again and remove some nodes
-                //log.debug("LBA.filterActiveList> layout selection");
-                for (int i = startLine; i < endLine; i++) {
-                    for (KnuthNode node = getNode(i); node != null; node = node.next) {
-                        //if (Math.abs(node.line - bestActiveNode.line) > maxDiff) {
-                        //if (false) {
-                        if (node.line != bestActiveNode.line
-                            && node.totalDemerits > MAX_DEMERITS) {
-                            //log.debug("                     XXX lines = " + node.line + " demerits = " + node.totalDemerits);
-                            removeNode(i, node);
-                        } else {
-                            //log.debug("                      ok lines = " + node.line + " demerits = " + node.totalDemerits);
-                        }
-                    }
-                }
-            } else {
-                // leave only the active node with fewest total demerits
-                for (int i = startLine; i < endLine; i++) {
-                    for (KnuthNode node = getNode(i); node != null; node = node.next) {
-                        bestActiveNode = compareNodes(bestActiveNode, node);
-                        if (node != bestActiveNode) {
-                            removeNode(i, node);
-                        }
-                    }
-                }
-            }
-            return bestActiveNode.line;
-        }
-    }
-
       
     private int constantLineHeight = 12000;
       
@@ -556,6 +292,26 @@
         lineHeight = lh;
         lead = l;
         follow = f;
+    }
+
+    public LineLayoutPossibilities getLineLayouts() {
+        return lineLayouts;
+    }
+
+    public boolean isFirstInBlock() {
+        return isFirstInBlock;
+    }
+
+    public int getLineWidth() {
+        return iLineWidth;
+    }
+
+    public void setConstantLineHeight(int constantLineHeight) {
+        this.constantLineHeight = constantLineHeight;
+    }
+
+    public List getKnuthParagraphs() {
+        return knuthParagraphs;
     }
 
     /** @see org.apache.fop.layoutmgr.LayoutManager */

Modified: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java?view=diff&rev=474218&r1=474217&r2=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java Mon Nov 13 01:39:19 2006
@@ -30,6 +30,7 @@
 import org.apache.fop.layoutmgr.Position;
 import org.apache.fop.layoutmgr.NonLeafPosition;
 import org.apache.fop.layoutmgr.TraitSetter;
+import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition;
 import org.apache.fop.area.Area;
 import org.apache.fop.area.Block;
 
@@ -145,6 +146,8 @@
                 if (firstLM == null) {
                     firstLM = lastLM;
                 }
+            } else if (pos instanceof SpaceHandlingBreakPosition) {
+                positionList.add(pos);
             } else {
                 // pos was created by this ListBlockLM, so it must be ignored
             }

Modified: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java?view=diff&rev=474218&r1=474217&r2=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java Mon Nov 13 01:39:19 2006
@@ -288,7 +288,21 @@
             int penaltyHeight = step 
                 + getMaxRemainingHeight(fullHeights, partialHeights) 
                 - totalHeight;
+            
+            //Additional penalty height from penalties in the source lists
+            int additionalPenaltyHeight = 0;
+            KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]);
+            if (endEl instanceof KnuthPenalty) {
+                additionalPenaltyHeight = ((KnuthPenalty)endEl).getW();
+            }
+            endEl = (KnuthElement)elementLists[1].get(end[1]);
+            if (endEl instanceof KnuthPenalty) {
+                additionalPenaltyHeight = Math.max(
+                        additionalPenaltyHeight, ((KnuthPenalty)endEl).getW());
+            }
+            
             int boxHeight = step - addedBoxHeight - penaltyHeight;
+            penaltyHeight += additionalPenaltyHeight; //Add AFTER calculating boxHeight!
 
             // add the new elements
             addedBoxHeight += boxHeight;
@@ -300,7 +314,6 @@
                 if (keepWithNextActive || mustKeepTogether()) {
                     p = KnuthPenalty.INFINITE;
                 }
-                //returnList.add(new KnuthPenalty(penaltyHeight, p, false, stepPosition, false));
                 returnList.add(new BreakElement(stepPosition, penaltyHeight, p, -1, context));
             }
         }

Modified: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java?view=diff&rev=474218&r1=474217&r2=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java Mon Nov 13 01:39:19 2006
@@ -77,6 +77,8 @@
     private int startXOffset;
     private int usedBPD;
     
+    private TableStepper stepper = new TableStepper(this);
+        
     /**
      * Main constructor
      * @param parent Parent layout manager
@@ -144,15 +146,18 @@
             this.headerList = getKnuthElementsForRowIterator(
                     headerIter, context, alignment, TableRowIterator.HEADER);
             ElementListUtils.removeLegalBreaks(this.headerList);
-            this.headerNetHeight = ElementListUtils.calcContentLength(this.headerList);
+            this.headerNetHeight = 
+                ElementListUtils.calcContentLength(this.headerList);
             if (log.isDebugEnabled()) {
-                log.debug("==> Header: " + headerNetHeight + " - " + this.headerList);
+                log.debug("==> Header: " 
+                        + headerNetHeight + " - " + this.headerList);
             }
             TableHeaderFooterPosition pos = new TableHeaderFooterPosition(
                     getTableLM(), true, this.headerList);
             KnuthBox box = new KnuthBox(headerNetHeight, pos, false);
             if (getTableLM().getTable().omitHeaderAtBreak()) {
-                //We can simply add the table header at the beginning of the whole list
+                //We can simply add the table header at the start 
+                //of the whole list
                 headerAsFirst = box;
             } else {
                 headerAsSecondToLast = box;
@@ -162,17 +167,17 @@
             this.footerList = getKnuthElementsForRowIterator(
                     footerIter, context, alignment, TableRowIterator.FOOTER);
             ElementListUtils.removeLegalBreaks(this.footerList);
-            this.footerNetHeight = ElementListUtils.calcContentLength(this.footerList);
+            this.footerNetHeight = 
+                    ElementListUtils.calcContentLength(this.footerList);
             if (log.isDebugEnabled()) {
-                log.debug("==> Footer: " + footerNetHeight + " - " + this.footerList);
-            }
-            if (true /*getTableLM().getTable().omitFooterAtBreak()*/) {
-                //We can simply add the table header at the end of the whole list
-                TableHeaderFooterPosition pos = new TableHeaderFooterPosition(
-                        getTableLM(), false, this.footerList);
-                KnuthBox box = new KnuthBox(footerNetHeight, pos, false);
-                footerAsLast = box;
+                log.debug("==> Footer: " 
+                        + footerNetHeight + " - " + this.footerList);
             }
+            //We can simply add the table footer at the end of the whole list
+            TableHeaderFooterPosition pos = new TableHeaderFooterPosition(
+                    getTableLM(), false, this.footerList);
+            KnuthBox box = new KnuthBox(footerNetHeight, pos, false);
+            footerAsLast = box;
         }
         LinkedList returnList = getKnuthElementsForRowIterator(
                 trIter, context, alignment, TableRowIterator.BODY);
@@ -192,7 +197,8 @@
      * @param iter TableRowIterator instance to fetch rows from
      * @param context Active LayoutContext
      * @param alignment alignment indicator
-     * @param bodyType Indicates what kind of body is being processed (BODY, HEADER or FOOTER)
+     * @param bodyType Indicates what kind of body is being processed 
+     *                  (BODY, HEADER or FOOTER)
      * @return An element list
      */
     private LinkedList getKnuthElementsForRowIterator(TableRowIterator iter, 
@@ -211,7 +217,7 @@
                         pen.setP(-KnuthPenalty.INFINITE);
                         pen.setBreakClass(rowFO.getBreakBefore());
                     } else if (last instanceof BreakElement) {
-                        BreakElement breakPoss = (BreakElement)last;
+                        BreakElement breakPoss = (BreakElement) last;
                         breakPoss.setPenaltyValue(-KnuthPenalty.INFINITE);
                         breakPoss.setBreakClass(rowFO.getBreakBefore());
                     }
@@ -573,9 +579,7 @@
                 log.debug("  height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]);
             }
         }
-        //TODO It may make sense to reuse the stepper since it allocates quite some space
-        TableStepper stepper = new TableStepper(this);
-        LinkedList returnedList = stepper.getCombinedKnuthElementsForRowGroup(
+        LinkedList returnedList = this.stepper.getCombinedKnuthElementsForRowGroup(
                 context, rowGroup, maxColumnCount, bodyType);
         if (returnedList != null) {
             returnList.addAll(returnedList);

Modified: xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/table/TableStepper.java?view=diff&rev=474218&r1=474217&r2=474218
==============================================================================
--- xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/table/TableStepper.java (original)
+++ xmlgraphics/fop/branches/Temp_Floats/src/java/org/apache/fop/layoutmgr/table/TableStepper.java Mon Nov 13 01:39:19 2006
@@ -72,10 +72,10 @@
      */
     public TableStepper(TableContentLayoutManager tclm) {
         this.tclm = tclm;
-        this.activeRow = 0;
     }
     
     private void setup(int columnCount) {
+        this.activeRow = 0;
         elementLists = new List[columnCount];
         startRow = new int[columnCount];
         start = new int[columnCount];



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org