]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Merged branches/Temp_BasicSideFloat back to trunk.
authorLuis Bernardo <lbernardo@apache.org>
Tue, 2 Dec 2014 00:29:57 +0000 (00:29 +0000)
committerLuis Bernardo <lbernardo@apache.org>
Tue, 2 Dec 2014 00:29:57 +0000 (00:29 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1642793 13f79535-47bb-0310-9956-ffa450edef68

37 files changed:
src/java/org/apache/fop/area/Area.java
src/java/org/apache/fop/area/Block.java
src/java/org/apache/fop/area/BlockParent.java
src/java/org/apache/fop/area/BlockViewport.java
src/java/org/apache/fop/area/LineArea.java
src/java/org/apache/fop/area/SideFloat.java [new file with mode: 0644]
src/java/org/apache/fop/area/inline/InlineViewport.java
src/java/org/apache/fop/area/inline/TextArea.java
src/java/org/apache/fop/fo/XMLWhiteSpaceHandler.java
src/java/org/apache/fop/fo/flow/Float.java
src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java
src/java/org/apache/fop/layoutmgr/FloatContentLayoutManager.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java
src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
src/java/org/apache/fop/layoutmgr/PageBreaker.java
src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
src/java/org/apache/fop/layoutmgr/SpaceResolver.java
src/java/org/apache/fop/layoutmgr/inline/FloatLayoutManager.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java
src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
test/java/org/apache/fop/layoutengine/LayoutEngineTestCase.java
test/layoutengine/standard-testcases/float_1.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/float_2.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/float_3.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/float_4.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/float_5.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/float_6.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/float_7.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_4.xml
test/layoutengine/standard-testcases/flow_changing-ipd_5.xml [new file with mode: 0644]

index 628e9e3ad0396b58559f5c3ec9f3a775d08a6cbe..895367c19398c9201eb1278427956f8e1abddf04 100644 (file)
@@ -111,6 +111,8 @@ public class Area extends AreaTreeObject implements Serializable {
     /** the area's block-progression-dimension */
     protected int bpd;
 
+    protected int effectiveIPD = -1;
+
     /**
      * Resolved bidirectional level for area.
      */
@@ -208,6 +210,10 @@ public class Area extends AreaTreeObject implements Serializable {
         return getBorderAndPaddingWidthStart() + getIPD() + getBorderAndPaddingWidthEnd();
     }
 
+    public int getEffectiveAllocIPD() {
+        return getBorderAndPaddingWidthStart() + getEffectiveIPD() + getBorderAndPaddingWidthEnd();
+    }
+
     /**
      * Get the allocation block progression dimension of this area.
      * This adds the content, borders, padding and spaces to find the
@@ -499,4 +505,14 @@ public class Area extends AreaTreeObject implements Serializable {
         sb.append("}");
         return sb.toString();
     }
+
+    public int getEffectiveIPD() {
+        return 0;
+    }
+
+    public void activateEffectiveIPD() {
+        if (effectiveIPD != -1) {
+            ipd = effectiveIPD;
+        }
+    }
 }
index e04a5dc43697fff39183291db344d75ff89e0ce8..565146415548cedd39c67118bdb0208d6ed67826 100644 (file)
@@ -184,5 +184,21 @@ public class Block extends BlockParent {
         return location;
     }
 
+    // maybe this can be done in the parent?
+    public int getEffectiveIPD() {
+        int eIPD = super.getEffectiveIPD();
+        if (eIPD != 0) {
+            effectiveIPD = eIPD;
+        }
+        return eIPD;
+    }
+
+    // maybe this can be done in the parent?
+    public void activateEffectiveIPD() {
+        super.activateEffectiveIPD();
+        if (effectiveIPD != -1) {
+            ipd = effectiveIPD;
+        }
+    }
 }
 
index 72baaeccf57e3111c427d027614c5c3e128024fa..fa599f31ad18f8a889b58c0a7e6afc15738c9d2e 100644 (file)
@@ -123,4 +123,25 @@ public class BlockParent extends Area {
     public int getYOffset() {
         return yOffset;
     }
+
+    public int getEffectiveIPD() {
+        int maxIPD = 0;
+        if (children != null) {
+            for (Area area : children) {
+                int effectiveIPD = area.getEffectiveIPD();
+                if (effectiveIPD > maxIPD) {
+                    maxIPD = effectiveIPD;
+                }
+            }
+        }
+        return maxIPD;
+    }
+
+    public void activateEffectiveIPD() {
+        if (children != null) {
+            for (Area area : children) {
+                area.activateEffectiveIPD();
+            }
+        }
+    }
 }
index 58d8d21061a9327867e9bee4296e567806db293e..d33a060e46c46884cdf95696c9e94af27947099c 100644 (file)
@@ -93,5 +93,9 @@ public class BlockViewport extends Block implements Viewport  {
             return null;
         }
     }
+
+    public int getEffectiveIPD() {
+        return getIPD();
+    }
 }
 
index 3213eb588764363e60bb1cd3dad905c66f18f2e8..8639b8201aa1ffbbf9d8f13443dafaa93565a438 100644 (file)
@@ -283,5 +283,19 @@ public class LineArea extends Area {
             // been handled, modifying the line indent
         }
     }
+
+    public int getEffectiveIPD() {
+        int maxIPD = 0;
+        if (inlineAreas != null) {
+            for (Area area : inlineAreas) {
+                int effectiveIPD = area.getEffectiveIPD();
+                if (effectiveIPD > maxIPD) {
+                    maxIPD = effectiveIPD;
+                }
+            }
+        }
+        return maxIPD;
+    }
+
 }
 
diff --git a/src/java/org/apache/fop/area/SideFloat.java b/src/java/org/apache/fop/area/SideFloat.java
new file mode 100644 (file)
index 0000000..af653ef
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.area;
+
+public class SideFloat extends Block {
+
+    private static final long serialVersionUID = 2058594336594375047L;
+
+    public SideFloat() {
+        setAreaClass(Area.CLASS_SIDE_FLOAT);
+        addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
+        setPositioning(Block.ABSOLUTE);
+    }
+}
index 32c4c12354423cf3c3cf9ebcfe8f6905e8516474..e111bdd9df80d5c03e42886425d2b72dd879fa51 100644 (file)
@@ -149,4 +149,7 @@ public class InlineViewport extends InlineArea implements Viewport {
         this.content = (Area) in.readObject();
     }
 
+    public int getEffectiveIPD() {
+        return getIPD();
+    }
 }
index a8d07148f0e9a606daa62b515df8ef02178be246..91a75d558b5a83ad0b195db59dcb3759754f6fa9 100644 (file)
@@ -209,5 +209,8 @@ public class TextArea extends AbstractTextArea {
         }
     }
 
+    public int getEffectiveIPD() {
+        return getIPD();
+    }
 }
 
index e37618736777b72ab794a40264fc0aa49a09fd6c..cc06ca26afd212e5574aa05723aaab1fe5cac2df 100644 (file)
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Stack;
 
 import org.apache.fop.fo.flow.Block;
+import org.apache.fop.fo.flow.Float;
 import org.apache.fop.util.CharUtilities;
 
 /**
@@ -157,6 +158,10 @@ public class XMLWhiteSpaceHandler {
 
         charIter = new RecursiveCharIterator(fo, firstTextNode);
         inWhiteSpace = false;
+        if (firstTextNode.siblings != null && firstTextNode.siblings[0] != null
+                && firstTextNode.siblings[0].getNameId() == Constants.FO_FLOAT) {
+            inWhiteSpace = ((Float) firstTextNode.siblings[0]).getInWhiteSpace();
+        }
 
         if (fo == currentBlock
                 || currentBlock == null
@@ -232,6 +237,9 @@ public class XMLWhiteSpaceHandler {
                 firstWhiteSpaceInSeq = null;
             }
         }
+        if (nextChild instanceof Float) {
+            ((Float) nextChild).setInWhiteSpace(inWhiteSpace);
+        }
     }
 
     /**
index 3fb273042a768d8824478f85f35af833ad61a3c3..a10d9c74dd5de3315d1d6091eb64b27eda2d0ece 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.fop.fo.flow;
 
 // XML
+import org.xml.sax.Attributes;
 import org.xml.sax.Locator;
 
 import org.apache.fop.apps.FOPException;
@@ -34,11 +35,11 @@ import org.apache.fop.fo.ValidationException;
  */
 public class Float extends FObj {
     // The value of properties relevant for fo:float (commented out for performance.
-    //     private int float_;
-    //     private int clear;
+    private int foFloat;
+    private int clear;
     // End of property values
-
-    private static boolean notImplementedWarningGiven;
+    private boolean inWhiteSpace;
+    private boolean disabled;
 
     /**
      * Base constructor
@@ -47,17 +48,13 @@ public class Float extends FObj {
      */
     public Float(FONode parent) {
         super(parent);
-
-        if (!notImplementedWarningGiven) {
-            getFOValidationEventProducer().unimplementedFeature(this, getName(),
-                    getName(), getLocator());
-            notImplementedWarningGiven = true;
-        }
     }
 
     /** {@inheritDoc} */
     public void bind(PropertyList pList) throws FOPException {
-        // No active properties -> Nothing to do.
+        super.bind(pList);
+        foFloat = pList.get(PR_FLOAT).getEnum();
+        clear = pList.get(PR_CLEAR).getEnum();
     }
 
     /**
@@ -92,4 +89,30 @@ public class Float extends FObj {
     public int getNameId() {
         return FO_FLOAT;
     }
+
+    public int getFloat() {
+        return foFloat;
+    }
+
+    public void setInWhiteSpace(boolean iws) {
+        inWhiteSpace = iws;
+    }
+
+    public boolean getInWhiteSpace() {
+        return inWhiteSpace;
+    }
+
+    public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList pList)
+            throws FOPException {
+        if (findAncestor(FO_TABLE) > 0) {
+            disabled = true;
+            getFOValidationEventProducer().unimplementedFeature(this, "fo:table", getName(), getLocator());
+        } else {
+            super.processNode(elementName, locator, attlist, pList);
+        }
+    }
+
+    public boolean isDisabled() {
+        return disabled;
+    }
 }
index cdfa4829538be6de38af74ee679b4c051f55a72b..e1c6b3a74ea363b0f5df6df8fbfef31ee4a3d9d9 100644 (file)
@@ -67,6 +67,17 @@ public abstract class AbstractBreaker {
         }
     }
 
+    public static class FloatPosition extends LeafPosition {
+        double bpdAdjust; // Percentage to adjust (stretch or shrink)
+        int difference;
+
+        FloatPosition(LayoutManager lm, int breakIndex, double bpdA, int diff) {
+            super(lm, breakIndex);
+            bpdAdjust = bpdA;
+            difference = diff;
+        }
+    }
+
     /**
      * Helper method, mainly used to improve debug/trace output
      * @param breakClassId  the {@link Constants} enum value.
@@ -195,9 +206,12 @@ public abstract class AbstractBreaker {
     }
 
     // used by doLayout and getNextBlockList*
-    private List<BlockSequence> blockLists;
+    protected List<BlockSequence> blockLists;
 
     private boolean empty = true;
+    /** blockListIndex of the current BlockSequence in blockLists */
+    protected int blockListIndex;
+
 
     /** desired text alignment */
     protected int alignment;
@@ -372,7 +386,7 @@ public abstract class AbstractBreaker {
 
             //*** Phases 2 and 3 ***
             log.debug("PLM> blockLists.size() = " + blockLists.size());
-            for (int blockListIndex = 0; blockListIndex < blockLists.size(); blockListIndex++) {
+            for (blockListIndex = 0; blockListIndex < blockLists.size(); blockListIndex++) {
                 blockList = blockLists.get(blockListIndex);
 
                 //debug code start
@@ -394,7 +408,10 @@ public abstract class AbstractBreaker {
                 alg.setConstantLineWidth(flowBPD);
                 int optimalPageCount = alg.findBreakingPoints(blockList, 1, true,
                         BreakingAlgorithm.ALL_BREAKS);
-                if (Math.abs(alg.getIPDdifference()) > 1) {
+
+                if (alg.handlingFloat()) {
+                    nextSequenceStartsOn = handleFloatLayout(alg, optimalPageCount, blockList, childLC);
+                } else if (Math.abs(alg.getIPDdifference()) > 1) {
                     addAreas(alg, optimalPageCount, blockList, blockList);
                     // *** redo Phase 1 ***
                     log.trace("IPD changes after page " + optimalPageCount);
@@ -476,14 +493,14 @@ public abstract class AbstractBreaker {
         for (int p = startPart; p < startPart + partCount; p++) {
             PageBreakPosition pbp = alg.getPageBreaks().get(p);
 
-            //Check the last break position for forced breaks
+            // Check the last break position for forced breaks
             int lastBreakClass;
             if (p == 0) {
                 lastBreakClass = effectiveList.getStartOn();
             } else {
                 ListElement lastBreakElement = effectiveList.getElement(endElementIndex);
                 if (lastBreakElement.isPenalty()) {
-                    KnuthPenalty pen = (KnuthPenalty)lastBreakElement;
+                    KnuthPenalty pen = (KnuthPenalty) lastBreakElement;
                     if (pen.getPenalty() == KnuthPenalty.INFINITE) {
                         /**
                          * That means that there was a keep.within-page="always", but that
@@ -500,14 +517,12 @@ public abstract class AbstractBreaker {
                 }
             }
 
-            //the end of the new part
+            // the end of the new part
             endElementIndex = pbp.getLeafPos();
 
             // ignore the first elements added by the
             // PageSequenceLayoutManager
-            startElementIndex += (startElementIndex == 0)
-                    ? effectiveList.ignoreAtStart
-                    : 0;
+            startElementIndex += (startElementIndex == 0) ? effectiveList.ignoreAtStart : 0;
 
             log.debug("PLM> part: " + (p + 1)
                     + ", start at pos " + startElementIndex
@@ -518,20 +533,17 @@ public abstract class AbstractBreaker {
 
             int displayAlign = getCurrentDisplayAlign();
 
-            //The following is needed by SpaceResolver.performConditionalsNotification()
-            //further down as there may be important Position elements in the element list trailer
+            // The following is needed by SpaceResolver.performConditionalsNotification()
+            // further down as there may be important Position elements in the element list trailer
             int notificationEndElementIndex = endElementIndex;
 
             // ignore the last elements added by the
             // PageSequenceLayoutManager
-            endElementIndex -= (endElementIndex == (originalList.size() - 1))
-                    ? effectiveList.ignoreAtEnd
-                    : 0;
+            endElementIndex -= (endElementIndex == (originalList.size() - 1)) ? effectiveList.ignoreAtEnd : 0;
 
             // ignore the last element in the page if it is a KnuthGlue
             // object
-            if (((KnuthElement) effectiveList.get(endElementIndex))
-                    .isGlue()) {
+            if (((KnuthElement) effectiveList.get(endElementIndex)).isGlue()) {
                 endElementIndex--;
             }
 
@@ -556,13 +568,12 @@ public abstract class AbstractBreaker {
                 }
 
                 // Handle SpaceHandling(Break)Positions, see SpaceResolver!
-                SpaceResolver.performConditionalsNotification(effectiveList,
-                        startElementIndex, notificationEndElementIndex, lastBreak);
+                SpaceResolver.performConditionalsNotification(effectiveList, startElementIndex,
+                        notificationEndElementIndex, lastBreak);
                 // Add areas now!
-                addAreas(new KnuthPossPosIter(effectiveList,
-                        startElementIndex, endElementIndex + 1), childLC);
+                addAreas(new KnuthPossPosIter(effectiveList, startElementIndex, endElementIndex + 1), childLC);
             } else {
-                //no content for this part
+                // no content for this part
                 handleEmptyContent();
             }
 
@@ -571,6 +582,10 @@ public abstract class AbstractBreaker {
             lastBreak = endElementIndex;
             startElementIndex = pbp.getLeafPos() + 1;
         }
+        if (alg.handlingFloat()) {
+            addAreasForFloats(alg, startPart, partCount, originalList, effectiveList, childLC, lastBreak,
+                    startElementIndex, endElementIndex);
+        }
     }
     /**
      * Notifies the layout managers about the space and conditional length situation based on
@@ -774,4 +789,14 @@ public abstract class AbstractBreaker {
         return nextSequenceStartsOn;
     }
 
+    protected int handleFloatLayout(PageBreakingAlgorithm alg, int optimalPageCount, BlockSequence blockList,
+            LayoutContext childLC) {
+        throw new IllegalStateException();
+    }
+
+    protected void addAreasForFloats(PageBreakingAlgorithm alg, int startPart, int partCount,
+            BlockSequence originalList, BlockSequence effectiveList, final LayoutContext childLC,
+            int lastBreak, int startElementIndex, int endElementIndex) {
+        throw new IllegalStateException();
+    }
 }
index 2dd18e4ee381e5019d73d02fe214705fab5e3ad0..5eac70548e0ea3e754ed79b00c0526c9402f8bb0 100644 (file)
@@ -537,4 +537,11 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager im
         }
         ((AbstractLayoutManager) lm).possiblyRegisterMarkersForTables(markers, isStarting, isFirst, isLast);
     }
+
+    public boolean handlingFloat() {
+        if (parentLayoutManager != null && parentLayoutManager instanceof AbstractLayoutManager) {
+            return ((AbstractLayoutManager) parentLayoutManager).handlingFloat();
+        }
+        return false;
+    }
 }
index d57588db832cda78e0929acb7d8dba3b2d435528..e060226c402d7186631b166c8d4685be11b35b99 100644 (file)
@@ -558,6 +558,9 @@ public abstract class BreakingAlgorithm {
                     elementIndex, previousIsBox, allowedBreaks).isBox();
 
             if (activeNodeCount == 0) {
+                if (handlingFloat()) {
+                    return handleFloat();
+                }
                 if (getIPDdifference() != 0) {
                     return handleIpdChange();
                 }
@@ -945,8 +948,11 @@ public abstract class BreakingAlgorithm {
                     log.trace("\tline=" + line);
                 }
 
+                if (element.isForcedBreak() && handlingFloat()) {
+                    disableFloatHandling(); // so that we do not create a float edge position later
+                }
                 // The line would be too long.
-                if (r < -1 || element.isForcedBreak()) {
+                if (r < -1 || element.isForcedBreak() || handlingFloat()) {
                     deactivateNode(node, line);
                 }
 
@@ -1028,6 +1034,13 @@ public abstract class BreakingAlgorithm {
             }
         }
 
+        createForcedNodes(node, line, elementIdx, difference, r, demerits, fitnessClass, availableShrink,
+                availableStretch, newWidth, newStretch, newShrink);
+    }
+
+    protected void createForcedNodes(KnuthNode node, int line, int elementIdx, int difference, double r,
+            double demerits, int fitnessClass, int availableShrink, int availableStretch, int newWidth,
+            int newStretch, int newShrink) {
         if (r <= -1) {
             log.debug("Considering tooLong, demerits=" + demerits);
             if (lastTooLong == null || demerits < lastTooLong.totalDemerits) {
@@ -1042,10 +1055,9 @@ public abstract class BreakingAlgorithm {
         } else {
             if (lastTooShort == null || demerits <= lastTooShort.totalDemerits) {
                 if (considerTooShort) {
-                    //consider possibilities which are too short
-                    best.addRecord(demerits, node, r,
-                            availableShrink, availableStretch,
-                            difference, fitnessClass);
+                    // consider possibilities which are too short
+                    best.addRecord(demerits, node, r, availableShrink, availableStretch, difference,
+                            fitnessClass);
                 }
                 lastTooShort = createNode(elementIdx, line + 1, fitnessClass,
                         newWidth, newStretch, newShrink,
@@ -1451,4 +1463,15 @@ public abstract class BreakingAlgorithm {
         return this.alignmentLast;
     }
 
+    protected boolean handlingFloat() {
+        return false;
+    }
+
+    protected int handleFloat() {
+        throw new IllegalStateException();
+    }
+
+    protected void disableFloatHandling() {
+        throw new IllegalStateException();
+    }
 }
diff --git a/src/java/org/apache/fop/layoutmgr/FloatContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FloatContentLayoutManager.java
new file mode 100644 (file)
index 0000000..5c6f6c6
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.fop.area.Area;
+import org.apache.fop.area.SideFloat;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.flow.Float;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.layoutmgr.inline.FloatLayoutManager;
+import org.apache.fop.layoutmgr.inline.KnuthInlineBox;
+
+public class FloatContentLayoutManager extends SpacedBorderedPaddedBlockLayoutManager {
+
+    private SideFloat floatContentArea;
+    private int side;
+    private int yOffset;
+
+    public FloatContentLayoutManager(Float node) {
+        super(node);
+        generatesReferenceArea = true;
+        side = node.getFloat();
+    }
+
+    public Keep getKeepTogether() {
+        return getParentKeepTogether();
+    }
+
+    public Keep getKeepWithNext() {
+        return Keep.KEEP_AUTO;
+    }
+
+    public Keep getKeepWithPrevious() {
+        return Keep.KEEP_ALWAYS;
+    }
+
+    public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) {
+        floatContentArea = new SideFloat();
+        AreaAdditionUtil.addAreas(this, parentIter, layoutContext);
+        flush();
+    }
+
+    public void addChildArea(Area childArea) {
+        floatContentArea.addChildArea(childArea);
+        floatContentArea.setBPD(childArea.getAllocBPD());
+        int effectiveContentIPD = childArea.getEffectiveAllocIPD();
+        int contentIPD = childArea.getIPD();
+        int xOffset = childArea.getBorderAndPaddingWidthStart();
+        floatContentArea.setIPD(effectiveContentIPD);
+        childArea.activateEffectiveIPD();
+        if (side == Constants.EN_END || side == Constants.EN_RIGHT) {
+            xOffset += getStartIndent();
+            floatContentArea.setXOffset(xOffset + contentIPD - effectiveContentIPD);
+        } else if (side == Constants.EN_START || side == Constants.EN_LEFT) {
+            floatContentArea.setXOffset(xOffset);
+        }
+        LayoutManager lm = parentLayoutManager;
+        while (!lm.getGeneratesReferenceArea()) {
+            lm = lm.getParent();
+        }
+        yOffset = lm.getParentArea(floatContentArea).getBPD();
+        lm.addChildArea(floatContentArea);
+        if (side == Constants.EN_END || side == Constants.EN_RIGHT) {
+            lm.getPSLM().setEndIntrusionAdjustment(effectiveContentIPD);
+        } else if (side == Constants.EN_START || side == Constants.EN_LEFT) {
+            lm.getPSLM().setStartIntrusionAdjustment(effectiveContentIPD);
+        }
+    }
+
+    public static List<FloatContentLayoutManager> checkForFloats(List<ListElement> elemenList,
+            int startIndex, int endIndex) {
+        ListIterator<ListElement> iter = elemenList.listIterator(startIndex);
+        List<FloatContentLayoutManager> floats = new ArrayList<FloatContentLayoutManager>();
+        while (iter.nextIndex() <= endIndex) {
+            ListElement element = iter.next();
+            if (element instanceof KnuthInlineBox && ((KnuthInlineBox) element).isFloatAnchor()) {
+                floats.add(((KnuthInlineBox) element).getFloatContentLM());
+            } else if (element instanceof KnuthBlockBox && ((KnuthBlockBox) element).hasFloatAnchors()) {
+                floats.addAll(((KnuthBlockBox) element).getFloatContentLMs());
+            }
+        }
+        if (floats.isEmpty()) {
+            return Collections.emptyList();
+        } else {
+            return floats;
+        }
+    }
+
+    protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
+        return null;
+    }
+
+    public void processAreas(LayoutContext layoutContext) {
+        if (getParent() instanceof FloatLayoutManager) {
+            FloatLayoutManager flm = (FloatLayoutManager) getParent();
+            flm.processAreas(layoutContext);
+        }
+    }
+
+    public int getFloatHeight() {
+        return floatContentArea.getAllocBPD();
+    }
+
+    public int getFloatYOffset() {
+        return yOffset;
+    }
+
+    private int getStartIndent() {
+        int startIndent = 0;
+        LayoutManager lm = getParent();
+        while (!(lm instanceof BlockLayoutManager)) {
+            lm = lm.getParent();
+        }
+        if (lm instanceof BlockLayoutManager) {
+            startIndent = ((BlockLayoutManager) lm).startIndent;
+        }
+        return startIndent;
+    }
+}
index d37f3b021d0ac2afa49488591c8587c46783dc38..227acbfd37e1a82dc0421dd966690fe2f50c83ce 100644 (file)
@@ -49,6 +49,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager {
     /** Array of areas currently being filled stored by area class */
     private final BlockParent[] currentAreas = new BlockParent[Area.CLASS_MAX];
 
+    private boolean handlingFloat;
+
     /**
      * This is the top level layout manager.
      * It is created by the PageSequence FO.
@@ -374,6 +376,10 @@ public class FlowLayoutManager extends BlockStackingLayoutManager {
      */
     @Override
     public void addChildArea(Area childArea) {
+        if (childArea instanceof BlockParent && handlingFloat()) {
+            BlockParent bp = (BlockParent) childArea;
+            bp.setXOffset(getPSLM().getStartIntrusionAdjustment());
+        }
         getParentArea(childArea);
         addChildToArea(childArea,
                           this.currentAreas[childArea.getAreaClass()]);
@@ -385,7 +391,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager {
         BlockParent parentArea = null;
         int aclass = childArea.getAreaClass();
 
-        if (aclass == Area.CLASS_NORMAL) {
+        if (aclass == Area.CLASS_NORMAL || aclass == Area.CLASS_SIDE_FLOAT) {
             parentArea = getCurrentPV().getCurrentFlow();
         } else if (aclass == Area.CLASS_BEFORE_FLOAT) {
             parentArea = getCurrentPV().getBodyRegion().getBeforeFloat();
@@ -407,7 +413,8 @@ public class FlowLayoutManager extends BlockStackingLayoutManager {
      */
     @Override
     public int getContentAreaIPD() {
-        return getCurrentPV().getCurrentSpan().getColumnWidth();
+        int flowIPD = getPSLM().getCurrentColumnWidth();
+        return flowIPD;
     }
 
     /**
@@ -425,5 +432,16 @@ public class FlowLayoutManager extends BlockStackingLayoutManager {
         return true;
     }
 
+    public void handleFloatOn() {
+        handlingFloat = true;
+    }
+
+    public void handleFloatOff() {
+        handlingFloat = false;
+    }
+
+    public boolean handlingFloat() {
+        return handlingFloat;
+    }
 }
 
index 530c6609a2efc94c2fe6f57879b916a81f255261..92ae1aacf51d450ea7884bffc1fd2814bb4b7059 100644 (file)
@@ -36,6 +36,7 @@ public class KnuthBlockBox extends KnuthBox {
      */
     private int bpd;
     private List<FootnoteBodyLayoutManager> footnoteList;
+    private List<FloatContentLayoutManager> floatContentLMs;
     /** List of Knuth elements. This is a list of LinkedList elements. */
     private List elementLists;
 
@@ -53,6 +54,7 @@ public class KnuthBlockBox extends KnuthBox {
         ipdRange = range;
         bpd = bpdim;
         footnoteList = new LinkedList<FootnoteBodyLayoutManager>();
+        floatContentLMs = new LinkedList<FloatContentLayoutManager>();
     }
 
     /**
@@ -69,6 +71,16 @@ public class KnuthBlockBox extends KnuthBox {
         ipdRange = MinOptMax.ZERO;
         bpd = 0;
         footnoteList = new LinkedList<FootnoteBodyLayoutManager>(list);
+        floatContentLMs = new LinkedList<FloatContentLayoutManager>();
+    }
+
+    public KnuthBlockBox(int width, List list, Position pos, boolean auxiliary,
+            List<FloatContentLayoutManager> fclms) {
+        super(width, pos, auxiliary);
+        ipdRange = MinOptMax.ZERO;
+        bpd = 0;
+        footnoteList = new LinkedList<FootnoteBodyLayoutManager>(list);
+        floatContentLMs = new LinkedList<FloatContentLayoutManager>(fclms);
     }
 
     /**
@@ -122,4 +134,12 @@ public class KnuthBlockBox extends KnuthBox {
     public int getBPD() {
         return bpd;
     }
+
+    public List<FloatContentLayoutManager> getFloatContentLMs() {
+        return floatContentLMs;
+    }
+
+    public boolean hasFloatAnchors() {
+        return (floatContentLMs.size() > 0);
+    }
 }
index 88c52b383a5f0c42e19da362cf2fc1f089006ec6..7c0f9c999323cc6eb90aa2ea446702695ff0425a 100644 (file)
@@ -41,6 +41,7 @@ import org.apache.fop.fo.flow.Block;
 import org.apache.fop.fo.flow.BlockContainer;
 import org.apache.fop.fo.flow.Character;
 import org.apache.fop.fo.flow.ExternalGraphic;
+import org.apache.fop.fo.flow.Float;
 import org.apache.fop.fo.flow.Footnote;
 import org.apache.fop.fo.flow.Inline;
 import org.apache.fop.fo.flow.InlineContainer;
@@ -74,6 +75,7 @@ import org.apache.fop.layoutmgr.inline.BidiLayoutManager;
 import org.apache.fop.layoutmgr.inline.CharacterLayoutManager;
 import org.apache.fop.layoutmgr.inline.ContentLayoutManager;
 import org.apache.fop.layoutmgr.inline.ExternalGraphicLayoutManager;
+import org.apache.fop.layoutmgr.inline.FloatLayoutManager;
 import org.apache.fop.layoutmgr.inline.FootnoteLayoutManager;
 import org.apache.fop.layoutmgr.inline.InlineContainerLayoutManager;
 import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
@@ -113,7 +115,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
         registerMaker(FObjMixed.class, new Maker());
         registerMaker(BidiOverride.class, new BidiOverrideLayoutManagerMaker());
         registerMaker(Inline.class, new InlineLayoutManagerMaker());
-        registerMaker(Footnote.class, new FootnodeLayoutManagerMaker());
+        registerMaker(Footnote.class, new FootnoteLayoutManagerMaker());
         registerMaker(InlineContainer.class,
                    new InlineContainerLayoutManagerMaker());
         registerMaker(BasicLink.class, new BasicLinkLayoutManagerMaker());
@@ -146,6 +148,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
         registerMaker(Title.class, new InlineLayoutManagerMaker());
         registerMaker(MultiCase.class, new MultiCaseLayoutManagerMaker());
         registerMaker(MultiSwitch.class, new MultiSwitchLayoutManagerMaker());
+        registerMaker(Float.class, new FloatLayoutManagerMaker());
     }
 
     /**
@@ -267,7 +270,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
     }
 
     /** a layout manager maker */
-    public static class FootnodeLayoutManagerMaker extends Maker {
+    public static class FootnoteLayoutManagerMaker extends Maker {
         /** {@inheritDoc} */
         public void make(FONode node, List lms) {
             lms.add(new FootnoteLayoutManager((Footnote) node));
@@ -463,4 +466,10 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
         }
     }
 
+    public static class FloatLayoutManagerMaker extends Maker {
+        public void make(FONode node, List lms) {
+            lms.add(new FloatLayoutManager((Float) node));
+        }
+    }
+
 }
index faff4ee17c0683fe612d37e69b29a9b2c5600629..ba676ab897c7f5b90cc61f3029dd9d3f3d0fd7f7 100644 (file)
@@ -20,6 +20,8 @@
 package org.apache.fop.layoutmgr;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 
@@ -32,7 +34,9 @@ import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.pagination.Region;
 import org.apache.fop.fo.pagination.RegionBody;
 import org.apache.fop.fo.pagination.StaticContent;
+import org.apache.fop.layoutmgr.BreakingAlgorithm.KnuthNode;
 import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
+import org.apache.fop.layoutmgr.list.ListItemLayoutManager;
 import org.apache.fop.traits.MinOptMax;
 
 /**
@@ -47,6 +51,23 @@ public class PageBreaker extends AbstractBreaker {
     private PageProvider pageProvider;
     private Block separatorArea;
     private boolean spanAllActive;
+    private boolean handlingStartOfFloat;
+    private boolean handlingEndOfFloat;
+    private int floatHeight;
+    private int floatYOffset;
+
+    private List relayedFootnotesList;
+    private List relayedLengthList;
+    private int relayedTotalFootnotesLength;
+    private int relayedInsertedFootnotesLength;
+    private boolean relayedFootnotesPending;
+    private boolean relayedNewFootnotes;
+    private int relayedFirstNewFootnoteIndex;
+    private int relayedFootnoteListIndex;
+    private int relayedFootnoteElementIndex = -1;
+    private MinOptMax relayedFootnoteSeparatorLength;
+    private int previousFootnoteListIndex = -2;
+    private int previousFootnoteElementIndex = -2;
 
     /**
      * The FlowLayoutManager object, which processes
@@ -69,7 +90,7 @@ public class PageBreaker extends AbstractBreaker {
 
     /** {@inheritDoc} */
     protected void updateLayoutContext(LayoutContext context) {
-        int flowIPD = pslm.getCurrentPV().getCurrentSpan().getColumnWidth();
+        int flowIPD = pslm.getCurrentColumnWidth();
         context.setRefIPD(flowIPD);
     }
 
@@ -140,18 +161,20 @@ public class PageBreaker extends AbstractBreaker {
     /** {@inheritDoc} */
     protected int getNextBlockList(LayoutContext childLC, int nextSequenceStartsOn,
             Position positionAtIPDChange, LayoutManager restartLM, List firstElements) {
-        if (!firstPart) {
-            // if this is the first page that will be created by
-            // the current BlockSequence, it could have a break
-            // condition that must be satisfied;
-            // otherwise, we may simply need a new page
-            handleBreakTrait(nextSequenceStartsOn);
-        }
-        firstPart = false;
-        pageBreakHandled = true;
+        if (!handlingFloat()) {
+            if (!firstPart) {
+                // if this is the first page that will be created by
+                // the current BlockSequence, it could have a break
+                // condition that must be satisfied;
+                // otherwise, we may simply need a new page
+                handleBreakTrait(nextSequenceStartsOn);
+            }
+            firstPart = false;
+            pageBreakHandled = true;
 
-        pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
-                pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex(), this.spanAllActive);
+            pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(), pslm.getCurrentPV()
+                    .getCurrentSpan().getCurrentFlowIndex(), this.spanAllActive);
+        }
         return super.getNextBlockList(childLC, nextSequenceStartsOn, positionAtIPDChange,
                 restartLM, firstElements);
     }
@@ -234,6 +257,7 @@ public class PageBreaker extends AbstractBreaker {
             // handle the footnote separator
             handleFootnoteSeparator();
         }
+
         return contentList;
     }
 
@@ -616,4 +640,238 @@ public class PageBreaker extends AbstractBreaker {
             return true;
         }
     }
+
+    protected boolean handlingStartOfFloat() {
+        return handlingStartOfFloat;
+    }
+
+    protected void handleStartOfFloat(int fHeight, int fYOffset) {
+        handlingStartOfFloat = true;
+        handlingEndOfFloat = false;
+        floatHeight = fHeight;
+        floatYOffset = fYOffset;
+        childFLM.handleFloatOn();
+    }
+
+    protected int getFloatHeight() {
+        return floatHeight;
+    }
+
+    protected int getFloatYOffset() {
+        return floatYOffset;
+    }
+
+    protected boolean handlingEndOfFloat() {
+        return handlingEndOfFloat;
+    }
+
+    protected void handleEndOfFloat(int fHeight) {
+        handlingEndOfFloat = true;
+        handlingStartOfFloat = false;
+        floatHeight = fHeight;
+        childFLM.handleFloatOff();
+    }
+
+    protected boolean handlingFloat() {
+        return (handlingStartOfFloat || handlingEndOfFloat);
+    }
+
+    public int getOffsetDueToFloat() {
+        handlingEndOfFloat = false;
+        return floatHeight + floatYOffset;
+    }
+
+    protected int handleFloatLayout(PageBreakingAlgorithm alg, int optimalPageCount, BlockSequence blockList,
+            LayoutContext childLC) {
+        pageBreakHandled = true;
+        List firstElements = Collections.EMPTY_LIST;
+        KnuthNode floatNode = alg.getBestFloatEdgeNode();
+        int floatPosition = floatNode.position;
+        KnuthElement floatElem = alg.getElement(floatPosition);
+        Position positionAtBreak = floatElem.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();
+        addAreas(alg, optimalPageCount, blockList, blockList);
+        blockLists.clear();
+        blockListIndex = -1;
+        LayoutManager restartAtLM = null;
+        if (positionAtBreak != null && positionAtBreak.getIndex() == -1) {
+            if (positionAtBreak instanceof ListItemLayoutManager.ListItemPosition) {
+                restartAtLM = positionAtBreak.getLM();
+            } else {
+                Position position;
+                Iterator iter = blockList.listIterator(floatPosition + 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();
+            }
+        }
+        int nextSequenceStartsOn = getNextBlockList(childLC, Constants.EN_COLUMN, positionAtBreak,
+                restartAtLM, firstElements);
+        return nextSequenceStartsOn;
+    }
+
+    protected void addAreasForFloats(PageBreakingAlgorithm alg, int startPart, int partCount,
+            BlockSequence originalList, BlockSequence effectiveList, final LayoutContext childLC,
+            int lastBreak, int startElementIndex, int endElementIndex) {
+        FloatPosition pbp = alg.getFloatPosition();
+
+        // Check the last break position for forced breaks
+        int lastBreakClass;
+        if (startElementIndex == 0) {
+            lastBreakClass = effectiveList.getStartOn();
+        } else {
+            ListElement lastBreakElement = effectiveList.getElement(endElementIndex);
+            if (lastBreakElement.isPenalty()) {
+                KnuthPenalty pen = (KnuthPenalty) lastBreakElement;
+                if (pen.getPenalty() == KnuthPenalty.INFINITE) {
+                    /**
+                     * That means that there was a keep.within-page="always", but that
+                     * it's OK to break at a column. TODO The break class is being
+                     * abused to implement keep.within-column and keep.within-page.
+                     * This is very misleading and must be revised.
+                     */
+                    lastBreakClass = Constants.EN_COLUMN;
+                } else {
+                    lastBreakClass = pen.getBreakClass();
+                }
+            } else {
+                lastBreakClass = Constants.EN_COLUMN;
+            }
+        }
+
+        // the end of the new part
+        endElementIndex = pbp.getLeafPos();
+
+        // ignore the first elements added by the
+        // PageSequenceLayoutManager
+        startElementIndex += (startElementIndex == 0) ? effectiveList.ignoreAtStart : 0;
+
+        log.debug("PLM> part: " + (startPart + partCount + 1) + ", start at pos " + startElementIndex
+                + ", break at pos " + endElementIndex + ", break class = "
+                + getBreakClassName(lastBreakClass));
+
+        startPart(effectiveList, lastBreakClass);
+
+        int displayAlign = getCurrentDisplayAlign();
+
+        // The following is needed by SpaceResolver.performConditionalsNotification()
+        // further down as there may be important Position elements in the element list trailer
+        int notificationEndElementIndex = endElementIndex;
+
+        // ignore the last elements added by the
+        // PageSequenceLayoutManager
+        endElementIndex -= (endElementIndex == (originalList.size() - 1)) ? effectiveList.ignoreAtEnd : 0;
+
+        // ignore the last element in the page if it is a KnuthGlue
+        // object
+        if (((KnuthElement) effectiveList.get(endElementIndex)).isGlue()) {
+            endElementIndex--;
+        }
+
+        // ignore KnuthGlue and KnuthPenalty objects
+        // at the beginning of the line
+        startElementIndex = alg.par.getFirstBoxIndex(startElementIndex);
+
+        if (startElementIndex <= endElementIndex) {
+            if (log.isDebugEnabled()) {
+                log.debug("     addAreas from " + startElementIndex + " to " + endElementIndex);
+            }
+            // set the space adjustment ratio
+            childLC.setSpaceAdjust(pbp.bpdAdjust);
+            // add space before if display-align is center or bottom
+            // add space after if display-align is distribute and
+            // this is not the last page
+            if (pbp.difference != 0 && displayAlign == Constants.EN_CENTER) {
+                childLC.setSpaceBefore(pbp.difference / 2);
+            } else if (pbp.difference != 0 && displayAlign == Constants.EN_AFTER) {
+                childLC.setSpaceBefore(pbp.difference);
+            }
+
+            // Handle SpaceHandling(Break)Positions, see SpaceResolver!
+            SpaceResolver.performConditionalsNotification(effectiveList, startElementIndex,
+                    notificationEndElementIndex, lastBreak);
+            // Add areas of lines, in the current page, before the float or during float
+            addAreas(new KnuthPossPosIter(effectiveList, startElementIndex, endElementIndex + 1), childLC);
+            // add areas for the float, if applicable
+            if (alg.handlingStartOfFloat()) {
+                for (int k = startElementIndex; k < endElementIndex + 1; k++) {
+                    ListElement le = effectiveList.getElement(k);
+                    if (le instanceof KnuthBlockBox) {
+                        KnuthBlockBox kbb = (KnuthBlockBox) le;
+                        for (FloatContentLayoutManager fclm : kbb.getFloatContentLMs()) {
+                            fclm.processAreas(childLC);
+                            int floatHeight = fclm.getFloatHeight();
+                            int floatYOffset = fclm.getFloatYOffset();
+                            PageSequenceLayoutManager pslm = (PageSequenceLayoutManager) getTopLevelLM();
+                            pslm.recordStartOfFloat(floatHeight, floatYOffset);
+                        }
+                    }
+                }
+            }
+            if (alg.handlingEndOfFloat()) {
+                PageSequenceLayoutManager pslm = (PageSequenceLayoutManager) getTopLevelLM();
+                pslm.setEndIntrusionAdjustment(0);
+                pslm.setStartIntrusionAdjustment(0);
+                int effectiveFloatHeight = alg.getFloatHeight();
+                pslm.recordEndOfFloat(effectiveFloatHeight);
+            }
+            if (alg.handlingFloat()) {
+                PageSequenceLayoutManager pslm = (PageSequenceLayoutManager) getTopLevelLM();
+                alg.relayFootnotes(pslm);
+            }
+        } else {
+            // no content for this part
+            handleEmptyContent();
+        }
+
+        pageBreakHandled = true;
+    }
+
+    public void holdFootnotes(List fl, List ll, int tfl, int ifl, boolean fp, boolean nf, int fnfi, int fli,
+            int fei, MinOptMax fsl, int pfli, int pfei) {
+        relayedFootnotesList = fl;
+        relayedLengthList = ll;
+        relayedTotalFootnotesLength = tfl;
+        relayedInsertedFootnotesLength = ifl;
+        relayedFootnotesPending = fp;
+        relayedNewFootnotes = nf;
+        relayedFirstNewFootnoteIndex = fnfi;
+        relayedFootnoteListIndex = fli;
+        relayedFootnoteElementIndex = fei;
+        relayedFootnoteSeparatorLength = fsl;
+        previousFootnoteListIndex = pfli;
+        previousFootnoteElementIndex = pfei;
+    }
+
+    public void retrieveFootones(PageBreakingAlgorithm alg) {
+        if (relayedFootnotesList != null && relayedFootnotesList.size() > 0) {
+            alg.loadFootnotes(relayedFootnotesList, relayedLengthList, relayedTotalFootnotesLength,
+                    relayedInsertedFootnotesLength, relayedFootnotesPending, relayedNewFootnotes,
+                    relayedFirstNewFootnoteIndex, relayedFootnoteListIndex, relayedFootnoteElementIndex,
+                    relayedFootnoteSeparatorLength, previousFootnoteListIndex,
+                    previousFootnoteElementIndex);
+            relayedFootnotesList = null;
+            relayedLengthList = null;
+            relayedTotalFootnotesLength = 0;
+            relayedInsertedFootnotesLength = 0;
+            relayedFootnotesPending = false;
+            relayedNewFootnotes = false;
+            relayedFirstNewFootnoteIndex = 0;
+            relayedFootnoteListIndex = 0;
+            relayedFootnoteElementIndex = -1;
+            relayedFootnoteSeparatorLength = null;
+        }
+    }
 }
index cdd9a703a5e03472c26a5be50cb40714f47a8819..008ec22653a99c612298b53abb25eca88b87fa5a 100644 (file)
@@ -29,6 +29,7 @@ import org.apache.commons.logging.LogFactory;
 
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FObj;
+import org.apache.fop.layoutmgr.AbstractBreaker.FloatPosition;
 import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition;
 import org.apache.fop.layoutmgr.WhitespaceManagementPenalty.Variant;
 import org.apache.fop.traits.MinOptMax;
@@ -99,6 +100,16 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
     private int currentKeepContext = Constants.EN_AUTO;
     private KnuthNode lastBeforeKeepContextSwitch;
 
+    // just one float for now...
+    private boolean handlingStartOfFloat;
+    private boolean handlingEndOfFloat;
+    private int floatHeight;
+    private KnuthNode bestFloatEdgeNode;
+    private FloatPosition floatPosition;
+    private int previousFootnoteListIndex = -2;
+    private int previousFootnoteElementIndex = -2;
+    private boolean relayingFootnotes;
+
     /**
      * Construct a page breaking algorithm.
      * @param topLevelLM the top level layout manager
@@ -235,6 +246,18 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
         insertedFootnotesLength = 0;
         footnoteListIndex = 0;
         footnoteElementIndex = -1;
+        if (topLevelLM instanceof PageSequenceLayoutManager) {
+            PageSequenceLayoutManager pslm = (PageSequenceLayoutManager) topLevelLM;
+            if (pslm.handlingStartOfFloat() || pslm.handlingEndOfFloat()) {
+                pslm.retrieveFootnotes(this);
+            }
+            if (pslm.handlingStartOfFloat()) {
+                floatHeight = Math.min(pslm.getFloatHeight(), lineWidth - pslm.getFloatYOffset());
+            }
+            if (pslm.handlingEndOfFloat()) {
+                totalWidth += pslm.getOffsetDueToFloat() + insertedFootnotesLength;
+            }
+        }
     }
 
     /**
@@ -352,6 +375,12 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
                 firstNewFootnoteIndex = footnotesList.size() - 1;
             }
         }
+        if (box instanceof KnuthBlockBox && ((KnuthBlockBox) box).hasFloatAnchors()) {
+            handlingStartOfFloat = true;
+        }
+        if (floatHeight != 0 && totalWidth >= floatHeight) {
+            handlingEndOfFloat = true;
+        }
     }
 
     /**
@@ -1064,17 +1093,6 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
                 difference = 0;
             }
         }
-        // compute the indexes of the first footnote list and the first element in that list
-        int firstListIndex = ((KnuthPageNode) bestActiveNode.previous).footnoteListIndex;
-        int firstElementIndex = ((KnuthPageNode) bestActiveNode.previous).footnoteElementIndex;
-        if (footnotesList != null
-                && firstElementIndex == getFootnoteList(firstListIndex).size() - 1) {
-            // advance to the next list
-            firstListIndex++;
-            firstElementIndex = 0;
-        } else {
-            firstElementIndex++;
-        }
 
         // add nodes at the beginning of the list, as they are found
         // backwards, from the last one to the first one
@@ -1082,12 +1100,31 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
             log.debug("BBA> difference=" + difference + " ratio=" + ratio
                     + " position=" + bestActiveNode.position);
         }
-        insertPageBreakAsFirst(new PageBreakPosition(this.topLevelLM,
-                bestActiveNode.position,
-                firstListIndex, firstElementIndex,
-                ((KnuthPageNode) bestActiveNode).footnoteListIndex,
-                ((KnuthPageNode) bestActiveNode).footnoteElementIndex,
-                ratio, difference));
+        if (handlingFloat() && floatPosition == null) {
+            floatPosition = new FloatPosition(this.topLevelLM, bestActiveNode.position, ratio, difference);
+        } else {
+            boolean useRelayedFootnotes = relayingFootnotes && bestActiveNode.previous.position == 0;
+            // compute the indexes of the first footnote list and the first element in that list
+            int firstListIndex = (useRelayedFootnotes) ? previousFootnoteListIndex
+                    : ((KnuthPageNode) bestActiveNode.previous).footnoteListIndex;
+            int firstElementIndex = (useRelayedFootnotes) ? previousFootnoteElementIndex
+                    : ((KnuthPageNode) bestActiveNode.previous).footnoteElementIndex;
+            if (useRelayedFootnotes) {
+                previousFootnoteListIndex = -2;
+                previousFootnoteElementIndex = -2;
+                relayingFootnotes = false;
+            }
+            if (footnotesList != null && firstElementIndex == getFootnoteList(firstListIndex).size() - 1) {
+                // advance to the next list
+                firstListIndex++;
+                firstElementIndex = 0;
+            } else {
+                firstElementIndex++;
+            }
+            insertPageBreakAsFirst(new PageBreakPosition(this.topLevelLM, bestActiveNode.position,
+                    firstListIndex, firstElementIndex, ((KnuthPageNode) bestActiveNode).footnoteListIndex,
+                    ((KnuthPageNode) bestActiveNode).footnoteElementIndex, ratio, difference));
+        }
     }
 
     /** {@inheritDoc} */
@@ -1233,4 +1270,94 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
         }
         return pageProvider.compareIPDs(line);
     }
+
+    protected boolean handlingFloat() {
+        return (handlingStartOfFloat || handlingEndOfFloat);
+    }
+
+    protected void createForcedNodes(KnuthNode node, int line, int elementIdx, int difference, double r,
+            double demerits, int fitnessClass, int availableShrink, int availableStretch, int newWidth,
+            int newStretch, int newShrink) {
+        if (handlingFloat()) {
+            if (bestFloatEdgeNode == null || demerits <= bestFloatEdgeNode.totalDemerits) {
+                bestFloatEdgeNode = createNode(elementIdx, line + 1, fitnessClass, newWidth, newStretch,
+                        newShrink, r, availableShrink, availableStretch, difference, demerits, node);
+            }
+        } else {
+            super.createForcedNodes(node, line, elementIdx, difference, r, demerits, fitnessClass,
+                    availableShrink, availableStretch, newWidth, newStretch, newShrink);
+        }
+    }
+
+    protected int handleFloat() {
+        calculateBreakPoints(bestFloatEdgeNode, par, bestFloatEdgeNode.line);
+        activeLines = null;
+        return bestFloatEdgeNode.line - 1;
+    }
+
+    protected KnuthNode getBestFloatEdgeNode() {
+        return bestFloatEdgeNode;
+    }
+
+    protected FloatPosition getFloatPosition() {
+        return floatPosition;
+    }
+
+    protected int getFloatHeight() {
+        return floatHeight;
+    }
+
+    protected boolean handlingStartOfFloat() {
+        return handlingStartOfFloat;
+    }
+
+    protected boolean handlingEndOfFloat() {
+        return handlingEndOfFloat;
+    }
+
+    /**
+     * Deactivate the given node
+     *
+     * @param node  the node
+     * @param line  the line number
+     */
+    protected void deactivateNode(KnuthNode node, int line) {
+        super.deactivateNode(node, line);
+        if (handlingEndOfFloat) {
+            floatHeight = totalWidth;
+        }
+    }
+
+    protected void disableFloatHandling() {
+        handlingEndOfFloat = false;
+        handlingStartOfFloat = false;
+    }
+
+    public void loadFootnotes(List fl, List ll, int tfl, int ifl, boolean fp, boolean nf, int fnfi, int fli,
+            int fei, MinOptMax fsl, int pfli, int pfei) {
+        footnotesList = fl;
+        lengthList = ll;
+        totalFootnotesLength = tfl;
+        insertedFootnotesLength = ifl;
+        footnotesPending = fp;
+        newFootnotes = nf;
+        firstNewFootnoteIndex = fnfi;
+        footnoteListIndex = fli;
+        footnoteElementIndex = fei;
+        footnoteSeparatorLength = fsl;
+        previousFootnoteListIndex = pfli;
+        previousFootnoteElementIndex = pfei;
+        relayingFootnotes = !(previousFootnoteListIndex == -2 && previousFootnoteElementIndex == -2);
+    }
+
+    public void relayFootnotes(PageSequenceLayoutManager pslm) {
+        if (!relayingFootnotes) {
+            previousFootnoteListIndex = ((KnuthPageNode) bestFloatEdgeNode.previous).footnoteListIndex;
+            previousFootnoteElementIndex = ((KnuthPageNode) bestFloatEdgeNode.previous).footnoteElementIndex;
+        }
+        pslm.holdFootnotes(footnotesList, lengthList, totalFootnotesLength, insertedFootnotesLength,
+                footnotesPending, newFootnotes, firstNewFootnoteIndex, footnoteListIndex,
+                footnoteElementIndex, footnoteSeparatorLength, previousFootnoteListIndex,
+                previousFootnoteElementIndex);
+    }
 }
index 70f02f8966c3c2ac17731dc4c2412a3e5971f150..20c4616bd14fa613b9617686674b8de340be402c 100644 (file)
@@ -36,6 +36,7 @@ import org.apache.fop.fo.pagination.PageSequenceMaster;
 import org.apache.fop.fo.pagination.SideRegion;
 import org.apache.fop.fo.pagination.StaticContent;
 import org.apache.fop.layoutmgr.inline.ContentLayoutManager;
+import org.apache.fop.traits.MinOptMax;
 
 /**
  * LayoutManager for a PageSequence.  This class is instantiated by
@@ -56,6 +57,9 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager
     /** Footnotes coming from repeated table footers, to be added after any other footnote. */
     private List<List<KnuthElement>> tableFooterFootnotes;
 
+    private int startIntrusionAdjustment;
+    private int endIntrusionAdjustment;
+
     /**
      * Constructor
      *
@@ -293,4 +297,64 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager
         }
     }
 
+    public void setStartIntrusionAdjustment(int sia) {
+        startIntrusionAdjustment = sia;
+    }
+
+    public void setEndIntrusionAdjustment(int eia) {
+        endIntrusionAdjustment = eia;
+    }
+
+    public int getStartIntrusionAdjustment() {
+        return startIntrusionAdjustment;
+    }
+
+    public int getEndIntrusionAdjustment() {
+        return endIntrusionAdjustment;
+    }
+
+    public void recordEndOfFloat(int fHeight) {
+        pageBreaker.handleEndOfFloat(fHeight);
+    }
+
+    public boolean handlingEndOfFloat() {
+        return pageBreaker.handlingEndOfFloat();
+    }
+
+    public int getOffsetDueToFloat() {
+        return pageBreaker.getOffsetDueToFloat();
+    }
+
+    public void recordStartOfFloat(int fHeight, int fYOffset) {
+        pageBreaker.handleStartOfFloat(fHeight, fYOffset);
+    }
+
+    public boolean handlingStartOfFloat() {
+        return pageBreaker.handlingStartOfFloat();
+    }
+
+    public int getFloatHeight() {
+        return pageBreaker.getFloatHeight();
+    }
+
+    public int getFloatYOffset() {
+        return pageBreaker.getFloatYOffset();
+    }
+
+    public int getCurrentColumnWidth() {
+        int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth();
+        flowIPD -= startIntrusionAdjustment + endIntrusionAdjustment;
+        return flowIPD;
+    }
+
+    public void holdFootnotes(List fl, List ll, int tfl, int ifl, boolean fp, boolean nf, int fnfi, int fli,
+            int fei, MinOptMax fsl, int pfli, int pfei) {
+        if (fl != null && fl.size() > 0) {
+            pageBreaker.holdFootnotes(fl, ll, tfl, ifl, fp, nf, fnfi, fli, fei, fsl, pfli, pfei);
+        }
+    }
+
+    public void retrieveFootnotes(PageBreakingAlgorithm alg) {
+        pageBreaker.retrieveFootones(alg);
+    }
 }
index 31bdaebbf84c8f4f0854eeddbbf510aedeb155fd..551e7d3f2708dc156774ac805083d240cd7f248a 100644 (file)
@@ -696,7 +696,7 @@ public final class SpaceResolver {
                 beforeBreak.notifyBreakSituation(true, RelSide.BEFORE);
             }
         }
-        el = (KnuthElement)effectiveList.get(endElementIndex);
+        el = endElementIndex > -1 ? (KnuthElement) effectiveList.get(endElementIndex) : null;
         if (el != null && el.isPenalty()) {
             Position pos = el.getPosition();
             if (pos instanceof SpaceResolver.SpaceHandlingBreakPosition) {
diff --git a/src/java/org/apache/fop/layoutmgr/inline/FloatLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/FloatLayoutManager.java
new file mode 100644 (file)
index 0000000..4bb481d
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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.inline;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.fop.fo.flow.Float;
+import org.apache.fop.layoutmgr.FloatContentLayoutManager;
+import org.apache.fop.layoutmgr.InlineKnuthSequence;
+import org.apache.fop.layoutmgr.KnuthElement;
+import org.apache.fop.layoutmgr.KnuthPossPosIter;
+import org.apache.fop.layoutmgr.KnuthSequence;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.SpaceResolver;
+
+public class FloatLayoutManager extends InlineStackingLayoutManager {
+
+    private FloatContentLayoutManager floatContentLM;
+    private KnuthInlineBox anchor;
+    private List<KnuthElement> floatContentKnuthElements;
+    private Float floatContent;
+    private boolean floatContentAreaAdded;
+
+    public FloatLayoutManager(Float node) {
+        super(node);
+        floatContent = node;
+    }
+
+    protected LayoutManager getChildLM() {
+        return null;
+    }
+
+    public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
+
+        if (!floatContentAreaAdded && !floatContent.isDisabled()) {
+            floatContentLM = new FloatContentLayoutManager(floatContent);
+            floatContentLM.setParent(this);
+            floatContentLM.initialize();
+            floatContentKnuthElements = floatContentLM.getNextKnuthElements(context, alignment);
+            SpaceResolver.resolveElementList(floatContentKnuthElements);
+        }
+
+        // the only knuth element is a zero width and height knuth box
+        LinkedList knuthElements = new LinkedList();
+        KnuthSequence seq = new InlineKnuthSequence();
+        anchor = new KnuthInlineBox(0, null, null, true);
+        if (!floatContentAreaAdded) {
+            anchor.setFloatContentLM(floatContentLM);
+        }
+        anchor.setPosition(notifyPos(new Position(this)));
+        seq.add(anchor);
+        knuthElements.add(seq);
+        setFinished(true);
+
+        return knuthElements;
+    }
+
+    public void addAreas(PositionIterator posIter, LayoutContext context) {
+        // "Unwrap" the NonLeafPositions stored in posIter
+        LinkedList positionList = new LinkedList();
+        Position pos = null;
+        while (posIter.hasNext()) {
+            pos = posIter.next();
+            if (pos != null && pos.getPosition() != null) {
+                positionList.add(pos.getPosition());
+            }
+        }
+    }
+
+    public void processAreas(LayoutContext context) {
+        PositionIterator contentPosIter = new KnuthPossPosIter(floatContentKnuthElements, 0,
+                floatContentKnuthElements.size());
+        floatContentLM.addAreas(contentPosIter, context);
+        floatContentAreaAdded = true;
+        anchor.setFloatContentLM(null);
+    }
+}
index e8bec8f4d7f8a81b8ff6e19da86379ada68292f1..dad6d283c785946e18ee7c9a8b77dabb3a52605b 100644 (file)
@@ -19,6 +19,7 @@
 
 package org.apache.fop.layoutmgr.inline;
 
+import org.apache.fop.layoutmgr.FloatContentLayoutManager;
 import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.Position;
@@ -30,6 +31,8 @@ public class KnuthInlineBox extends KnuthBox {
 
     private FootnoteBodyLayoutManager footnoteBodyLM;
     private AlignmentContext alignmentContext;
+    private FloatContentLayoutManager floatContentLM;
+
 
     /**
      * Create a new KnuthBox.
@@ -72,4 +75,17 @@ public class KnuthInlineBox extends KnuthBox {
     public boolean isAnchor() {
         return (footnoteBodyLM != null);
     }
+
+    public void setFloatContentLM(FloatContentLayoutManager fclm) {
+        floatContentLM = fclm;
+    }
+
+    public FloatContentLayoutManager getFloatContentLM() {
+        return floatContentLM;
+    }
+
+    public boolean isFloatAnchor() {
+        return (floatContentLM != null);
+    }
+
 }
index d8ebc6dbf92397468ce4dbb31c24f772d72bb436..6f31f038a1475ab08089e39e07c9443b4299832f 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.fop.layoutmgr.inline;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -50,6 +51,7 @@ import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
 import org.apache.fop.layoutmgr.BreakElement;
 import org.apache.fop.layoutmgr.BreakingAlgorithm;
 import org.apache.fop.layoutmgr.ElementListObserver;
+import org.apache.fop.layoutmgr.FloatContentLayoutManager;
 import org.apache.fop.layoutmgr.FootenoteUtil;
 import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager;
 import org.apache.fop.layoutmgr.InlineKnuthSequence;
@@ -963,13 +965,19 @@ public class LineLayoutManager extends InlineStackingLayoutManager
                 /* "normal" vertical alignment: create a sequence whose boxes
                    represent effective lines, and contain LineBreakPositions */
                 int startIndex = 0;
+                int previousEndIndex = 0;
                 for (int i = 0;
                         i < llPoss.getChosenLineCount();
                         i++) {
+                    int orphans = fobj.getOrphans();
+                    int widows = fobj.getWidows();
+                    if (handlingFloat()) {
+                        orphans = 1;
+                        widows = 1;
+                    }
                     if (returnList.size() > 0
                             && i > 0 //if i==0 break generated above already
-                            && i >= fobj.getOrphans()
-                            && i <= llPoss.getChosenLineCount() - fobj.getWidows()) {
+                            && i >= orphans && i <= llPoss.getChosenLineCount() - widows) {
                         // penalty allowing a page break between lines
                         Keep keep = getKeepTogether();
                         returnList.add(new BreakElement(
@@ -983,14 +991,28 @@ public class LineLayoutManager extends InlineStackingLayoutManager
                     // whose citations are in this line
                     List<FootnoteBodyLayoutManager> footnoteList = FootenoteUtil.getFootnotes(
                             seq, startIndex, endIndex);
+                    List<FloatContentLayoutManager> floats = FloatContentLayoutManager.checkForFloats(seq,
+                            startIndex, endIndex);
                     startIndex = endIndex + 1;
                     LineBreakPosition lbp = (LineBreakPosition) llPoss.getChosenPosition(i);
                     if (baselineOffset < 0) {
                         baselineOffset = lbp.spaceBefore + lbp.baseline;
                     }
-                    returnList.add(new KnuthBlockBox(
-                                   lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter,
-                                    footnoteList, lbp, false));
+                    if (floats.isEmpty()) {
+                        returnList.add(new KnuthBlockBox(lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter,
+                                footnoteList, lbp, false));
+                    } else {
+                        // add a line with height zero and no content and attach float to it
+                        returnList.add(new KnuthBlockBox(0, Collections.emptyList(), null, false, floats));
+                        // add a break element to signal that we should restart LB at this break
+                        Keep keep = getKeepTogether();
+                        returnList.add(new BreakElement(new LeafPosition(this, p, previousEndIndex), keep
+                                .getPenalty(), keep.getContext(), context));
+                        // add the original line where the float was but without the float now
+                        returnList.add(new KnuthBlockBox(lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter,
+                                footnoteList, lbp, false));
+                    }
+                    previousEndIndex = endIndex;
                 }
             }
         }
@@ -1196,10 +1218,15 @@ public class LineLayoutManager extends InlineStackingLayoutManager
         for (int p = 0; p < knuthParagraphs.size(); p++) {
             LineLayoutPossibilities llPoss = lineLayoutsList[p];
             //log.debug("demerits of the chosen layout: " + llPoss.getChosenDemerits());
+            int orphans = fobj.getOrphans();
+            int widows = fobj.getWidows();
+            if (handlingFloat()) {
+                orphans = 1;
+                widows = 1;
+            }
             for (int i = 0; i < llPoss.getChosenLineCount(); i++) {
-                if (!((BlockLevelLayoutManager) parentLayoutManager).mustKeepTogether()
-                    && i >= fobj.getOrphans()
-                    && i <= llPoss.getChosenLineCount() - fobj.getWidows()) {
+                if (!((BlockLevelLayoutManager) parentLayoutManager).mustKeepTogether() && i >= orphans
+                        && i <= llPoss.getChosenLineCount() - widows) {
                     // null penalty allowing a page break between lines
                     returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
                 }
index 062a67b38507785d19cb670f3e7b30d81d0b38b9..d39b634774c9218f2c44a09f544a88a5d79dd9e3 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr.list;
 
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Stack;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -95,10 +96,11 @@ public class ListBlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManag
     }
 
     /** {@inheritDoc} */
-    @Override
-    public List getNextKnuthElements(LayoutContext context, int alignment) {
+    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
+            Position restartPosition, LayoutManager restartAtLM) {
         resetSpaces();
-        List returnList = super.getNextKnuthElements(context, alignment);
+        List returnList;
+        returnList = super.getNextKnuthElements(context, alignment, lmStack, restartPosition, restartAtLM);
 
         //fox:widow-content-limit
         int widowRowLimit = getListBlockFO().getWidowContentLimit().getValue();
@@ -275,5 +277,9 @@ public class ListBlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManag
         return getListBlockFO().getKeepWithNext();
     }
 
+    /** {@inheritDoc} */
+    public boolean isRestartable() {
+        return true;
+    }
 }
 
index 108402cfa3c50fd177b629f391cb2105ae101730..214ba626921847d1815fd4e685a7c4cd07d37fdd 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr.list;
 
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Stack;
 
 import org.apache.fop.area.Area;
 import org.apache.fop.area.Block;
@@ -225,15 +226,15 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager imp
         return Keep.KEEP_AUTO;
     }
 
-    @SuppressWarnings("unchecked")
-    @Override
-    public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) {
+    /** {@inheritDoc} */
+    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
+            Position restartPosition, LayoutManager restartAtLM) {
         List<ListElement> elements = new LinkedList<ListElement>();
         do {
-            elements.addAll(super.getNextKnuthElements(context, alignment));
+            elements.addAll(super.getNextKnuthElements(context, alignment, lmStack, restartPosition,
+                    restartAtLM));
         } while (!isFinished());
         return elements;
     }
-
 }
 
index 6404e9feb15fab8edd7369b7415f90b0f098427e..ba49b7dc0918a0334c7624f44be51ffcfa2ac43b 100644 (file)
 package org.apache.fop.layoutmgr.list;
 
 import java.util.ArrayList;
+import java.util.Collections;
 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;
@@ -39,15 +41,16 @@ import org.apache.fop.layoutmgr.BreakOpportunity;
 import org.apache.fop.layoutmgr.BreakOpportunityHelper;
 import org.apache.fop.layoutmgr.ElementListObserver;
 import org.apache.fop.layoutmgr.ElementListUtils;
+import org.apache.fop.layoutmgr.FloatContentLayoutManager;
 import org.apache.fop.layoutmgr.FootenoteUtil;
 import org.apache.fop.layoutmgr.Keep;
 import org.apache.fop.layoutmgr.KnuthBlockBox;
-import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthPenalty;
 import org.apache.fop.layoutmgr.KnuthPossPosIter;
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.LeafPosition;
 import org.apache.fop.layoutmgr.ListElement;
 import org.apache.fop.layoutmgr.NonLeafPosition;
 import org.apache.fop.layoutmgr.Position;
@@ -79,11 +82,13 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
     private Keep keepWithNextPendingOnLabel;
     private Keep keepWithNextPendingOnBody;
 
-    private class ListItemPosition extends Position {
+    public class ListItemPosition extends Position {
         private int labelFirstIndex;
         private int labelLastIndex;
         private int bodyFirstIndex;
         private int bodyLastIndex;
+        private Position originalLabelPosition;
+        private Position originalBodyPosition;
 
         public ListItemPosition(LayoutManager lm, int labelFirst, int labelLast,
                 int bodyFirst, int bodyLast) {
@@ -124,6 +129,22 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
             sb.append(")");
             return sb.toString();
         }
+
+        public Position getOriginalLabelPosition() {
+            return originalLabelPosition;
+        }
+
+        public void setOriginalLabelPosition(Position originalLabelPosition) {
+            this.originalLabelPosition = originalLabelPosition;
+        }
+
+        public Position getOriginalBodyPosition() {
+            return originalBodyPosition;
+        }
+
+        public void setOriginalBodyPosition(Position originalBodyPosition) {
+            this.originalBodyPosition = originalBodyPosition;
+        }
     }
 
     /**
@@ -188,8 +209,8 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
     }
 
     /** {@inheritDoc} */
-    @Override
-    public List getNextKnuthElements(LayoutContext context, int alignment) {
+    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
+            Position restartPosition, LayoutManager restartAtLM) {
         referenceIPD = context.getRefIPD();
         LayoutContext childLC;
 
@@ -205,7 +226,30 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
         childLC = makeChildLayoutContext(context);
         childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
         label.initialize();
-        labelList = label.getNextKnuthElements(childLC, alignment);
+        boolean labelDone = false;
+        Stack labelLMStack = null;
+        Position labelRestartPosition = null;
+        LayoutManager labelRestartLM = null;
+        if (restartPosition != null && restartPosition instanceof ListItemPosition) {
+            ListItemPosition lip = (ListItemPosition) restartPosition;
+            if (lip.labelLastIndex <= lip.labelFirstIndex) {
+                labelDone = true;
+            } else {
+                labelRestartPosition = lip.getOriginalLabelPosition();
+                labelRestartLM = labelRestartPosition.getLM();
+                LayoutManager lm = labelRestartLM;
+                labelLMStack = new Stack();
+                while (lm != this) {
+                    labelLMStack.push(lm);
+                    lm = lm.getParent();
+                    if (lm instanceof ListItemContentLayoutManager) {
+                        lm = lm.getParent();
+                    }
+                }
+            }
+        }
+        labelList = !labelDone ? label.getNextKnuthElements(childLC, alignment, labelLMStack,
+                labelRestartPosition, labelRestartLM) : new LinkedList<KnuthElement>();
 
         //Space resolution as if the contents were placed in a new reference area
         //(see 6.8.3, XSL 1.0, section on Constraints, last paragraph)
@@ -219,7 +263,30 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
         childLC = makeChildLayoutContext(context);
         childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
         body.initialize();
-        bodyList = body.getNextKnuthElements(childLC, alignment);
+        boolean bodyDone = false;
+        Stack bodyLMStack = null;
+        Position bodyRestartPosition = null;
+        LayoutManager bodyRestartLM = null;
+        if (restartPosition != null && restartPosition instanceof ListItemPosition) {
+            ListItemPosition lip = (ListItemPosition) restartPosition;
+            if (lip.bodyLastIndex <= lip.bodyFirstIndex) {
+                bodyDone = true;
+            } else {
+                bodyRestartPosition = lip.getOriginalBodyPosition();
+                bodyRestartLM = bodyRestartPosition.getLM();
+                LayoutManager lm = bodyRestartLM;
+                bodyLMStack = new Stack();
+                while (lm != this) {
+                    bodyLMStack.push(lm);
+                    lm = lm.getParent();
+                    if (lm instanceof ListItemContentLayoutManager) {
+                        lm = lm.getParent();
+                    }
+                }
+            }
+        }
+        bodyList = !bodyDone ? body.getNextKnuthElements(childLC, alignment, bodyLMStack,
+                bodyRestartPosition, bodyRestartLM) : new LinkedList<KnuthElement>();
 
         //Space resolution as if the contents were placed in a new reference area
         //(see 6.8.3, XSL 1.0, section on Constraints, last paragraph)
@@ -229,8 +296,34 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
         context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
         this.keepWithNextPendingOnBody = childLC.getKeepWithNextPending();
 
+        List<ListElement> returnedList = new LinkedList<ListElement>();
+        if (!labelList.isEmpty() && labelList.get(0) instanceof KnuthBlockBox) {
+            KnuthBlockBox kbb = (KnuthBlockBox) labelList.get(0);
+            if (kbb.getWidth() == 0 && kbb.hasFloatAnchors()) {
+                List<FloatContentLayoutManager> floats = kbb.getFloatContentLMs();
+                returnedList.add(new KnuthBlockBox(0, Collections.emptyList(), null, false, floats));
+                Keep keep = getKeepTogether();
+                returnedList.add(new BreakElement(new LeafPosition(this, 0), keep.getPenalty(), keep
+                        .getContext(), context));
+                labelList.remove(0);
+                labelList.remove(0);
+            }
+        }
+        if (!bodyList.isEmpty() && bodyList.get(0) instanceof KnuthBlockBox) {
+            KnuthBlockBox kbb = (KnuthBlockBox) bodyList.get(0);
+            if (kbb.getWidth() == 0 && kbb.hasFloatAnchors()) {
+                List<FloatContentLayoutManager> floats = kbb.getFloatContentLMs();
+                returnedList.add(new KnuthBlockBox(0, Collections.emptyList(), null, false, floats));
+                Keep keep = getKeepTogether();
+                returnedList.add(new BreakElement(new LeafPosition(this, 0), keep.getPenalty(), keep
+                        .getContext(), context));
+                bodyList.remove(0);
+                bodyList.remove(0);
+            }
+        }
+
         // create a combined list
-        List returnedList = getCombinedKnuthElementsForListItem(labelList, bodyList, context);
+        returnedList.addAll(getCombinedKnuthElementsForListItem(labelList, bodyList, context));
 
         // "wrap" the Position inside each element
         wrapPositionElements(returnedList, returnList, true);
@@ -298,7 +391,9 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
             int additionalPenaltyHeight = 0;
             int stepPenalty = 0;
             int breakClass = EN_AUTO;
-            KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]);
+            KnuthElement endEl = elementLists[0].size() > 0 ? (KnuthElement) elementLists[0].get(end[0])
+                    : null;
+            Position originalLabelPosition = endEl != null ? endEl.getPosition().getPosition() : null;
             if (endEl instanceof KnuthPenalty) {
                 additionalPenaltyHeight = endEl.getWidth();
                 stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math
@@ -306,7 +401,8 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
                 breakClass = BreakUtil.compareBreakClasses(breakClass,
                         ((KnuthPenalty) endEl).getBreakClass());
             }
-            endEl = (KnuthElement)elementLists[1].get(end[1]);
+            endEl = elementLists[1].size() > 0 ? (KnuthElement) elementLists[1].get(end[1]) : null;
+            Position originalBodyPosition = endEl != null ? endEl.getPosition().getPosition() : null;
             if (endEl instanceof KnuthPenalty) {
                 additionalPenaltyHeight = Math.max(
                         additionalPenaltyHeight, endEl.getWidth());
@@ -327,13 +423,26 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
                 footnoteList.addAll(FootenoteUtil.getFootnotes(elementLists[i], start[i], end[i]));
             }
 
+            LinkedList<FloatContentLayoutManager> floats = new LinkedList<FloatContentLayoutManager>();
+            for (int i = 0; i < elementLists.length; i++) {
+                floats.addAll(FloatContentLayoutManager.checkForFloats(elementLists[i], start[i], end[i]));
+            }
+
             // add the new elements
             addedBoxHeight += boxHeight;
-            ListItemPosition stepPosition = new ListItemPosition(this,
-                    start[0], end[0], start[1], end[1]);
-            if (footnoteList.isEmpty()) {
-                returnList.add(new KnuthBox(boxHeight, stepPosition, false));
+            ListItemPosition stepPosition = new ListItemPosition(this, start[0], end[0], start[1], end[1]);
+            stepPosition.setOriginalLabelPosition(originalLabelPosition);
+            stepPosition.setOriginalBodyPosition(originalBodyPosition);
+
+            if (floats.isEmpty()) {
+                returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false));
             } else {
+                // add a line with height zero and no content and attach float to it
+                returnList.add(new KnuthBlockBox(0, Collections.emptyList(), stepPosition, false, floats));
+                // add a break element to signal that we should restart LB at this break
+                Keep keep = getKeepTogether();
+                returnList.add(new BreakElement(stepPosition, keep.getPenalty(), keep.getContext(), context));
+                // add the original line where the float was but without the float now
                 returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false));
             }
 
@@ -512,6 +621,10 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
                 positionList.add(pos.getPosition());
             }
         }
+        if (positionList.isEmpty()) {
+            reset();
+            return;
+        }
 
         registerMarkers(true, isFirst(firstPos), isLast(lastPos));
 
@@ -674,5 +787,9 @@ public class ListItemLayoutManager extends SpacedBorderedPaddedBlockLayoutManage
         return breakBefore;
     }
 
+    /** {@inheritDoc} */
+    public boolean isRestartable() {
+        return true;
+    }
 }
 
index ad0804af51c6eb7cdb5c4719bd7cbf7bf5ff3314..901969a71b9d25da21705e07a656c22e725ab276 100644 (file)
@@ -323,7 +323,11 @@ public class LayoutEngineTestCase {
             throw new RuntimeException("No available area tree check");
         }
         for (LayoutEngineCheck check : checks) {
-            check.check(result);
+            try {
+                check.check(result);
+            } catch (RuntimeException rte) {
+                throw new RuntimeException("Layout test (" + testFile.getName() + "): " + rte.getMessage());
+            }
         }
     }
 
diff --git a/test/layoutengine/standard-testcases/float_1.xml b/test/layoutengine/standard-testcases/float_1.xml
new file mode 100644 (file)
index 0000000..5e9fc7f
--- /dev/null
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks floats.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master margin="50pt" master-name="page" page-height="800pt" page-width="600pt">
+      <fo:region-body background-color="yellow" />
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body">
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="start">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="100pt">
+              <fo:block background-color="orange">
+                This is a normal block that is confined to the block container inside a side float. The background is orange.
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="end">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="90pt">
+              <fo:block background-color="pink">
+                This is a normal block that is confined to the block container inside a side float. The background is pink.
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="start">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="110pt">
+              <fo:block background-color="green">
+                This is a normal block that is confined to the block container inside a side float. The background is green.
+              </fo:block>
+            </fo:block-container>
+            <fo:block>This line is not constrained by a width.</fo:block>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="start">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block background-color="red">
+              The background is red.
+            </fo:block>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <!-- first float -->
+    <eval expected="11000" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[3]/@left-offset" />
+    <eval expected="40692" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[7]/text/@ipd" />
+    <eval expected="orange." xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[7]" />
+    <eval expected="122000" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[4]/@left-offset" />
+    <eval expected="last content before the float and the float is right now. This is the first" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[4]/lineArea[1]" />
+    <eval expected="reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[6]/lineArea[1]" />
+    <!-- second float -->
+    <eval expected="399000" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[8]/@left-offset" />
+    <eval expected="25344" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[8]/block[1]/block[1]/block[1]/block[1]/lineArea[8]/text/@ipd" />
+    <eval expected="pink." xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[8]/block[1]/block[1]/block[1]/block[1]/lineArea[8]" />
+    <eval expected="last content before the float and the float is right now. This is the first" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[9]/lineArea[1]" />
+    <eval expected="the foot of the village of Elstree. This noble sheet of water occupies a space of considerable" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[11]/lineArea[1]" />
+    <!-- third float -->
+    <eval expected="11000" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[3]/@left-offset" />
+    <eval expected="34020" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[7]/text/@ipd" />
+    <eval expected="green." xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[7]" />
+    <eval expected="224752" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[4]/@left-offset" />
+    <eval expected="last content before the float and the float is right" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[4]/lineArea[1]" />
+    <eval expected="at some distance on the right in the valley catch a view of the celebrated reservoir, the" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[6]/lineArea[1]" />
+    <!-- fourth float -->
+    <eval expected="11000" xpath="//pageViewport[4]/page/regionViewport[1]//flow[1]/block[3]/@left-offset" />
+    <eval expected="122724" xpath="//pageViewport[4]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/lineArea[1]/text/@ipd" />
+    <eval expected="The background is red." xpath="//pageViewport[4]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/lineArea[1]" />
+    <eval expected="144724" xpath="//pageViewport[4]/page/regionViewport[1]//flow[1]/block[4]/@left-offset" />
+    <eval expected="last content before the float and the float is right now. This is the" xpath="//pageViewport[4]/page/regionViewport[1]//flow[1]/block[4]/lineArea[1]" />
+    <eval expected="float... this is very complicated but the current implementation can handle the simpler cases." xpath="//pageViewport[4]/page/regionViewport[1]//flow[1]/block[5]/lineArea[1]" />
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/float_2.xml b/test/layoutengine/standard-testcases/float_2.xml
new file mode 100644 (file)
index 0000000..d4ccb83
--- /dev/null
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks floats in two column pages.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master margin="50pt" master-name="page" page-height="600pt" page-width="800pt">
+      <fo:region-body background-color="yellow" column-count="2" />
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body">
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="start">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="100pt">
+              <fo:block background-color="orange">
+                This is a normal block that is confined to the block container inside a side float. The background is orange.
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="end">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="90pt">
+              <fo:block background-color="pink">
+                This is a normal block that is confined to the block container inside a side float. The background is pink.
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="start">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="150pt">
+              <fo:block background-color="green">
+                This is a normal block that is confined to the block container inside a side float. The background is green.
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+      <fo:block>
+Elstree Reservoir[edit]
+The dam was built in 1795 by French prisoners of war.[34] English watercolour landscape painter John Hassell writes:
+"At the top of Stanmore Hill we enter on Bushy Heath, and at some distance on the right in the valley catch a view of the celebrated reservoir, the property of the Grand Junction Company, on Aidenham Common, at the foot of the village of Elstree. This noble sheet of water occupies a space of considerable extent on the verge of Aidenham Common, which thirty years ago was a barren waste; here the improvements in agriculture are indeed conspicuous, for at this place a poor, sandy, meagre, wretched soil has now by good husbandry been converted into rich pasturage.
+"The reservoir has all the appearance of a lake; and when the timber that surrounds it shall have arrived at maturity, it will be a most delightful spot. From this immense sheet of water, in event of drought or a deficiency of upland waters, the lower parts of the Grand Junction and the Paddington Canals can have an immediate supply. The feeder from this reservoir enters the main stream near Rickmansworth, above Batchworth Mills, and supplies the millers' below with 300 locks of water, to whose interest the Duke of Northumberland is a perpetual trustee."[35]
+In 1886, the Photographic Society of Great Britain featured an exhibition of photos of Elstree Reservoir by Edgar Clifton.[36] During World War I, then Major Keith Caldwell with No. 74 Squadron RAF, used Elstree Reservoir for target practice.[37] In 1918, one of the pilots accidentally killed a local resident when his machine gun misfired.[38]
+      </fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <!-- first float -->
+    <eval expected="11000" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[3]/@left-offset" />
+    <eval expected="40692" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[7]/text/@ipd" />
+    <eval expected="orange." xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[7]" />
+    <eval expected="122000" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[4]/@left-offset" />
+    <eval expected="content before the float and the float is" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[4]/lineArea[1]" />
+    <eval expected="built in 1795 by French prisoners of war.[34] English" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[6]/lineArea[1]" />
+    <!-- second float -->
+    <eval expected="240000" xpath="//pageViewport[2]/page/regionViewport[1]//flow[2]/block[3]/@left-offset" />
+    <eval expected="25344" xpath="//pageViewport[2]/page/regionViewport[1]//flow[2]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[8]/text/@ipd" />
+    <eval expected="pink." xpath="//pageViewport[2]/page/regionViewport[1]//flow[2]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[8]" />
+    <eval expected="content before the float and the float is" xpath="//pageViewport[2]/page/regionViewport[1]//flow[2]/block[4]/lineArea[1]" />
+    <eval expected="war.[34] English watercolour landscape painter John Hassell" xpath="//pageViewport[2]/page/regionViewport[1]//flow[2]/block[6]/lineArea[1]" />
+    <!-- third float -->
+    <eval expected="11000" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[3]/@left-offset" />
+    <eval expected="136068" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[4]/text/@ipd" />
+    <eval expected="The background is green." xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[3]/block[1]/block[1]/block[1]/block[1]/lineArea[4]" />
+    <eval expected="172000" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[4]/@left-offset" />
+    <eval expected="content before the float and" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[4]/lineArea[1]" />
+    <eval expected="wrapped around the float... this is very complicated but the" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[5]/lineArea[1]" />
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/float_3.xml b/test/layoutengine/standard-testcases/float_3.xml
new file mode 100644 (file)
index 0000000..770e782
--- /dev/null
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks floats.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master margin="50pt" master-name="page" page-height="800pt" page-width="600pt">
+      <fo:region-body background-color="yellow" />
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body">
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="start">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="110pt">
+              <fo:block background-color="green">
+                This is a normal block that is confined to the block container inside a side float. The background is green.
+              </fo:block>
+            </fo:block-container>
+            <fo:block>This line is not constrained by a width. xxx xxx xxx xxx xxx</fo:block>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <!-- first float -->
+    <eval expected="11000" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[2]/@left-offset" />
+    <eval expected="green." xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[2]/block[1]/block[1]/block[1]/block[1]/lineArea[7]" />
+    <eval expected="331432" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[3]/@left-offset" />
+    <eval expected="last content before the float" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[3]/lineArea[1]" />
+    <eval expected="handle the simpler cases." xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[3]/lineArea[10]" />
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/float_4.xml b/test/layoutengine/standard-testcases/float_4.xml
new file mode 100644 (file)
index 0000000..9db4ec3
--- /dev/null
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks floats.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master margin="50pt" master-name="page" page-height="800pt" page-width="600pt">
+      <fo:region-body background-color="yellow" />
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body">
+      <fo:block>
+        <fo:table table-layout="fixed" width="100%">
+          <fo:table-body>
+            <fo:table-row>
+              <fo:table-cell>
+                <fo:block>C11</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block>C12</fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+            <fo:table-row>
+              <fo:table-cell>
+                <fo:block>C21</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block>C22</fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+            <fo:table-row>
+              <fo:table-cell>
+                <fo:block>C31</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block>C32</fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+            <fo:table-row>
+              <fo:table-cell>
+                <fo:block>C41</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block>C42</fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+            <fo:table-row>
+              <fo:table-cell>
+                <fo:block>C51</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block>C52</fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+          </fo:table-body>
+        </fo:table>
+      </fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="start">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="110pt">
+              <fo:block background-color="green">
+                This is a normal block that is confined to the block container inside a side float. The background is green.
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+        <fo:table table-layout="fixed" width="100%">
+          <fo:table-body>
+            <fo:table-row>
+              <fo:table-cell>
+                <fo:block>C11</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block>C12</fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+            <fo:table-row>
+              <fo:table-cell>
+                <fo:block>C21</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block>C22</fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+            <fo:table-row>
+              <fo:table-cell>
+                <fo:block>C31</fo:block>
+              </fo:table-cell>
+              <fo:table-cell>
+                <fo:block>C32</fo:block>
+              </fo:table-cell>
+            </fo:table-row>
+          </fo:table-body>
+        </fo:table>
+      </fo:block>
+      <fo:block>Content after the table. Floats cannot be handled if next to a table, unless the table starts and ends between the start and the end of the float. Tables before or after floats are not a problem.</fo:block>
+      <fo:block>
+        Put some content before the float but enough to make the float go to the third line of this block. Just enought content to place the float in the second line is not desirable. <fo:inline color="red">This is the last content before the float and the float is right now.</fo:inline>
+        <fo:float float="end">
+          <fo:block border="1pt solid red" padding="10pt" color="blue" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="110pt">
+              <fo:block background-color="orange">
+                This is a normal block that is confined to the block container inside a side float. The background is orange.
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+        <fo:inline color="blue">This is the first content after the float.</fo:inline> This paragraph contains a side float and the content of the paragraph needs to be wrapped around the float... this is very complicated but the current implementation can handle the simpler cases.
+      </fo:block>
+      <fo:block>
+        <fo:list-block>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+                here is text in the list item body and lets make sure the text is enought to wrap at the edge of the float
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(b)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+                here is text in the list item body
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+        </fo:list-block>
+      </fo:block>
+      <fo:block>Content after the list. Floats cannot be handled if next to a list, unless the list starts and ends between the start and the end of the float. Lists before or after a float are not a problem.</fo:block>
+      <fo:block>
+        <fo:list-block >
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+                here is text in the list item body
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(b)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+                here is text in the list item body
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(c)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+                here is text in the list item body
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(d)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+                here is text in the list item body
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+        </fo:list-block>
+      </fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <!-- first float -->
+    <eval expected="132000" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[5]/@left-offset" />
+    <eval expected="C11" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[5]/block[1]/block[1]/block[1]/lineArea[1]" />
+    <eval expected="379000" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[9]/@left-offset" />
+    <eval expected="here is text in the list item body and lets make sure the text is" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[11]/block[1]/block[1]/block[2]/block[1]/lineArea[1]" />
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/float_5.xml b/test/layoutengine/standard-testcases/float_5.xml
new file mode 100644 (file)
index 0000000..e43d9d6
--- /dev/null
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks floats.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master margin="0.25in" master-name="page" page-height="11in" page-width="8.5in">
+      <fo:region-body />
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body">
+      <fo:block>
+Did you know... (taken from Wikipedia main page on November 6th, 2014, with the order slightly changed to better show the wrapping around the float)
+      </fo:block>
+      <fo:block>
+From Wikipedia's new and recently improved content:
+      </fo:block>
+      <fo:block>
+        <fo:float float="end">
+          <fo:block border="1pt solid red" padding="5pt" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="120pt">
+              <fo:block background-color="yellow">
+The former dean's house at the University of Wisconsin (this is the alt text of the image in the Wikipedia page)
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+      </fo:block>
+      <fo:block>
+        <fo:list-block>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that the Queen Anne house (pictured) at the Allen Centennial Gardens was home to four deans of the University of Wisconsin–Madison College of Agricultural and Life Sciences?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that rhapsodomancy was so vague, Virgil wrote against it in The Aeneid?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that Australian physician Claudia Burton Bradley was one of the first diabetics to be treated with insulin?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that Green Bay Packers offensive lineman David Bakhtiari was the first rookie in Packers history to start every game at left tackle in a season since the start of the 16-game season?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that in the Byzantine Empire, the office of orphanotrophos, head of the imperial orphanage, ranked among the higher offices of state?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that the stream Shingle Run is actually named after sawmills?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that while testifying in a 2004 lawsuit involving the meaning of the word steakburger, a corporate CEO was grilled on the witness stand?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+        </fo:list-block>
+      </fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <!-- first float -->
+    <eval expected="450000" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[4]/@left-offset" />
+    <eval expected="... that the Queen Anne house (pictured) at the Allen Centennial Gardens" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[6]/block[1]/block[1]/block[2]/block[1]/lineArea[1]" />
+    <eval expected="... that Green Bay Packers offensive lineman David Bakhtiari was the first" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[6]/block[1]/block[4]/block[2]/block[1]/lineArea[1]" />
+    <eval expected="rookie in Packers history to start every game at left tackle in a season since the start of the 16-game" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[7]/block[1]/block[1]/block[1]/block[1]/lineArea[1]" />
+  </checks>
+</testcase>
+
+
diff --git a/test/layoutengine/standard-testcases/float_6.xml b/test/layoutengine/standard-testcases/float_6.xml
new file mode 100644 (file)
index 0000000..543096a
--- /dev/null
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks floats.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master margin="0.25in" master-name="page" page-height="11in" page-width="8.5in">
+      <fo:region-body />
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body">
+      <fo:block>
+Did you know... (taken from Wikipedia main page on November 6th, 2014, with the order slightly changed to better show the wrapping around the float)
+      </fo:block>
+      <fo:block>
+From Wikipedia's new and recently improved content:
+      </fo:block>
+      <fo:block>
+        <fo:list-block>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that while testifying in a 2004 lawsuit involving the meaning of the word steakburger, a corporate CEO was grilled on the witness stand?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that the Queen Anne house (pictured) 
+        <fo:float float="end">
+          <fo:block border="1pt solid red" padding="5pt" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="120pt">
+              <fo:block background-color="yellow">
+The former dean's house at the University of Wisconsin (this is the alt text of the image in the Wikipedia page)
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+at the Allen Centennial Gardens was home to four deans of the University of Wisconsin–Madison College of Agricultural and Life Sciences?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that rhapsodomancy was so vague, Virgil wrote against it in The Aeneid?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that Australian physician Claudia Burton Bradley was one of the first diabetics to be treated with insulin?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that Green Bay Packers offensive lineman David Bakhtiari was the first rookie in Packers history to start every game at left tackle in a season since the start of the 16-game season?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that in the Byzantine Empire, the office of orphanotrophos, head of the imperial orphanage, ranked among the higher offices of state?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>&#x2022;</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+... that the stream Shingle Run is actually named after sawmills?
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+        </fo:list-block>
+      </fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <!-- first float -->
+    <eval expected="450000" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[4]/@left-offset" />
+    <eval expected="... that the Queen Anne house (pictured) at the Allen Centennial Gardens" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[5]/block[1]/block[1]/block[2]/block[1]/lineArea[1]" />
+    <eval expected="was home to four deans of the University of Wisconsin–Madison College of" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[5]/block[1]/block[1]/block[2]/block[1]/lineArea[2]" />
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/float_7.xml b/test/layoutengine/standard-testcases/float_7.xml
new file mode 100644 (file)
index 0000000..6e51ea9
--- /dev/null
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks floats.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="simple" page-height="5in" page-width="5in" margin="0.2in">
+          <fo:region-body />
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="simple">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block font-size="12pt" space-before="3pt" text-indent="0.75cm" text-align="justify">
+            Footnote in normal block before a float.<fo:footnote>
+              <fo:inline font-size="60%" baseline-shift="super">1)</fo:inline>
+              <fo:footnote-body>
+                <fo:block start-indent="0.5cm" text-indent="-0.5cm">
+                  <fo:inline font-size="60%" baseline-shift="super">1)</fo:inline> The footnote from the normal block before the float.</fo:block>
+              </fo:footnote-body>
+            </fo:footnote>.
+          </fo:block>
+          <fo:list-block provisional-distance-between-starts="30pt" provisional-label-separation="10pt">
+            <fo:list-item>
+              <fo:list-item-label end-indent="label-end()">
+                <fo:block>(a)</fo:block>
+              </fo:list-item-label>
+              <fo:list-item-body start-indent="body-start()">
+                <fo:block>
+                  Test for float and footnote inside a list. Test for float and footnote inside a list. Test for float and footnote inside a list. (see box)
+        <fo:float float="end">
+          <fo:block border="1pt solid red" padding="5pt" end-indent="0pt" start-indent="0pt">
+            <fo:block-container inline-progression-dimension="120pt">
+              <fo:block background-color="yellow">
+The former dean's house at the University of Wisconsin (this is the alt text of the image in the Wikipedia page)
+              </fo:block>
+            </fo:block-container>
+          </fo:block>
+        </fo:float>
+                  Test for float and footnote inside a list. Test for float and footnote inside a list.
+                </fo:block>
+              </fo:list-item-body>
+            </fo:list-item>
+            <fo:list-item>
+              <fo:list-item-label end-indent="label-end()">
+                <fo:block>(b)</fo:block>
+              </fo:list-item-label>
+              <fo:list-item-body start-indent="body-start()">
+                <fo:block>
+                  Footnote in list that is being wrapped around a float.<fo:footnote>
+                  <fo:inline font-size="60%" baseline-shift="super">2)</fo:inline>
+                    <fo:footnote-body>
+                      <fo:block start-indent="0.5cm" text-indent="-0.5cm">
+                        <fo:inline font-size="60%" baseline-shift="super">2)</fo:inline> The footnote from the list that is being wrapped around a float.</fo:block>
+                    </fo:footnote-body>
+                  </fo:footnote>.
+                  Test for float and footnote inside a list. Test for float and footnote inside a list. Test for float and footnote inside a list. Test for float and footnote inside a list. Test for float and footnote inside a list.
+                </fo:block>
+              </fo:list-item-body>
+            </fo:list-item>
+          </fo:list-block>
+          <fo:block font-size="12pt" space-before="3pt" text-indent="0.75cm" text-align="justify">
+            Footnote in normal block after the float.<fo:footnote>
+              <fo:inline font-size="60%" baseline-shift="super">3)</fo:inline>
+              <fo:footnote-body>
+                <fo:block start-indent="0.5cm" text-indent="-0.5cm">
+                  <fo:inline font-size="60%" baseline-shift="super">3)</fo:inline> The footnote from the normal block after the float.</fo:block>
+              </fo:footnote-body>
+            </fo:footnote>.
+          </fo:block>
+          <fo:block>
+Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.  Some filler text.
+          </fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <!-- footnotes -->
+    <eval expected="265113" xpath="//pageViewport[1]/page/regionViewport[1]//footnote[1]/@top-offset" />
+    <eval expected="1) The footnote from the normal block before the float." xpath="//pageViewport[1]/page/regionViewport[1]//footnote[1]/block[1]/lineArea[1]" />
+    <eval expected="2) The footnote from the list that is being wrapped around a" xpath="//pageViewport[1]/page/regionViewport[1]//footnote[1]/block[2]/lineArea[1]" />
+    <eval expected="3) The footnote from the normal block after the float." xpath="//pageViewport[1]/page/regionViewport[1]//footnote[1]/block[3]/lineArea[1]" />
+   <!-- last line in second page -->
+    <eval expected="text. Some filler text. Some filler text. Some filler text." xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[1]/lineArea[11]" />
+  </checks>
+</testcase>
index fe166d05ce2f90fe13484c504621bb81464556da..4b0aea09394c8b88ba91da6e70ce59610363dece 100644 (file)
@@ -19,8 +19,7 @@
 <testcase>
   <info>
     <p>
-      This test checks that non-restartable elements still show up at IPD change, even if not 
-      re-laid out.
+      This test checks that a list can be relaid out when a change in ipd happens across pages.
     </p>
   </info>
   <fo>
     <eval expected="olden"  xpath="//pageSequence[1]/pageViewport[2]//flow/block[2]//lineArea[1]/text/word[2]"/>
 
     <!-- Second page sequence – list -->
-    <eval expected="300000" xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/@ipd"/>
+    <eval expected="500000" xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/@ipd"/>
     <eval expected="b2_4"   xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/block/block[2]/block/@prod-id"/>
     <eval expected="In"     xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/block/block[2]/block/lineArea[1]/text/word[1]"/>
     <eval expected="olden"  xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/block/block[2]/block/lineArea[1]/text/word[2]"/>
-    <eval expected="was"    xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/block/block[2]/block/lineArea[4]/text/word[position()=last()-1]"/>
+    <eval expected="was"    xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/block/block[2]/block/lineArea[3]/text/word[position()=last()-1]"/>
     <eval expected="astonished…"
-                            xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/block/block[2]/block/lineArea[4]/text/word[position()=last()]"/>
+                            xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]/block/block[2]/block/lineArea[3]/text/word[position()=last()]"/>
 
     <eval expected="b2_5"   xpath="//pageSequence[2]/pageViewport[2]//flow/block[2]/@prod-id"/>
     <eval expected="500000" xpath="//pageSequence[2]/pageViewport[2]//flow/block[2]/@ipd"/>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_5.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_5.xml
new file mode 100644 (file)
index 0000000..a027ff1
--- /dev/null
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks that a list can be relaid out when a change in ipd happens across pages.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="narrow" page-height="200pt" page-width="400pt" margin="50pt">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="wide" page-height="200pt" page-width="600pt" margin="50pt">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:single-page-master-reference master-reference="narrow"/>
+          <fo:repeatable-page-master-reference master-reference="wide"/>
+        </fo:page-sequence-master>
+        <fo:page-sequence-master master-name="alternate">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference odd-or-even="odd" master-reference="wide"/>
+            <fo:conditional-page-master-reference odd-or-even="even" master-reference="narrow"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="alternate">
+        <fo:flow flow-name="xsl-region-body">
+      <fo:block widows="1" orphans="1">
+        <fo:list-block>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face.
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face.
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face.
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face.
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face.
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face.
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face.
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+          <fo:list-item>
+            <fo:list-item-label end-indent="label-end()">
+              <fo:block>(a)</fo:block>
+            </fo:list-item-label>
+            <fo:list-item-body start-indent="body-start()">
+              <fo:block>
+In olden times when wishing still helped one, there lived a king whose daughters were all beautiful, but the youngest was so beautiful that the sun itself, which has seen so much, was astonished whenever it shone in her face.
+              </fo:block>
+            </fo:list-item-body>
+          </fo:list-item>
+        </fo:list-block>
+      </fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="In olden times when wishing still helped one, there lived a king whose daughters were all" xpath="//pageViewport[1]/page/regionViewport[1]//flow[1]/block[1]/block[1]/block[1]/block[2]/block[1]/lineArea[1]" />
+    <eval expected="In olden times when wishing still helped one, there" xpath="//pageViewport[2]/page/regionViewport[1]//flow[1]/block[1]/block[1]/block[1]/block[2]/block[1]/lineArea[1]" />
+    <eval expected="lived a king whose daughters were all beautiful, but the youngest was so beautiful that" xpath="//pageViewport[3]/page/regionViewport[1]//flow[1]/block[1]/block[1]/block[1]/block[1]/block[1]/lineArea[1]" />
+    <eval expected="beautiful, but the youngest was so beautiful that the" xpath="//pageViewport[4]/page/regionViewport[1]//flow[1]/block[1]/block[1]/block[1]/block[1]/block[1]/lineArea[1]" />
+    <eval expected="itself, which has seen so much, was astonished whenever it shone in her face." xpath="//pageViewport[5]/page/regionViewport[1]//flow[1]/block[1]/block[1]/block[1]/block[1]/block[1]/lineArea[1]" />
+  </checks>
+</testcase>