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 2009/09/18 19:10:52 UTC

svn commit: r816718 [4/11] - in /xmlgraphics/fop/branches/Temp_Accessibility: ./ examples/fo/advanced/ hyph/ lib/ src/codegen/unicode/java/org/apache/fop/hyphenation/ src/codegen/unicode/java/org/apache/fop/text/linebreak/ src/codegen/unicode/java/org/...

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java Fri Sep 18 17:10:42 2009
@@ -19,6 +19,8 @@
 
 package org.apache.fop.layoutmgr;
 
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
@@ -27,6 +29,7 @@
 import org.apache.commons.logging.LogFactory;
 
 import org.apache.fop.fo.Constants;
+import org.apache.fop.layoutmgr.BreakingAlgorithm.KnuthNode;
 import org.apache.fop.traits.MinOptMax;
 import org.apache.fop.util.ListUtil;
 
@@ -46,10 +49,10 @@
         int footnoteLastListIndex;
         int footnoteLastElementIndex;
 
-        PageBreakPosition(LayoutManager lm, int iBreakIndex,
+        PageBreakPosition(LayoutManager lm, int breakIndex,
                           int ffli, int ffei, int flli, int flei,
                           double bpdA, int diff) {
-            super(lm, iBreakIndex);
+            super(lm, breakIndex);
             bpdAdjust = bpdA;
             difference = diff;
             footnoteFirstListIndex = ffli;
@@ -59,6 +62,30 @@
         }
     }
 
+    /**
+     * Helper method, mainly used to improve debug/trace output
+     * @param breakClassId  the {@link Constants} enum value.
+     * @return the break class name
+     */
+    static String getBreakClassName(int breakClassId) {
+        switch (breakClassId) {
+        case Constants.EN_ALL: return "ALL";
+        case Constants.EN_ANY: return "ANY";
+        case Constants.EN_AUTO: return "AUTO";
+        case Constants.EN_COLUMN: return "COLUMN";
+        case Constants.EN_EVEN_PAGE: return "EVEN PAGE";
+        case Constants.EN_LINE: return "LINE";
+        case Constants.EN_NONE: return "NONE";
+        case Constants.EN_ODD_PAGE: return "ODD PAGE";
+        case Constants.EN_PAGE: return "PAGE";
+        default: return "??? (" + String.valueOf(breakClassId) + ")";
+        }
+    }
+
+    /**
+     * Helper class, extending the functionality of the
+     * basic {@link BlockKnuthSequence}.
+     */
     public class BlockSequence extends BlockKnuthSequence {
 
         /** Number of elements to ignore at the beginning of the list. */
@@ -79,19 +106,21 @@
 
         /**
          * Creates a new BlockSequence.
-         * @param iStartOn the kind of page the sequence should start on. One of EN_ANY, EN_COLUMN,
-         *                 EN_ODD_PAGE, EN_EVEN_PAGE.
+         * @param  startOn  the kind of page the sequence should start on.
+         *                  One of {@link Constants#EN_ANY}, {@link Constants#EN_COLUMN},
+         *                  {@link Constants#EN_ODD_PAGE}, or {@link Constants#EN_EVEN_PAGE}.
          * @param displayAlign the value for the display-align property
          */
-        public BlockSequence(int iStartOn, int displayAlign) {
+        public BlockSequence(int startOn, int displayAlign) {
             super();
-            startOn = iStartOn;
+            this.startOn =  startOn;
             this.displayAlign = displayAlign;
         }
 
         /**
-         * @return the kind of page the sequence should start on. One of EN_ANY, EN_COLUMN,
-         *         EN_ODD_PAGE, EN_EVEN_PAGE.
+         * @return the kind of page the sequence should start on.
+         *         One of {@link Constants#EN_ANY}, {@link Constants#EN_COLUMN},
+         *         {@link Constants#EN_ODD_PAGE}, or {@link Constants#EN_EVEN_PAGE}.
          */
         public int getStartOn() {
             return this.startOn;
@@ -101,6 +130,7 @@
         public int getDisplayAlign() {
             return this.displayAlign;
         }
+
         /**
          * Finalizes a Knuth sequence.
          * @return a finalized sequence.
@@ -142,6 +172,12 @@
             }
         }
 
+        /**
+         * Finalizes a this {@link BlockSequence}, adding a terminating
+         * penalty-glue-penalty sequence
+         * @param breakPosition a Position instance pointing to the last penalty
+         * @return the finalized {@link BlockSequence}
+         */
         public BlockSequence endBlockSequence(Position breakPosition) {
             KnuthSequence temp = endSequence(breakPosition);
             if (temp != null) {
@@ -214,6 +250,11 @@
      */
     protected abstract List getNextKnuthElements(LayoutContext context, int alignment);
 
+    protected List getNextKnuthElements(LayoutContext context, int alignment,
+            Position positionAtIPDChange, LayoutManager restartAtLM) {
+        throw new UnsupportedOperationException("TODO: implement acceptable fallback");
+    }
+
     /** @return true if there's no content that could be handled. */
     public boolean isEmpty() {
         return (this.blockLists.isEmpty());
@@ -260,14 +301,6 @@
     /**
      * Starts the page breaking process.
      * @param flowBPD the constant available block-progression-dimension (used for every part)
-     */
-    public void doLayout(int flowBPD) {
-        doLayout(flowBPD, false);
-    }
-
-    /**
-     * Starts the page breaking process.
-     * @param flowBPD the constant available block-progression-dimension (used for every part)
      * @param autoHeight true if warnings about overflows should be disabled because the
      *                   the BPD is really undefined (for footnote-separators, for example)
      */
@@ -310,10 +343,7 @@
                 //debug code start
                 if (log.isDebugEnabled()) {
                     log.debug("  blockListIndex = " + blockListIndex);
-                    String pagina = (blockList.startOn == Constants.EN_ANY) ? "any page"
-                            : (blockList.startOn == Constants.EN_ODD_PAGE) ? "odd page"
-                                    : "even page";
-                    log.debug("  sequence starts on " + pagina);
+                    log.debug("  sequence starts on " + getBreakClassName(blockList.startOn));
                 }
                 observeElementList(blockList);
                 //debug code end
@@ -324,7 +354,6 @@
                         getPageProvider(), createLayoutListener(),
                         alignment, alignmentLast, footnoteSeparatorLength,
                         isPartOverflowRecoveryActivated(), autoHeight, isSinglePartFavored());
-                int iOptPageCount;
 
                 BlockSequence effectiveList;
                 if (getCurrentDisplayAlign() == Constants.EN_X_FILL) {
@@ -335,22 +364,108 @@
                     effectiveList = blockList;
                 }
 
-                //iOptPageCount = alg.firstFit(effectiveList, flowBPD, 1, true);
                 alg.setConstantLineWidth(flowBPD);
-                iOptPageCount = alg.findBreakingPoints(effectiveList, /*flowBPD,*/
-                            1, true, BreakingAlgorithm.ALL_BREAKS);
-                log.debug("PLM> iOptPageCount= " + iOptPageCount
-                        + " pageBreaks.size()= " + alg.getPageBreaks().size());
+                int optimalPageCount = alg.findBreakingPoints(effectiveList, 1, true,
+                        BreakingAlgorithm.ALL_BREAKS);
+                if (alg.ipdChanged()) {
+                    KnuthNode optimalBreak = alg.getBestNodeBeforeIPDChange();
+                    int positionIndex = optimalBreak.position;
+                    KnuthElement elementAtBreak = alg.getElement(positionIndex);
+                    Position positionAtBreak = elementAtBreak.getPosition();
+                    if (!(positionAtBreak instanceof SpaceResolver.SpaceHandlingBreakPosition)) {
+                        throw new UnsupportedOperationException(
+                                "Don't know how to restart at position" + positionAtBreak);
+                    }
+                    /* Retrieve the original position wrapped into this space position */
+                    positionAtBreak = positionAtBreak.getPosition();
+                    LayoutManager restartAtLM = null;
+                    List firstElements = Collections.EMPTY_LIST;
+                    if (containsNonRestartableLM(positionAtBreak)) {
+                        firstElements = new LinkedList();
+                        boolean boxFound = false;
+                        Iterator iter = effectiveList.listIterator(++positionIndex);
+                        Position position = null;
+                        while (iter.hasNext()
+                                && (position == null || containsNonRestartableLM(position))) {
+                            KnuthElement element = (KnuthElement) iter.next();
+                            positionIndex++;
+                            position = element.getPosition();
+                            if (element.isBox()) {
+                                boxFound = true;
+                                firstElements.add(element);
+                            } else if (boxFound) {
+                                firstElements.add(element);
+                            }
+                        }
+                        if (position instanceof SpaceResolver.SpaceHandlingBreakPosition) {
+                            /* Retrieve the original position wrapped into this space position */
+                            positionAtBreak = position.getPosition();
+                        }
+                    }
+                    if (positionAtBreak.getIndex() == -1) {
+                        /*
+                         * This is an indication that we are between two blocks
+                         * (possibly surrounded by another block), not inside a
+                         * paragraph.
+                         */
+                        Position position;
+                        Iterator iter = effectiveList.listIterator(positionIndex + 1);
+                        do {
+                            KnuthElement nextElement = (KnuthElement) iter.next();
+                            position = nextElement.getPosition();
+                        } while (position == null
+                                || position instanceof SpaceResolver.SpaceHandlingPosition
+                                || position instanceof SpaceResolver.SpaceHandlingBreakPosition
+                                    && position.getPosition().getIndex() == -1);
+                        LayoutManager surroundingLM = positionAtBreak.getLM();
+                        while (position.getLM() != surroundingLM) {
+                            position = position.getPosition();
+                        }
+                        restartAtLM = position.getPosition().getLM();
+                    }
+                    log.trace("IPD changes after page " + optimalPageCount + " at index "
+                            + optimalBreak.position);
+                    doPhase3(alg, optimalPageCount, blockList, effectiveList);
+
+                    blockLists.clear();
+                    blockListIndex = -1;
+                    nextSequenceStartsOn = getNextBlockList(childLC, Constants.EN_COLUMN,
+                            positionAtBreak, restartAtLM, firstElements);
+                } else {
+                    log.debug("PLM> iOptPageCount= " + optimalPageCount
+                            + " pageBreaks.size()= " + alg.getPageBreaks().size());
 
 
-                //*** Phase 3: Add areas ***
-                doPhase3(alg, iOptPageCount, blockList, effectiveList);
+                    //*** Phase 3: Add areas ***
+                    doPhase3(alg, optimalPageCount, blockList, effectiveList);
+                }
             }
         }
 
     }
 
     /**
+     * Returns {@code true} if the given position or one of its descendants
+     * corresponds to a non-restartable LM.
+     *
+     * @param position a position
+     * @return {@code true} if there is a non-restartable LM in the hierarchy
+     */
+    private boolean containsNonRestartableLM(Position position) {
+        LayoutManager lm = position.getLM();
+        if (lm != null && !lm.isRestartable()) {
+            return true;
+        } else {
+            Position subPosition = position.getPosition();
+            if (subPosition == null) {
+                return false;
+            } else {
+                return containsNonRestartableLM(subPosition);
+            }
+        }
+    }
+
+    /**
      * Phase 3 of Knuth algorithm: Adds the areas
      * @param alg PageBreakingAlgorithm instance which determined the breaks
      * @param partCount number of parts (pages) to be rendered
@@ -417,7 +532,7 @@
             log.debug("PLM> part: " + (p + 1)
                     + ", start at pos " + startElementIndex
                     + ", break at pos " + endElementIndex
-                    + ", break class = " + lastBreakClass);
+                    + ", break class = " + getBreakClassName(lastBreakClass));
 
             startPart(effectiveList, lastBreakClass);
 
@@ -444,17 +559,9 @@
             // at the beginning of the line
             effectiveListIterator = effectiveList
                     .listIterator(startElementIndex);
-            KnuthElement firstElement;
             while (effectiveListIterator.hasNext()
-                    && !(firstElement = (KnuthElement) effectiveListIterator.next())
+                    && !((KnuthElement) effectiveListIterator.next())
                             .isBox()) {
-                /*
-                if (firstElement.isGlue() && firstElement.getLayoutManager() != null) {
-                    // discard the space representd by the glue element
-                    ((BlockLevelLayoutManager) firstElement
-                            .getLayoutManager())
-                            .discardSpace((KnuthGlue) firstElement);
-                }*/
                 startElementIndex++;
             }
 
@@ -537,6 +644,7 @@
     protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
         return nextSequenceStartsOn;
     }
+
     /**
      * Gets the next block list (sequence) and adds it to a list of block lists if it's not empty.
      * @param childLC LayoutContext to use
@@ -545,12 +653,38 @@
      */
     protected int getNextBlockList(LayoutContext childLC,
             int nextSequenceStartsOn) {
+        return getNextBlockList(childLC, nextSequenceStartsOn, null, null, null);
+    }
+
+    /**
+     * Gets the next block list (sequence) and adds it to a list of block lists
+     * if it's not empty.
+     *
+     * @param childLC LayoutContext to use
+     * @param nextSequenceStartsOn indicates on what page the next sequence
+     * should start
+     * @param positionAtIPDChange last element on the part before an IPD change
+     * @param restartAtLM the layout manager from which to restart, if IPD
+     * change occurs between two LMs
+     * @param firstElements elements from non-restartable LMs on the new page
+     * @return the page on which the next content should appear after a hard
+     * break
+     */
+    protected int getNextBlockList(LayoutContext childLC, int nextSequenceStartsOn,
+            Position positionAtIPDChange, LayoutManager restartAtLM, List firstElements) {
         updateLayoutContext(childLC);
         //Make sure the span change signal is reset
         childLC.signalSpanChange(Constants.NOT_SET);
 
         BlockSequence blockList;
-        List returnedList = getNextKnuthElements(childLC, alignment);
+        List returnedList;
+        if (positionAtIPDChange == null) {
+            returnedList = getNextKnuthElements(childLC, alignment);
+        } else {
+            returnedList = getNextKnuthElements(childLC, alignment, positionAtIPDChange,
+                    restartAtLM);
+            returnedList.addAll(0, firstElements);
+        }
         if (returnedList != null) {
             if (returnedList.isEmpty()) {
                 nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn);
@@ -562,26 +696,23 @@
             nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn);
 
             Position breakPosition = null;
-            if (((KnuthElement) ListUtil.getLast(returnedList)).isForcedBreak()) {
+            if (ElementListUtils.endsWithForcedBreak(returnedList)) {
                 KnuthPenalty breakPenalty = (KnuthPenalty) ListUtil
                         .removeLast(returnedList);
                 breakPosition = breakPenalty.getPosition();
+                log.debug("PLM> break - " + getBreakClassName(breakPenalty.getBreakClass()));
                 switch (breakPenalty.getBreakClass()) {
                 case Constants.EN_PAGE:
-                    log.debug("PLM> break - PAGE");
                     nextSequenceStartsOn = Constants.EN_ANY;
                     break;
                 case Constants.EN_COLUMN:
-                    log.debug("PLM> break - COLUMN");
                     //TODO Fix this when implementing multi-column layout
                     nextSequenceStartsOn = Constants.EN_COLUMN;
                     break;
                 case Constants.EN_ODD_PAGE:
-                    log.debug("PLM> break - ODD PAGE");
                     nextSequenceStartsOn = Constants.EN_ODD_PAGE;
                     break;
                 case Constants.EN_EVEN_PAGE:
-                    log.debug("PLM> break - EVEN PAGE");
                     nextSequenceStartsOn = Constants.EN_EVEN_PAGE;
                     break;
                 default:
@@ -590,7 +721,7 @@
                 }
             }
             blockList.addAll(returnedList);
-            BlockSequence seq = null;
+            BlockSequence seq;
             seq = blockList.endBlockSequence(breakPosition);
             if (seq != null) {
                 this.blockLists.add(seq);
@@ -602,8 +733,8 @@
     /**
      * Returns the average width of all the lines in the given range.
      * @param effectiveList effective block list to work on
-     * @param startElementIndex
-     * @param endElementIndex
+     * @param startElementIndex index of the element starting the range
+     * @param endElementIndex   index of the element ending the range
      * @return the average line length, 0 if there's no content
      */
     private int optimizeLineLength(KnuthSequence effectiveList, int startElementIndex, int endElementIndex) {
@@ -854,29 +985,6 @@
             log.debug("AdjustLineNumbers: difference " + difference + " / " + total + " on " + lineList.size() + " elements");
         }
 
-//            int adjustedDiff = 0;
-//            int partial = 0;
-//            KnuthGlue prevLine = null;
-//            KnuthGlue currLine = null;
-//            ListIterator lineListIterator = lineList.listIterator();
-//            while (lineListIterator.hasNext()) {
-//                currLine = (KnuthGlue)lineListIterator.next();
-//                if (prevLine != null
-//                    && prevLine.getLayoutManager() != currLine.getLayoutManager()) {
-//                    int newAdjust = ((BlockLevelLayoutManager) prevLine.getLayoutManager())
-//                                    .negotiateBPDAdjustment(((int) ((float) partial * difference / total)) - adjustedDiff, prevLine);
-//                    adjustedDiff += newAdjust;
-//                }
-//                partial += (difference > 0 ? currLine.getY() : currLine.getZ());
-//                prevLine = currLine;
-//            }
-//            if (currLine != null) {
-//                int newAdjust = ((BlockLevelLayoutManager) currLine.getLayoutManager())
-//                                .negotiateBPDAdjustment(((int) ((float) partial * difference / total)) - adjustedDiff, currLine);
-//                adjustedDiff += newAdjust;
-//            }
-//            return adjustedDiff;
-
         ListIterator lineListIterator = lineList.listIterator();
         int adjustedDiff = 0;
         int partial = 0;

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java Fri Sep 18 17:10:42 2009
@@ -47,22 +47,22 @@
     private static Log log = LogFactory.getLog(AbstractLayoutManager.class);
 
     /** Parent LayoutManager for this LayoutManager */
-    protected LayoutManager parentLM = null;
+    protected LayoutManager parentLM;
     /** List of child LayoutManagers */
-    protected List childLMs = null;
+    protected List childLMs;
     /** Iterator for child LayoutManagers */
-    protected ListIterator fobjIter = null;
+    protected ListIterator fobjIter;
     /** Marker map for markers related to this LayoutManager */
-    private Map markers = null;
+    private Map markers;
 
     /** True if this LayoutManager has handled all of its content. */
-    private boolean isFinished = false;
+    private boolean isFinished;
 
     /** child LM during getNextKnuthElement phase */
-    protected LayoutManager curChildLM = null;
+    protected LayoutManager curChildLM;
 
     /** child LM iterator during getNextKnuthElement phase */
-    protected ListIterator childLMiter = null;
+    protected ListIterator childLMiter;
 
     private int lastGeneratedPosition = -1;
     private int smallestPosNumberChecked = Integer.MAX_VALUE;
@@ -122,6 +122,14 @@
         return null;
     }
 
+    protected void setCurrentChildLM(LayoutManager childLM) {
+        curChildLM = childLM;
+        childLMiter = new LMiter(this);
+        do {
+            curChildLM = (LayoutManager) childLMiter.next();
+        } while (curChildLM != childLM);
+    }
+
     /**
      * Return indication if getChildLM will return another LM.
      * @return true if another child LM is still available
@@ -450,4 +458,22 @@
         return (super.toString() + (fobj != null ? "[fobj=" + fobj.toString() + "]" : ""));
     }
 
+    /** {@inheritDoc} */
+    public void reset() {
+        isFinished = false;
+        curChildLM = null;
+        childLMiter = new LMiter(this);
+        /*
+         * Reset the children LM. Can't rely on childLMiter since it may have
+         * been set to null in checkEndOfLayout.
+         */
+        for (LMiter iter = new LMiter(this); iter.hasNext();) {
+            ((LayoutManager) iter.next()).reset();
+        }
+        if (fobj != null) {
+            markers = fobj.getMarkers();
+        }
+        lastGeneratedPosition = -1;
+    }
+
 }

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java Fri Sep 18 17:10:42 2009
@@ -382,4 +382,9 @@
         }
     }
 
+    /** {@inheritDoc} */
+    public void reset() {
+        throw new IllegalStateException();
+    }
+
 }

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java Fri Sep 18 17:10:42 2009
@@ -117,7 +117,7 @@
             // set space after for each LM, in order to implement
             // display-align = distribute
             lc.setSpaceAfter(layoutContext.getSpaceAfter());
-            lc.setStackLimitsFrom(layoutContext);
+            lc.setStackLimitBP(layoutContext.getStackLimitBP());
             childLM.addAreas(childPosIter, lc);
         }
 

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java Fri Sep 18 17:10:42 2009
@@ -24,6 +24,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Stack;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -37,6 +38,7 @@
 import org.apache.fop.datatypes.Length;
 import org.apache.fop.fo.flow.BlockContainer;
 import org.apache.fop.fo.properties.CommonAbsolutePosition;
+import org.apache.fop.fo.properties.KeepProperty;
 import org.apache.fop.traits.MinOptMax;
 import org.apache.fop.traits.SpaceVal;
 import org.apache.fop.util.ListUtil;
@@ -261,7 +263,215 @@
 
         if (!firstVisibleMarkServed) {
             addKnuthElementsForSpaceBefore(returnList, alignment);
-            context.updateKeepWithPreviousPending(getKeepWithPreviousStrength());
+            context.updateKeepWithPreviousPending(getKeepWithPrevious());
+        }
+
+        addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
+        firstVisibleMarkServed = true;
+
+        if (autoHeight && inlineElementList) {
+            //Spaces, border and padding to be repeated at each break
+            addPendingMarks(context);
+
+            LayoutManager curLM; // currently active LM
+            LayoutManager prevLM = null; // previously active LM
+            while ((curLM = getChildLM()) != null) {
+                LayoutContext childLC = new LayoutContext(0);
+                childLC.copyPendingMarksFrom(context);
+                // curLM is a ?
+                childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit));
+                childLC.setRefIPD(relDims.ipd);
+                childLC.setWritingMode(getBlockContainerFO().getWritingMode());
+                if (curLM == this.childLMs.get(0)) {
+                    childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
+                    //Handled already by the parent (break collapsing, see above)
+                }
+
+                // get elements from curLM
+                returnedList = curLM.getNextKnuthElements(childLC, alignment);
+                if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) {
+                    //Propagate keep-with-previous up from the first child
+                    context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
+                    childLC.clearKeepWithPreviousPending();
+                }
+                if (returnedList.size() == 1
+                        && ((ListElement)returnedList.get(0)).isForcedBreak()) {
+                    // a descendant of this block has break-before
+                    /*
+                    if (returnList.size() == 0) {
+                        // the first child (or its first child ...) has
+                        // break-before;
+                        // all this block, including space before, will be put in
+                        // the
+                        // following page
+                        bSpaceBeforeServed = false;
+                    }*/
+                    contentList.addAll(returnedList);
+
+                    // "wrap" the Position inside each element
+                    // moving the elements from contentList to returnList
+                    returnedList = new LinkedList();
+                    wrapPositionElements(contentList, returnList);
+
+                    return returnList;
+                } else {
+                    if (prevLM != null) {
+                        // there is a block handled by prevLM
+                        // before the one handled by curLM
+                        addInBetweenBreak(contentList, context, childLC);
+                    }
+                    contentList.addAll(returnedList);
+                    if (returnedList.isEmpty()) {
+                        //Avoid NoSuchElementException below (happens with empty blocks)
+                        continue;
+                    }
+                    if (ElementListUtils.endsWithForcedBreak(returnedList)) {
+                        // a descendant of this block has break-after
+                        if (curLM.isFinished()) {
+                            // there is no other content in this block;
+                            // it's useless to add space after before a page break
+                            setFinished(true);
+                        }
+
+                        returnedList = new LinkedList();
+                        wrapPositionElements(contentList, returnList);
+
+                        return returnList;
+                    }
+                }
+                // propagate and clear
+                context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
+                childLC.clearKeepsPending();
+                prevLM = curLM;
+            }
+
+            returnedList = new LinkedList();
+            wrapPositionElements(contentList, returnList);
+
+        } else {
+            MinOptMax range = new MinOptMax(relDims.ipd);
+            BlockContainerBreaker breaker = new BlockContainerBreaker(this, range);
+            breaker.doLayout(relDims.bpd, autoHeight);
+            boolean contentOverflows = breaker.isOverflow();
+            if (autoHeight) {
+                //Update content BPD now that it is known
+                int newHeight = breaker.deferredAlg.totalWidth;
+                boolean switchedProgressionDirection
+                    = (getBlockContainerFO().getReferenceOrientation() % 180 != 0);
+                if (switchedProgressionDirection) {
+                    setContentAreaIPD(newHeight);
+                } else {
+                    vpContentBPD = newHeight;
+                }
+                updateRelDims(contentRectOffsetX, contentRectOffsetY, false);
+            }
+
+            Position bcPosition = new BlockContainerPosition(this, breaker);
+            returnList.add(new KnuthBox(vpContentBPD, notifyPos(bcPosition), false));
+            //TODO Handle min/opt/max for block-progression-dimension
+            /* These two elements will be used to add stretchability to the above box
+            returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE,
+                                   false, returnPosition, false));
+            returnList.add(new KnuthGlue(0, 1 * constantLineHeight, 0,
+                                   LINE_NUMBER_ADJUSTMENT, returnPosition, false));
+            */
+
+            if (contentOverflows) {
+                BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get(
+                        getBlockContainerFO().getUserAgent().getEventBroadcaster());
+                boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW);
+                eventProducer.viewportOverflow(this, getBlockContainerFO().getName(),
+                        breaker.getOverflowAmount(), needClip(), canRecover,
+                        getBlockContainerFO().getLocator());
+            }
+        }
+        addKnuthElementsForBorderPaddingAfter(returnList, true);
+        addKnuthElementsForSpaceAfter(returnList, alignment);
+
+        //All child content is processed. Only break-after can occur now, so...
+        context.clearPendingMarks();
+        addKnuthElementsForBreakAfter(returnList, context);
+
+        context.updateKeepWithNextPending(getKeepWithNext());
+
+        setFinished(true);
+        return returnList;
+    }
+
+    /** {@inheritDoc} */
+    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
+            Position restartPosition, LayoutManager restartAtLM) {
+        resetSpaces();
+        if (isAbsoluteOrFixed()) {
+            return getNextKnuthElementsAbsolute(context, alignment);
+        }
+
+        autoHeight = false;
+        //boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0);
+        int maxbpd = context.getStackLimitBP().opt;
+        int allocBPD;
+        if (height.getEnum() == EN_AUTO
+                || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) {
+            //auto height when height="auto" or "if that dimension is not specified explicitly
+            //(i.e., it depends on content's block-progression-dimension)" (XSL 1.0, 7.14.1)
+            allocBPD = maxbpd;
+            autoHeight = true;
+            if (getBlockContainerFO().getReferenceOrientation() == 0) {
+                //Cannot easily inline element list when ref-or="180"
+                inlineElementList = true;
+            }
+        } else {
+            allocBPD = height.getValue(this); //this is the content-height
+            allocBPD += getBPIndents();
+        }
+        vpContentBPD = allocBPD - getBPIndents();
+
+        referenceIPD = context.getRefIPD();
+        if (width.getEnum() == EN_AUTO) {
+            updateContentAreaIPDwithOverconstrainedAdjust();
+        } else {
+            int contentWidth = width.getValue(this);
+            updateContentAreaIPDwithOverconstrainedAdjust(contentWidth);
+        }
+
+        double contentRectOffsetX = 0;
+        contentRectOffsetX += getBlockContainerFO()
+                .getCommonMarginBlock().startIndent.getValue(this);
+        double contentRectOffsetY = 0;
+        contentRectOffsetY += getBlockContainerFO()
+                .getCommonBorderPaddingBackground().getBorderBeforeWidth(false);
+        contentRectOffsetY += getBlockContainerFO()
+                .getCommonBorderPaddingBackground().getPaddingBefore(false, this);
+
+        updateRelDims(contentRectOffsetX, contentRectOffsetY, autoHeight);
+
+        int availableIPD = referenceIPD - getIPIndents();
+        if (getContentAreaIPD() > availableIPD) {
+            BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get(
+                    getBlockContainerFO().getUserAgent().getEventBroadcaster());
+            eventProducer.objectTooWide(this, getBlockContainerFO().getName(),
+                    getContentAreaIPD(), context.getRefIPD(),
+                    getBlockContainerFO().getLocator());
+        }
+
+        MinOptMax stackLimit = new MinOptMax(relDims.bpd);
+
+        List returnedList;
+        List contentList = new LinkedList();
+        List returnList = new LinkedList();
+
+        if (!breakBeforeServed) {
+            breakBeforeServed = true;
+            if (!context.suppressBreakBefore()) {
+                if (addKnuthElementsForBreakBefore(returnList, context)) {
+                    return returnList;
+                }
+            }
+        }
+
+        if (!firstVisibleMarkServed) {
+            addKnuthElementsForSpaceBefore(returnList, alignment);
+            context.updateKeepWithPreviousPending(getKeepWithPrevious());
         }
 
         addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
@@ -273,8 +483,99 @@
 
             BlockLevelLayoutManager curLM; // currently active LM
             BlockLevelLayoutManager prevLM = null; // previously active LM
+
+            LayoutContext childLC = new LayoutContext(0);
+            if (lmStack.isEmpty()) {
+                assert restartAtLM != null && restartAtLM.getParent() == this;
+                curLM = (BlockLevelLayoutManager) restartAtLM;
+                curLM.reset();
+                setCurrentChildLM(curLM);
+
+                childLC.copyPendingMarksFrom(context);
+                childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit));
+                childLC.setRefIPD(relDims.ipd);
+                childLC.setWritingMode(getBlockContainerFO().getWritingMode());
+                if (curLM == this.childLMs.get(0)) {
+                    childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
+                    //Handled already by the parent (break collapsing, see above)
+                }
+
+                // get elements from curLM
+                returnedList = curLM.getNextKnuthElements(childLC, alignment);
+            } else {
+                curLM = (BlockLevelLayoutManager) lmStack.pop();
+                setCurrentChildLM(curLM);
+
+                childLC.copyPendingMarksFrom(context);
+                childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit));
+                childLC.setRefIPD(relDims.ipd);
+                childLC.setWritingMode(getBlockContainerFO().getWritingMode());
+                if (curLM == this.childLMs.get(0)) {
+                    childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
+                    //Handled already by the parent (break collapsing, see above)
+                }
+
+                // get elements from curLM
+                returnedList = curLM.getNextKnuthElements(childLC, alignment, lmStack,
+                        restartPosition, restartAtLM);
+            }
+            if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) {
+                //Propagate keep-with-previous up from the first child
+                context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
+                childLC.clearKeepWithPreviousPending();
+            }
+            if (returnedList.size() == 1
+                    && ((ListElement)returnedList.get(0)).isForcedBreak()) {
+                // a descendant of this block has break-before
+                /*
+                if (returnList.size() == 0) {
+                    // the first child (or its first child ...) has
+                    // break-before;
+                    // all this block, including space before, will be put in
+                    // the
+                    // following page
+                    bSpaceBeforeServed = false;
+                }*/
+                contentList.addAll(returnedList);
+
+                // "wrap" the Position inside each element
+                // moving the elements from contentList to returnList
+                returnedList = new LinkedList();
+                wrapPositionElements(contentList, returnList);
+
+                return returnList;
+            } else {
+                if (prevLM != null) {
+                    // there is a block handled by prevLM
+                    // before the one handled by curLM
+                    addInBetweenBreak(contentList, context, childLC);
+                }
+                contentList.addAll(returnedList);
+                if (!returnedList.isEmpty()) {
+                    if (((ListElement) ListUtil.getLast(returnedList))
+                            .isForcedBreak()) {
+                        // a descendant of this block has break-after
+                        if (curLM.isFinished()) {
+                            // there is no other content in this block;
+                            // it's useless to add space after before a page break
+                            setFinished(true);
+                        }
+
+                        returnedList = new LinkedList();
+                        wrapPositionElements(contentList, returnList);
+
+                        return returnList;
+                    }
+                }
+            }
+            // propagate and clear
+            context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
+            childLC.clearKeepsPending();
+            prevLM = curLM;
+
             while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) {
-                LayoutContext childLC = new LayoutContext(0);
+                curLM.reset();
+                childLC = new LayoutContext(0);
                 childLC.copyPendingMarksFrom(context);
                 // curLM is a ?
                 childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit));
@@ -391,12 +692,17 @@
         context.clearPendingMarks();
         addKnuthElementsForBreakAfter(returnList, context);
 
-        context.updateKeepWithNextPending(getKeepWithNextStrength());
+        context.updateKeepWithNextPending(getKeepWithNext());
 
         setFinished(true);
         return returnList;
     }
 
+    /** {@inheritDoc} */
+    public boolean isRestartable() {
+        return true;
+    }
+
     private List getNextKnuthElementsAbsolute(LayoutContext context, int alignment) {
         autoHeight = false;
 
@@ -1011,23 +1317,18 @@
     }
 
     /** {@inheritDoc} */
-    public int getKeepTogetherStrength() {
-        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(
-                getBlockContainerFO().getKeepTogether());
-        strength = Math.max(strength, getParentKeepTogetherStrength());
-        return strength;
+    public KeepProperty getKeepTogetherProperty() {
+        return getBlockContainerFO().getKeepTogether();
     }
 
     /** {@inheritDoc} */
-    public int getKeepWithNextStrength() {
-        return KeepUtil.getCombinedBlockLevelKeepStrength(
-                getBlockContainerFO().getKeepWithNext());
+    public KeepProperty getKeepWithPreviousProperty() {
+        return getBlockContainerFO().getKeepWithPrevious();
     }
 
     /** {@inheritDoc} */
-    public int getKeepWithPreviousStrength() {
-        return KeepUtil.getCombinedBlockLevelKeepStrength(
-                getBlockContainerFO().getKeepWithPrevious());
+    public KeepProperty getKeepWithNextProperty() {
+        return getBlockContainerFO().getKeepWithNext();
     }
 
     /**

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java Fri Sep 18 17:10:42 2009
@@ -22,6 +22,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Stack;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -67,9 +68,6 @@
     private MinOptMax effSpaceBefore;
     private MinOptMax effSpaceAfter;
 
-    /** The list of child BreakPoss instances. */
-    protected List childBreaks = new java.util.ArrayList();
-
     /**
      * Creates a new BlockLayoutManager.
      * @param inBlock the block FO object to create the layout manager for.
@@ -114,8 +112,19 @@
 
     /** {@inheritDoc} */
     public List getNextKnuthElements(LayoutContext context, int alignment) {
+        return getNextKnuthElements(context, alignment, null, null, null);
+    }
+
+    /** {@inheritDoc} */
+    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
+            Position restartPosition, LayoutManager restartAtLM) {
         resetSpaces();
-        return super.getNextKnuthElements(context, alignment);
+        if (lmStack == null) {
+            return super.getNextKnuthElements(context, alignment);
+        } else {
+            return super.getNextKnuthElements(context, alignment, lmStack, restartPosition,
+                    restartAtLM);
+        }
     }
 
     private void resetSpaces() {
@@ -210,21 +219,18 @@
     }
 
     /** {@inheritDoc} */
-    public int getKeepTogetherStrength() {
-        KeepProperty keep = getBlockFO().getKeepTogether();
-        int strength = KeepUtil.getCombinedBlockLevelKeepStrength(keep);
-        strength = Math.max(strength, getParentKeepTogetherStrength());
-        return strength;
+    public KeepProperty getKeepTogetherProperty() {
+        return getBlockFO().getKeepTogether();
     }
 
     /** {@inheritDoc} */
-    public int getKeepWithNextStrength() {
-        return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithNext());
+    public KeepProperty getKeepWithPreviousProperty() {
+        return getBlockFO().getKeepWithPrevious();
     }
 
     /** {@inheritDoc} */
-    public int getKeepWithPreviousStrength() {
-        return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithPrevious());
+    public KeepProperty getKeepWithNextProperty() {
+        return getBlockFO().getKeepWithNext();
     }
 
     /** {@inheritDoc} */
@@ -252,8 +258,8 @@
         // and put them in a new list;
         LinkedList positionList = new LinkedList();
         Position pos;
-        boolean bSpaceBefore = false;
-        boolean bSpaceAfter = false;
+        boolean spaceBefore = false;
+        boolean spaceAfter = false;
         Position firstPos = null;
         Position lastPos = null;
         while (parentIter.hasNext()) {
@@ -276,11 +282,11 @@
                 // this means the space was not discarded
                 if (positionList.size() == 0) {
                     // pos was in the element representing space-before
-                    bSpaceBefore = true;
+                    spaceBefore = true;
                     //log.trace(" space before");
                 } else {
                     // pos was in the element representing space-after
-                    bSpaceAfter = true;
+                    spaceAfter = true;
                     //log.trace(" space-after");
                 }
             } else if (innerPosition.getLM() == this
@@ -305,7 +311,7 @@
             // the Positions in positionList were inside the elements
             // created by the LineLM
             childPosIter = new StackingIter(positionList.listIterator());
-            } else {
+        } else {
             // the Positions in positionList were inside the elements
             // created by the BlockLM in the createUnitElements() method
             //if (((Position) positionList.getLast()) instanceof
@@ -344,7 +350,7 @@
             //                   + " spacing");
             // add space before and / or after the paragraph
             // to reach a multiple of bpUnit
-            if (bSpaceBefore && bSpaceAfter) {
+            if (spaceBefore && spaceAfter) {
                 foSpaceBefore = new SpaceVal(getBlockFO()
                                     .getCommonMarginBlock().spaceBefore, this).getSpace();
                 foSpaceAfter = new SpaceVal(getBlockFO()
@@ -357,7 +363,7 @@
                         + foSpaceBefore.min
                         + foSpaceAfter.min)
                         * bpUnit - splitLength - adjustedSpaceBefore;
-                } else if (bSpaceBefore) {
+                } else if (spaceBefore) {
                 adjustedSpaceBefore = neededUnits(splitLength
                         + foSpaceBefore.min)
                         * bpUnit - splitLength;
@@ -551,5 +557,10 @@
         }
     }
 
+    /** {@inheritDoc} */
+    public boolean isRestartable() {
+        return true;
+    }
+
 }
 

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java Fri Sep 18 17:10:42 2009
@@ -19,6 +19,8 @@
 
 package org.apache.fop.layoutmgr;
 
+import org.apache.fop.fo.properties.KeepProperty;
+
 /**
  * The interface for LayoutManagers which generate block areas
  */
@@ -35,11 +37,6 @@
     /** Adjustment class: adjustment for line height */
     int LINE_HEIGHT_ADJUSTMENT = 3;
 
-    /** The integer value for "auto" keep strength */
-    int KEEP_AUTO = Integer.MIN_VALUE;
-    /** The integer value for "always" keep strength */
-    int KEEP_ALWAYS = Integer.MAX_VALUE;
-
     int negotiateBPDAdjustment(int adj, KnuthElement lastElement);
 
     void discardSpace(KnuthGlue spaceGlue);
@@ -48,7 +45,7 @@
      * Returns the keep-together strength for this element.
      * @return the keep-together strength
      */
-    int getKeepTogetherStrength();
+    Keep getKeepTogether();
 
     /**
      * @return true if this element must be kept together
@@ -59,7 +56,7 @@
      * Returns the keep-with-previous strength for this element.
      * @return the keep-with-previous strength
      */
-    int getKeepWithPreviousStrength();
+    Keep getKeepWithPrevious();
 
     /**
      * @return true if this element must be kept with the previous element.
@@ -70,11 +67,28 @@
      * Returns the keep-with-next strength for this element.
      * @return the keep-with-next strength
      */
-    int getKeepWithNextStrength();
+    Keep getKeepWithNext();
 
     /**
      * @return true if this element must be kept with the next element.
      */
     boolean mustKeepWithNext();
 
+    /**
+     * Returns the keep-together property specified on the FObj.
+     * @return the keep-together property
+     */
+    KeepProperty getKeepTogetherProperty();
+
+    /**
+     * Returns the keep-with-previous property specified on the FObj.
+     * @return the keep-together property
+     */
+    KeepProperty getKeepWithPreviousProperty();
+
+    /**
+     * Returns the keep-with-next property specified on the FObj.
+     * @return the keep-together property
+     */
+    KeepProperty getKeepWithNextProperty();
 }

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java Fri Sep 18 17:10:42 2009
@@ -23,6 +23,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Stack;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -30,9 +31,11 @@
 import org.apache.fop.area.Area;
 import org.apache.fop.area.Block;
 import org.apache.fop.area.BlockParent;
+import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.properties.BreakPropertySet;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.fo.properties.KeepProperty;
 import org.apache.fop.fo.properties.SpaceProperty;
 import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
 import org.apache.fop.layoutmgr.inline.LineLayoutManager;
@@ -52,31 +55,26 @@
      */
     private static Log log = LogFactory.getLog(BlockStackingLayoutManager.class);
 
-    /**
-     * Reference to FO whose areas it's managing or to the traits
-     * of the FO.
-     */
-    //protected LayoutManager curChildLM = null; AbstractLayoutManager also defines this!
-    protected BlockParent parentArea = null;
+    protected BlockParent parentArea;
 
     /** Value of the block-progression-unit (non-standard property) */
-    protected int bpUnit = 0;
+    protected int bpUnit;
     /** space-before value adjusted for block-progression-unit handling */
-    protected int adjustedSpaceBefore = 0;
+    protected int adjustedSpaceBefore;
     /** space-after value adjusted for block-progression-unit handling */
-    protected int adjustedSpaceAfter = 0;
+    protected int adjustedSpaceAfter;
     /** Only used to store the original list when createUnitElements is called */
-    protected List storedList = null;
+    protected List storedList;
     /** Indicates whether break before has been served or not */
-    protected boolean breakBeforeServed = false;
+    protected boolean breakBeforeServed;
     /** Indicates whether the first visible mark has been returned by this LM, yet */
-    protected boolean firstVisibleMarkServed = false;
+    protected boolean firstVisibleMarkServed;
     /** Reference IPD available */
-    protected int referenceIPD = 0;
+    protected int referenceIPD;
     /** the effective start-indent value */
-    protected int startIndent = 0;
+    protected int startIndent;
     /** the effective end-indent value */
-    protected int endIndent = 0;
+    protected int endIndent;
     /**
      * Holds the (one-time use) fo:block space-before
      * and -after properties.  Large fo:blocks are split
@@ -86,13 +84,13 @@
      * Block and space-after at the end of the last Block
      * used in rendering the fo:block.
      */
-    protected MinOptMax foSpaceBefore = null;
+    protected MinOptMax foSpaceBefore;
     /** see foSpaceBefore */
-    protected MinOptMax foSpaceAfter = null;
+    protected MinOptMax foSpaceAfter;
 
     private Position auxiliaryPosition;
 
-    private int contentAreaIPD = 0;
+    private int contentAreaIPD;
 
     /**
      * @param node the fo this LM deals with
@@ -246,38 +244,27 @@
 
     /** {@inheritDoc} */
     public List getNextKnuthElements(LayoutContext context, int alignment) {
-        //log.debug("BLM.getNextKnuthElements> keep-together = "
-              // + layoutProps.keepTogether.getType());
-        //log.debug(" keep-with-previous = " +
-              // layoutProps.keepWithPrevious.getType());
-        //log.debug(" keep-with-next = " +
-              // layoutProps.keepWithNext.getType());
-        BlockLevelLayoutManager curLM; // currently active LM
-        BlockLevelLayoutManager prevLM = null; // previously active LM
-
         referenceIPD = context.getRefIPD();
-
         updateContentAreaIPDwithOverconstrainedAdjust();
 
-        List returnedList = null;
         List contentList = new LinkedList();
-        List returnList = new LinkedList();
+        List elements = new LinkedList();
 
         if (!breakBeforeServed) {
             breakBeforeServed = true;
             if (!context.suppressBreakBefore()) {
-                if (addKnuthElementsForBreakBefore(returnList, context)) {
-                    return returnList;
+                if (addKnuthElementsForBreakBefore(elements, context)) {
+                    return elements;
                 }
             }
         }
 
         if (!firstVisibleMarkServed) {
-            addKnuthElementsForSpaceBefore(returnList, alignment);
-            context.updateKeepWithPreviousPending(getKeepWithPreviousStrength());
+            addKnuthElementsForSpaceBefore(elements, alignment);
+            context.updateKeepWithPreviousPending(getKeepWithPrevious());
         }
 
-        addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
+        addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed);
         firstVisibleMarkServed = true;
 
         //Spaces, border and padding to be repeated at each break
@@ -286,171 +273,340 @@
         //Used to indicate a special break-after case when all content has already been generated.
         BreakElement forcedBreakAfterLast = null;
 
-        while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) {
+        LayoutManager currentChildLM;
+        while ((currentChildLM = (LayoutManager) getChildLM()) != null) {
             LayoutContext childLC = new LayoutContext(0);
-            childLC.copyPendingMarksFrom(context);
-            if (curLM instanceof LineLayoutManager) {
-                // curLM is a LineLayoutManager
-                // set stackLimit for lines (stack limit is now i-p-direction, not b-p-direction!)
-                childLC.setStackLimitBP(context.getStackLimitBP());
-                childLC.setStackLimitIP(new MinOptMax(getContentAreaIPD()));
-                childLC.setRefIPD(getContentAreaIPD());
-            } else {
-                // curLM is a ?
-                //childLC.setStackLimit(MinOptMax.subtract(context
-                //        .getStackLimit(), stackSize));
-                childLC.setStackLimitBP(context.getStackLimitBP());
-                childLC.setRefIPD(referenceIPD);
-            }
-            if (curLM == this.childLMs.get(0)) {
-                childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
-                //Handled already by the parent (break collapsing, see above)
-            }
 
-            // get elements from curLM
-            returnedList = curLM.getNextKnuthElements(childLC, alignment);
-            if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) {
+            List childrenElements = getNextChildElements(currentChildLM, context, childLC,
+                    alignment);
+
+            if (contentList.isEmpty()) {
                 //Propagate keep-with-previous up from the first child
                 context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
-                childLC.clearKeepWithPreviousPending();
             }
-            if (returnedList != null
-                    && returnedList.size() == 1
-                    && ((ListElement) returnedList.get(0)).isForcedBreak()) {
+            if (childrenElements != null && !childrenElements.isEmpty()) {
+                if (!contentList.isEmpty()
+                        && !ElementListUtils.startsWithForcedBreak(childrenElements)) {
+                    // there is a block handled by prevLM before the one
+                    // handled by curLM, and the one handled
+                    // by the current LM does not begin with a break
+                    addInBetweenBreak(contentList, context, childLC);
+                }
+                if (childrenElements.size() == 1
+                        && ElementListUtils.startsWithForcedBreak(childrenElements)) {
+
+                    if (currentChildLM.isFinished() && !hasNextChildLM()) {
+                        // a descendant of this block has break-before
+                        forcedBreakAfterLast = (BreakElement) childrenElements.get(0);
+                        context.clearPendingMarks();
+                        break;
+                    }
+
+                    if (contentList.isEmpty()) {
+                        // Empty fo:block, zero-length box makes sure the IDs and/or markers
+                        // are registered and borders/padding are painted.
+                        elements.add(new KnuthBox(0, notifyPos(new Position(this)), false));
+                    }
+                    // a descendant of this block has break-before
+                    contentList.addAll(childrenElements);
+
+                    wrapPositionElements(contentList, elements);
+
+                    return elements;
+                } else {
+                    contentList.addAll(childrenElements);
+                    if (ElementListUtils.endsWithForcedBreak(childrenElements)) {
+                        // a descendant of this block has break-after
+                        if (currentChildLM.isFinished() && !hasNextChildLM()) {
+                            forcedBreakAfterLast = (BreakElement) ListUtil.removeLast(contentList);
+                            context.clearPendingMarks();
+                            break;
+                        }
+
+                        wrapPositionElements(contentList, elements);
+
+                        return elements;
+                    }
+                }
+                context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
+            }
+        }
+
+        if (!contentList.isEmpty()) {
+            wrapPositionElements(contentList, elements);
+        } else if (forcedBreakAfterLast == null) {
+            // Empty fo:block, zero-length box makes sure the IDs and/or markers
+            // are registered.
+            elements.add(new KnuthBox(0, notifyPos(new Position(this)), true));
+        }
+
+        addKnuthElementsForBorderPaddingAfter(elements, true);
+        addKnuthElementsForSpaceAfter(elements, alignment);
+
+        //All child content is processed. Only break-after can occur now, so...
+        context.clearPendingMarks();
+        if (forcedBreakAfterLast == null) {
+            addKnuthElementsForBreakAfter(elements, context);
+        } else {
+            forcedBreakAfterLast.clearPendingMarks();
+            elements.add(forcedBreakAfterLast);
+        }
+
+        context.updateKeepWithNextPending(getKeepWithNext());
+
+        setFinished(true);
+
+        return elements;
+    }
+
+    /** {@inheritDoc} */
+    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
+            Position restartPosition, LayoutManager restartAtLM) {
+        referenceIPD = context.getRefIPD();
+        updateContentAreaIPDwithOverconstrainedAdjust();
+
+        List contentList = new LinkedList();
+        List elements = new LinkedList();
+
+        if (!breakBeforeServed) {
+            breakBeforeServed = true;
+            if (!context.suppressBreakBefore()) {
+                if (addKnuthElementsForBreakBefore(elements, context)) {
+                    return elements;
+                }
+            }
+        }
+
+        if (!firstVisibleMarkServed) {
+            addKnuthElementsForSpaceBefore(elements, alignment);
+            context.updateKeepWithPreviousPending(getKeepWithPrevious());
+        }
+
+        addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed);
+        firstVisibleMarkServed = true;
+
+        //Spaces, border and padding to be repeated at each break
+        addPendingMarks(context);
+
+        //Used to indicate a special break-after case when all content has already been generated.
+        BreakElement forcedBreakAfterLast = null;
+
+        LayoutContext childLC = new LayoutContext(0);
+        List childrenElements;
+        LayoutManager currentChildLM;
+        if (lmStack.isEmpty()) {
+            assert restartAtLM != null && restartAtLM.getParent() == this;
+            currentChildLM = restartAtLM;
+            currentChildLM.reset();
+            setCurrentChildLM(currentChildLM);
+
+            childrenElements = getNextChildElements(currentChildLM, context, childLC,
+                    alignment);
+        } else {
+            currentChildLM = (BlockLevelLayoutManager) lmStack.pop();
+            setCurrentChildLM(currentChildLM);
+            childrenElements = getNextChildElements(currentChildLM, context, childLC, alignment,
+                    lmStack, restartPosition, restartAtLM);
+        }
+
+        if (contentList.isEmpty()) {
+            //Propagate keep-with-previous up from the first child
+            context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
+        }
+        if (childrenElements != null && !childrenElements.isEmpty()) {
+            if (!contentList.isEmpty()
+                    && !ElementListUtils.startsWithForcedBreak(childrenElements)) {
+                // there is a block handled by prevLM before the one
+                // handled by curLM, and the one handled
+                // by the current LM does not begin with a break
+                addInBetweenBreak(contentList, context, childLC);
+            }
+            if (childrenElements.size() == 1
+                    && ElementListUtils.startsWithForcedBreak(childrenElements)) {
 
-                if (curLM.isFinished() && !hasNextChildLM()) {
+                if (currentChildLM.isFinished() && !hasNextChildLM()) {
                     // a descendant of this block has break-before
-                    forcedBreakAfterLast = (BreakElement) returnedList.get(0);
+                    forcedBreakAfterLast = (BreakElement) childrenElements.get(0);
                     context.clearPendingMarks();
-                    break;
+//                    break; TODO
                 }
 
                 if (contentList.isEmpty()) {
                     // Empty fo:block, zero-length box makes sure the IDs and/or markers
                     // are registered and borders/padding are painted.
-                    returnList.add(new KnuthBox(0, notifyPos(new Position(this)), false));
+                    elements.add(new KnuthBox(0, notifyPos(new Position(this)), false));
                 }
                 // a descendant of this block has break-before
-                contentList.addAll(returnedList);
+                contentList.addAll(childrenElements);
 
-                /* extension: conversione di tutta la sequenza fin'ora ottenuta */
-                if (bpUnit > 0) {
-                    storedList = contentList;
-                    contentList = createUnitElements(contentList);
-                }
-                /* end of extension */
+                wrapPositionElements(contentList, elements);
 
-                // "wrap" the Position inside each element
-                // moving the elements from contentList to returnList
-                returnedList = new LinkedList();
-                wrapPositionElements(contentList, returnList);
-
-                return returnList;
+                return elements;
             } else {
-                if (returnedList == null || returnedList.isEmpty()) {
-                    //Avoid NoSuchElementException below (happens with empty blocks)
-                    continue;
+                contentList.addAll(childrenElements);
+                if (ElementListUtils.endsWithForcedBreak(childrenElements)) {
+                    // a descendant of this block has break-after
+                    if (currentChildLM.isFinished() && !hasNextChildLM()) {
+                        forcedBreakAfterLast = (BreakElement) ListUtil.removeLast(contentList);
+                        context.clearPendingMarks();
+//                        break; TODO
+                    }
+
+                    wrapPositionElements(contentList, elements);
+
+                    return elements;
                 }
-                if (prevLM != null
-                        && !ElementListUtils.startsWithForcedBreak(returnedList)) {
+            }
+            context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
+        }
+
+        while ((currentChildLM = (LayoutManager) getChildLM()) != null) {
+            currentChildLM.reset(); // TODO won't work with forced breaks
+
+            childLC = new LayoutContext(0);
+
+            childrenElements = getNextChildElements(currentChildLM, context, childLC,
+                    alignment);
+
+            if (contentList.isEmpty()) {
+                //Propagate keep-with-previous up from the first child
+                context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
+            }
+            if (childrenElements != null && !childrenElements.isEmpty()) {
+                if (!contentList.isEmpty()
+                        && !ElementListUtils.startsWithForcedBreak(childrenElements)) {
                     // there is a block handled by prevLM before the one
                     // handled by curLM, and the one handled
                     // by the current LM does not begin with a break
                     addInBetweenBreak(contentList, context, childLC);
                 }
-                contentList.addAll(returnedList);
-                if (ElementListUtils.endsWithForcedBreak(returnedList)) {
-                    // a descendant of this block has break-after
-                    if (curLM.isFinished() && !hasNextChildLM()) {
-                        forcedBreakAfterLast = (BreakElement) ListUtil
-                                .removeLast(contentList);
+                if (childrenElements.size() == 1
+                        && ElementListUtils.startsWithForcedBreak(childrenElements)) {
+
+                    if (currentChildLM.isFinished() && !hasNextChildLM()) {
+                        // a descendant of this block has break-before
+                        forcedBreakAfterLast = (BreakElement) childrenElements.get(0);
                         context.clearPendingMarks();
                         break;
                     }
 
-                    /* extension: conversione di tutta la sequenza fin'ora ottenuta */
-                    if (bpUnit > 0) {
-                        storedList = contentList;
-                        contentList = createUnitElements(contentList);
+                    if (contentList.isEmpty()) {
+                        // Empty fo:block, zero-length box makes sure the IDs and/or markers
+                        // are registered and borders/padding are painted.
+                        elements.add(new KnuthBox(0, notifyPos(new Position(this)), false));
                     }
-                    /* end of extension */
+                    // a descendant of this block has break-before
+                    contentList.addAll(childrenElements);
 
-                    returnedList = new LinkedList();
-                    wrapPositionElements(contentList, returnList);
+                    wrapPositionElements(contentList, elements);
+
+                    return elements;
+                } else {
+                    contentList.addAll(childrenElements);
+                    if (ElementListUtils.endsWithForcedBreak(childrenElements)) {
+                        // a descendant of this block has break-after
+                        if (currentChildLM.isFinished() && !hasNextChildLM()) {
+                            forcedBreakAfterLast = (BreakElement) ListUtil.removeLast(contentList);
+                            context.clearPendingMarks();
+                            break;
+                        }
 
-                    return returnList;
+                        wrapPositionElements(contentList, elements);
+
+                        return elements;
+                    }
                 }
+                context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
             }
-            // propagate and clear
-            context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
-            childLC.clearKeepsPending();
-            prevLM = curLM;
-        }
-
-        /* Extension: conversione di tutta la sequenza fin'ora ottenuta */
-        if (bpUnit > 0) {
-            storedList = contentList;
-            contentList = createUnitElements(contentList);
         }
-        /* end of extension */
 
-        returnedList = new LinkedList();
         if (!contentList.isEmpty()) {
-            wrapPositionElements(contentList, returnList);
+            wrapPositionElements(contentList, elements);
         } else if (forcedBreakAfterLast == null) {
             // Empty fo:block, zero-length box makes sure the IDs and/or markers
             // are registered.
-            returnList.add(new KnuthBox(0, notifyPos(new Position(this)), true));
+            elements.add(new KnuthBox(0, notifyPos(new Position(this)), true));
         }
 
-        addKnuthElementsForBorderPaddingAfter(returnList, true);
-        addKnuthElementsForSpaceAfter(returnList, alignment);
+        addKnuthElementsForBorderPaddingAfter(elements, true);
+        addKnuthElementsForSpaceAfter(elements, alignment);
 
         //All child content is processed. Only break-after can occur now, so...
         context.clearPendingMarks();
         if (forcedBreakAfterLast == null) {
-            addKnuthElementsForBreakAfter(returnList, context);
-        }
-
-        if (forcedBreakAfterLast != null) {
+            addKnuthElementsForBreakAfter(elements, context);
+        } else {
             forcedBreakAfterLast.clearPendingMarks();
-            returnList.add(forcedBreakAfterLast);
+            elements.add(forcedBreakAfterLast);
         }
 
-        context.updateKeepWithNextPending(getKeepWithNextStrength());
+        context.updateKeepWithNextPending(getKeepWithNext());
 
         setFinished(true);
 
-        return returnList;
+        return elements;
+    }
+
+    private List getNextChildElements(LayoutManager childLM, LayoutContext context,
+            LayoutContext childLC, int alignment) {
+        return getNextChildElements(childLM, context, childLC, alignment, null, null, null);
+    }
+
+    private List getNextChildElements(LayoutManager childLM, LayoutContext context,
+            LayoutContext childLC, int alignment, Stack lmStack, Position restartPosition,
+            LayoutManager restartAtLM) {
+        childLC.copyPendingMarksFrom(context);
+        childLC.setStackLimitBP(context.getStackLimitBP());
+        if (childLM instanceof LineLayoutManager) {
+            childLC.setRefIPD(getContentAreaIPD());
+        } else {
+            childLC.setRefIPD(referenceIPD);
+        }
+        if (childLM == this.childLMs.get(0)) {
+            childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
+            //Handled already by the parent (break collapsing, see above)
+        }
+
+        if (lmStack == null) {
+            return childLM.getNextKnuthElements(childLC, alignment);
+        } else {
+            if (childLM instanceof LineLayoutManager) {
+                return ((LineLayoutManager) childLM).getNextKnuthElements(childLC, alignment,
+                        (LeafPosition) restartPosition);
+            } else {
+                return childLM.getNextKnuthElements(childLC, alignment,
+                        lmStack, restartPosition, restartAtLM);
+            }
+        }
     }
 
     /**
      * Adds a break element to the content list between individual child elements.
-     * @param contentList the content list to populate
-     * @param context the current layout context
+     * @param contentList
+     * @param parentLC
      * @param childLC the currently active child layout context
      */
-    protected void addInBetweenBreak(List contentList, LayoutContext context,
-            LayoutContext childLC) {
+    protected void addInBetweenBreak(List contentList, LayoutContext parentLC,
+                                     LayoutContext childLC) {
+
         if (mustKeepTogether()
-                || context.isKeepWithNextPending()
+                || parentLC.isKeepWithNextPending()
                 || childLC.isKeepWithPreviousPending()) {
 
-            int strength = getKeepTogetherStrength();
+            Keep keep = getKeepTogether();
 
             //Handle pending keep-with-next
-            strength = Math.max(strength, context.getKeepWithNextPending());
-            context.clearKeepWithNextPending();
+            keep = keep.compare(parentLC.getKeepWithNextPending());
+            parentLC.clearKeepWithNextPending();
 
             //Handle pending keep-with-previous from child LM
-            strength = Math.max(strength, childLC.getKeepWithPreviousPending());
+            keep = keep.compare(childLC.getKeepWithPreviousPending());
             childLC.clearKeepWithPreviousPending();
 
-            int penalty = KeepUtil.getPenaltyForKeep(strength);
-
             // add a penalty to forbid or discourage a break between blocks
             contentList.add(new BreakElement(
-                    new Position(this), penalty, context));
+                    new Position(this), keep.getPenalty(),
+                    keep.getContext(), parentLC));
             return;
         }
 
@@ -481,7 +637,7 @@
 
             // add a null penalty to allow a break between blocks
             contentList.add(new BreakElement(
-                    new Position(this), 0, context));
+                    new Position(this), 0, Constants.EN_AUTO, parentLC));
         }
     }
 
@@ -817,33 +973,77 @@
      * Retrieves and returns the keep-together strength from the parent element.
      * @return the keep-together strength
      */
-    protected int getParentKeepTogetherStrength() {
-        int strength = KEEP_AUTO;
+    protected Keep getParentKeepTogether() {
+        Keep keep = Keep.KEEP_AUTO;
         if (getParent() instanceof BlockLevelLayoutManager) {
-            strength = ((BlockLevelLayoutManager)getParent()).getKeepTogetherStrength();
+            keep = ((BlockLevelLayoutManager)getParent()).getKeepTogether();
         } else if (getParent() instanceof InlineLayoutManager) {
             if (((InlineLayoutManager) getParent()).mustKeepTogether()) {
-                strength = KEEP_ALWAYS;
+                keep = Keep.KEEP_ALWAYS;
             }
             //TODO Fix me
             //strength = ((InlineLayoutManager) getParent()).getKeepTogetherStrength();
         }
-        return strength;
+        return keep;
     }
 
     /** {@inheritDoc} */
     public boolean mustKeepTogether() {
-        return getKeepTogetherStrength() > KEEP_AUTO;
+        return !getKeepTogether().isAuto();
     }
 
     /** {@inheritDoc} */
     public boolean mustKeepWithPrevious() {
-        return getKeepWithPreviousStrength() > KEEP_AUTO;
+        return !getKeepWithPrevious().isAuto();
     }
 
     /** {@inheritDoc} */
     public boolean mustKeepWithNext() {
-        return getKeepWithNextStrength() > KEEP_AUTO;
+        return !getKeepWithNext().isAuto();
+    }
+
+    /** {@inheritDoc} */
+    public Keep getKeepTogether() {
+        Keep keep = Keep.getKeep(getKeepTogetherProperty());
+        keep = keep.compare(getParentKeepTogether());
+        return keep;
+    }
+
+    /** {@inheritDoc} */
+    public Keep getKeepWithPrevious() {
+        return Keep.getKeep(getKeepWithPreviousProperty());
+    }
+
+    /** {@inheritDoc} */
+    public Keep getKeepWithNext() {
+        return Keep.getKeep(getKeepWithNextProperty());
+    }
+
+    /**
+     * {@inheritDoc}
+     * Default implementation throws {@code IllegalStateException}
+     * Must be implemented by the subclass, if applicable.
+     */
+    public KeepProperty getKeepTogetherProperty() {
+        throw new IllegalStateException();
+    }
+
+    /**
+     * {@inheritDoc}
+     * Default implementation throws {@code IllegalStateException}
+     * Must be implemented by the subclass, if applicable.
+     */
+    public KeepProperty getKeepWithPreviousProperty() {
+        throw new IllegalStateException();
+    }
+
+    /**
+     * {@inheritDoc}
+     * Default implementation throws {@code IllegalStateException}
+     * Must be implemented by the subclass, if applicable.
+     */
+    public KeepProperty getKeepWithNextProperty() {
+        throw new IllegalStateException();
     }
 
     /**
@@ -1608,5 +1808,13 @@
         return -1;
     }
 
+    /** {@inheritDoc} */
+    public void reset() {
+        super.reset();
+        breakBeforeServed = false;
+        firstVisibleMarkServed = false;
+        // TODO startIndent, endIndent
+    }
+
 }
 

Modified: xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BreakElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BreakElement.java?rev=816718&r1=816717&r2=816718&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BreakElement.java (original)
+++ xmlgraphics/fop/branches/Temp_Accessibility/src/java/org/apache/fop/layoutmgr/BreakElement.java Fri Sep 18 17:10:42 2009
@@ -41,7 +41,22 @@
      * @param context the layout context which contains the pending conditional elements
      */
     public BreakElement(Position position, int penaltyValue, LayoutContext context) {
-        this(position, 0, penaltyValue, -1, context);
+        this(position, penaltyValue, -1, context);
+    }
+
+    /**
+     * Create a new BreakElement for the given {@code position}, {@code penaltyValue}
+     * and {@code breakClass}. (Used principally to generate break-possibilities in
+     * ranges of content that must be kept together within the context corresponding
+     * to the {@code breakClass}; expected to be one of {@link Constants#EN_AUTO},
+     * {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or {@link Constants#EN_PAGE})
+     * @param position  the corresponding {@link Position}
+     * @param penaltyValue  the penalty value
+     * @param breakClass    the break class
+     * @param context       the {@link LayoutContext}
+     */
+    public BreakElement(Position position, int penaltyValue, int breakClass, LayoutContext context) {
+        this(position, 0, penaltyValue, breakClass, context);
     }
 
     /**
@@ -65,6 +80,10 @@
         this.pendingAfterMarks = context.getPendingAfterMarks();
     }
 
+    private static String getBreakClassName(int breakClass) {
+        return AbstractBreaker.getBreakClassName(breakClass);
+    }
+
     /** {@inheritDoc} */
     public boolean isConditional() {
         return false; //Does not really apply here
@@ -143,27 +162,17 @@
 
     /** {@inheritDoc} */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuffer sb = new StringBuffer(64);
         sb.append("BreakPossibility[p:");
-        sb.append(this.penaltyValue);
+        sb.append(KnuthPenalty.valueOf(this.penaltyValue));
         if (isForcedBreak()) {
-            sb.append(" (forced break");
-            switch (getBreakClass()) {
-            case Constants.EN_PAGE:
-                sb.append(", page");
-                break;
-            case Constants.EN_COLUMN:
-                sb.append(", column");
-                break;
-            case Constants.EN_EVEN_PAGE:
-                sb.append(", even page");
-                break;
-            case Constants.EN_ODD_PAGE:
-                sb.append(", odd page");
-                break;
-            default:
-            }
-            sb.append(")");
+            sb.append(" (forced break, ")
+                    .append(getBreakClassName(this.breakClass))
+                    .append(")");
+        } else if (this.penaltyValue >= 0 && this.breakClass != -1) {
+            sb.append(" (keep constraint, ")
+                    .append(getBreakClassName(this.breakClass))
+                    .append(")");
         }
         sb.append("; w:");
         sb.append(penaltyWidth);



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