]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Block Knuth sequences in inline content are properly joined, taking
authorSimon Pepping <spepping@apache.org>
Fri, 30 Dec 2005 11:39:08 +0000 (11:39 +0000)
committerSimon Pepping <spepping@apache.org>
Fri, 30 Dec 2005 11:39:08 +0000 (11:39 +0000)
keeps into account.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@360073 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/layoutmgr/BlockKnuthSequence.java
src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java
src/java/org/apache/fop/layoutmgr/KnuthSequence.java
src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
test/layoutengine/standard-testcases/inline_block_nested_6.xml [new file with mode: 0644]

index c3c837f1ee4f7ddd8c357a8629825c12d0c5bc4d..9ef3d61e3777f08ddcb6cea86aa3b4613c7e4b06 100644 (file)
@@ -57,109 +57,33 @@ public class BlockKnuthSequence extends KnuthSequence {
         return !sequence.isInlineSequence() && !isClosed;
     }
 
-    /**
-     * this and sequence are supposed to belong to the same LayoutManager,
-     * which is stored in the positions of the elements in the sequences
-     * @param sequence The sequence following this
-     * @return whether this and the following sequence must be kept together
-     */
-    private boolean mustKeepWithNext(BlockKnuthSequence sequence) {
-/*        // TODO read keep together correctly
-        // for now, return false
-        return BlockKnuthSequence.mustKeepTogether(this, sequence);
-*/        return false;
-    }
-
-    /**
-     * the two sequences are supposed to belong to the same LayoutManager,
-     * which is stored in the positions of the elements in the sequences
-     * @param sequence1 The leading sequence
-     * @param sequence2 The following sequence
-     * @return whether the two sequences must be kept together
+    /* (non-Javadoc)
+     * @see org.apache.fop.layoutmgr.KnuthList#appendSequence(org.apache.fop.layoutmgr.KnuthSequence,)
      */
-    public static boolean mustKeepTogether(BlockKnuthSequence sequence1,
-                                           BlockKnuthSequence sequence2) {
-        ListElement element1 = (ListElement) sequence1.get(sequence1.size() - 1);
-        LayoutManager lm1 = (LayoutManager) element1.getLayoutManager();
-        ListElement element2 = (ListElement) sequence2.get(0);
-        LayoutManager lm2 = (LayoutManager) element2.getLayoutManager();
-        if (!lm1.equals(lm2)) {
-            throw new IllegalStateException
-              ("The two sequences must belong to the same LayoutManager");
-        }
-        if (lm1 instanceof BlockLevelLayoutManager
-                && ((BlockLevelLayoutManager) lm1).mustKeepTogether()) {
-            return true;
-        }
-        Position pos1 = element1.getPosition();
-        if (pos1 != null) {
-            pos1 = pos1.getPosition();
-            if (pos1 != null) {
-                lm1 = pos1.getLM();
-                if (lm1 instanceof BlockLevelLayoutManager
-                    && ((BlockLevelLayoutManager) lm1).mustKeepWithNext()) {
-                        return true;
-                } 
-            }
-        }
-        Position pos2 = element1.getPosition();
-        if (pos2 != null) {
-            pos2 = pos2.getPosition();
-            if (pos2 != null) {
-                lm2 = pos2.getLM();
-                if (lm2 instanceof BlockLevelLayoutManager
-                    && ((BlockLevelLayoutManager) lm2).mustKeepWithPrevious()) {
-                        return true;
-                } 
-            }
-        }
+    public boolean appendSequence(KnuthSequence sequence) {
+        // log.debug("Cannot append a sequence without a BreakElement");
         return false;
-/*      From BlockStackingLM.getChangedKnuthElements
-        // there is another block after this one
-        if (bSomethingAdded
-            && (this.mustKeepTogether()
-                || prevLM.mustKeepWithNext()
-                || currLM.mustKeepWithPrevious())) {
-            // add an infinite penalty to forbid a break between blocks
-            returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, 
-                    new Position(this), false));
-        } else if (bSomethingAdded && !((KnuthElement) returnedList.getLast()).isGlue()) {
-            // add a null penalty to allow a break between blocks
-            returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
-        }
-*/    }
-
+    }
+    
     /* (non-Javadoc)
-     * @see org.apache.fop.layoutmgr.KnuthList#appendSequence(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager)
+     * @see KnuthList#appendSequence(KnuthSequence, boolean, BreakElement)
      */
-    /**
-     * this and sequence are supposed to belong to the same LayoutManager,
-     * which is stored in the positions of the elements in the sequences
-     */
-    public boolean appendSequence(KnuthSequence sequence, LayoutManager lm) {
+    public boolean appendSequence(KnuthSequence sequence, boolean keepTogether,
+                                  BreakElement breakElement) {
         if (!canAppendSequence(sequence)) {
             return false;
         }
-/*        // TODO disable because InlineLM.addAreas expects only NonLeafPostions; why?
-        if (!mustKeepWithNext((BlockKnuthSequence) sequence)) {
-            add(new KnuthPenalty(0, 0, false, new Position(lm), false));
+        if (keepTogether) {
+            breakElement.setPenaltyValue(KnuthElement.INFINITE);
+            add(breakElement);
+        } else if (!((ListElement) getLast()).isGlue()) {
+            breakElement.setPenaltyValue(0);
+            add(breakElement);
         }
-*/        addAll(sequence);
+        addAll(sequence);
         return true;
     }
 
-    /* (non-Javadoc)
-     * @see org.apache.fop.layoutmgr.KnuthList#appendSequenceOrClose(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager)
-     */
-    public boolean appendSequenceOrClose(KnuthSequence sequence, LayoutManager lm) {
-        if (!appendSequence(sequence, lm)) {
-            endSequence();
-            return false;
-        } else {
-            return true;
-        }
-    }
-    
     /* (non-Javadoc)
      * @see org.apache.fop.layoutmgr.KnuthSequence#endSequence()
      */
index e495b40629fed524feb245088a72953e91227964..631aacf3265c49b147064d20153da9269a6046c2 100644 (file)
@@ -27,6 +27,7 @@ import org.apache.fop.area.Block;
 import org.apache.fop.area.LineArea;
 import org.apache.fop.datatypes.Length;
 import org.apache.fop.fonts.Font;
+import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
 import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager;
 import org.apache.fop.layoutmgr.inline.LineLayoutManager;
 import org.apache.fop.traits.MinOptMax;
@@ -198,13 +199,15 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
      * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether()
      */
     public boolean mustKeepTogether() {
-        //TODO Keeps will have to be more sophisticated sooner or later
+        // TODO Keeps will have to be more sophisticated sooner or later
         // TODO This is a quick fix for the fact that the parent is not always a BlockLevelLM;
         // eventually mustKeepTogether() must be moved up to the LM interface
-        return (getParent() instanceof BlockLevelLayoutManager
-                && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) 
-                || !getBlockFO().getKeepTogether().getWithinPage().isAuto()
-                || !getBlockFO().getKeepTogether().getWithinColumn().isAuto();
+        return (!getBlockFO().getKeepTogether().getWithinPage().isAuto()
+                || !getBlockFO().getKeepTogether().getWithinColumn().isAuto()
+                || (getParent() instanceof BlockLevelLayoutManager
+                    && ((BlockLevelLayoutManager) getParent()).mustKeepTogether())
+                || (getParent() instanceof InlineLayoutManager
+                    && ((InlineLayoutManager) getParent()).mustKeepTogether()));
     }
 
     /**
@@ -212,7 +215,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
      */
     public boolean mustKeepWithPrevious() {
         return !getBlockFO().getKeepWithPrevious().getWithinPage().isAuto()
-            || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto();
+                || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto();
     }
 
     /**
index 494d732d7b20474c328a8e29569db2c89b6b7ff6..c09ae8ae5719e2aa521bfed978dadda253b58a5a 100644 (file)
@@ -29,6 +29,7 @@ import org.apache.fop.area.Block;
 import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fo.properties.SpaceProperty;
+import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
 import org.apache.fop.layoutmgr.inline.LineLayoutManager;
 import org.apache.fop.traits.MinOptMax;
 
@@ -309,9 +310,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
                     if (mustKeepTogether() 
                             || context.isKeepWithNextPending()
                             || childLC.isKeepWithPreviousPending()) {
-                        //Clear keep pending flag
+                        // Clear keep pending flag
                         context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
-                        childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
                         // add an infinite penalty to forbid a break between
                         // blocks
                         contentList.add(new BreakElement(
@@ -368,11 +368,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
                     return returnList;
                 }*/
             }
-            if (childLC.isKeepWithNextPending()) {
-                //Clear and propagate
-                childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
-                context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
-            }
+            // propagate and clear
+            context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, childLC.isKeepWithNextPending());
+            childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
+            childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
             prevLM = curLM;
         }
 
@@ -617,6 +616,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
                 }
                 fromIndex = workListIterator.previousIndex();
 
+                /*
+                 * TODO: why are KnuthPenalties added here,
+                 *       while in getNextKE they were changed to BreakElements?
+                 */
                 // there is another block after this one
                 if (bSomethingAdded
                     && (this.mustKeepTogether()
@@ -732,8 +735,12 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
     /**
      * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether()
      */
+    // default action: ask parentLM
     public boolean mustKeepTogether() {
-        return false;
+        return ((getParent() instanceof BlockLevelLayoutManager
+                    && ((BlockLevelLayoutManager) getParent()).mustKeepTogether())
+                || (getParent() instanceof InlineLayoutManager
+                    && ((InlineLayoutManager) getParent()).mustKeepTogether()));
     }
 
     /**
index efe3e28ce153f024877844a9efabdff4cef06d02..0e48eb1ae29605a68d139b2be7619d59fcf85b64 100644 (file)
@@ -26,7 +26,8 @@ import org.apache.fop.layoutmgr.inline.KnuthInlineBox;
 
 
 /**
- * 
+ * Represents a list of inline Knuth elements.
+ * If closed, it represents all elements of a Knuth paragraph.
  */
 public class InlineKnuthSequence extends KnuthSequence  {
 
@@ -63,9 +64,9 @@ public class InlineKnuthSequence extends KnuthSequence  {
     }
 
     /* (non-Javadoc)
-     * @see org.apache.fop.layoutmgr.KnuthSequence#appendSequence(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager)
+     * @see org.apache.fop.layoutmgr.KnuthSequence#appendSequence(org.apache.fop.layoutmgr.KnuthSequence)
      */
-    public boolean appendSequence(KnuthSequence sequence, LayoutManager lm) {
+    public boolean appendSequence(KnuthSequence sequence) {
         if (!canAppendSequence(sequence)) {
             return false;
         }
@@ -82,17 +83,14 @@ public class InlineKnuthSequence extends KnuthSequence  {
     }
 
     /* (non-Javadoc)
-     * @see org.apache.fop.layoutmgr.KnuthSequence#appendSequenceOrClose(org.apache.fop.layoutmgr.KnuthSequence, org.apache.fop.layoutmgr.LayoutManager)
+     * @see KnuthSequence#appendSequence(KnuthSequence, boolean, BreakElement)
      */
-    public boolean appendSequenceOrClose(KnuthSequence sequence, LayoutManager lm) {
-        if (!appendSequence(sequence, lm)) {
-            endSequence();
-            return false;
-        } else {
-            return true;
-        }
+    public boolean appendSequence(KnuthSequence sequence, boolean keepTogether,
+                                  BreakElement breakElement) {
+        return appendSequence(sequence);
     }
 
+        
     /* (non-Javadoc)
      * @see org.apache.fop.layoutmgr.KnuthSequence#endSequence()
      */
@@ -108,9 +106,9 @@ public class InlineKnuthSequence extends KnuthSequence  {
         KnuthBox prevBox = (KnuthBox) getLast();
         if (prevBox.isAuxiliary()
             && (size() < 4
-                || !getElement(size()-2).isGlue()
-                || !getElement(size()-3).isPenalty()
-                || !getElement(size()-4).isBox()
+                || !getElement(size() - 2).isGlue()
+                || !getElement(size() - 3).isPenalty()
+                || !getElement(size() - 4).isBox()
                )
            ) {
             // Not the sequence we are expecting
index 405af115736c497c2950523def825e301899143a..c574c7396d88075d0bcbd63942fffb42e8b52480 100644 (file)
@@ -65,22 +65,53 @@ public abstract class KnuthSequence extends ArrayList {
 
     /**
      * Append sequence to this sequence if it can be appended.
-     * TODO In principle the LayoutManager can also be retrieved from the elements in the sequence.
      * @param sequence The sequence that is to be appended.
-     * @param lm The LayoutManager for the Position that may have to be created. 
+     * @param keepTogether Whether the two sequences must be kept together.
+     * @param breakElement The BreakElement that may be inserted between the two sequences. 
      * @return whether the sequence was succesfully appended to this sequence.
      */
-    public abstract boolean appendSequence(KnuthSequence sequence, LayoutManager lm);
+    public abstract boolean appendSequence(KnuthSequence sequence, boolean keepTogether,
+                                           BreakElement breakElement);
+    
+    /**
+     * Append sequence to this sequence if it can be appended.
+     * @param sequence The sequence that is to be appended.
+     * @return whether the sequence was succesfully appended to this sequence.
+     */
+    public abstract boolean appendSequence(KnuthSequence sequence);
     
     /**
      * Append sequence to this sequence if it can be appended.
      * If that is not possible, close this sequence.
-     * TODO In principle the LayoutManager can also be retrieved from the elements in the sequence.
      * @param sequence The sequence that is to be appended.
-     * @param lm The LayoutManager for the Position that may have to be created. 
      * @return whether the sequence was succesfully appended to this sequence.
      */
-    public abstract boolean appendSequenceOrClose(KnuthSequence sequence, LayoutManager lm);
+    public boolean appendSequenceOrClose(KnuthSequence sequence) {
+        if (!appendSequence(sequence)) {
+            endSequence();
+            return false;
+        } else {
+            return true;
+        }
+    }
+    
+    /**
+     * Append sequence to this sequence if it can be appended.
+     * If that is not possible, close this sequence.
+     * @param sequence The sequence that is to be appended.
+     * @param keepTogether Whether the two sequences must be kept together.
+     * @param breakElement The BreakElement that may be inserted between the two sequences. 
+     * @return whether the sequence was succesfully appended to this sequence.
+     */
+    public boolean appendSequenceOrClose(KnuthSequence sequence, boolean keepTogether,
+                                         BreakElement breakElement) {
+        if (!appendSequence(sequence, keepTogether, breakElement)) {
+            endSequence();
+            return false;
+        } else {
+            return true;
+        }
+    }
     
     /**
      * Wrap the Positions of the elements of this sequence in a Position for LayoutManager lm.
index 633dda77deb6c208b069dc051a2bb15d74b914f7..d287b59f838ad4f0dd961947540de61bbde0a847 100755 (executable)
@@ -35,6 +35,8 @@ import org.apache.fop.fo.properties.CommonMarginInline;
 import org.apache.fop.fo.properties.SpaceProperty;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.layoutmgr.BlockKnuthSequence;
+import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
+import org.apache.fop.layoutmgr.BreakElement;
 import org.apache.fop.layoutmgr.KnuthBox;
 import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthSequence;
@@ -196,6 +198,24 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
         }
     }
 
+    /**
+     * @return true if this element must be kept together
+     */
+    // TODO Use the keep-together property on Inline as well
+    public boolean mustKeepTogether() {
+        return mustKeepTogether(this.getParent());
+    }
+
+    private boolean mustKeepTogether(LayoutManager lm) {
+        if (lm instanceof BlockLevelLayoutManager) {
+            return ((BlockLevelLayoutManager) lm).mustKeepTogether();
+        } else if (lm instanceof InlineLayoutManager) {
+            return ((InlineLayoutManager) lm).mustKeepTogether();
+        } else { 
+            return mustKeepTogether(lm.getParent());
+        }
+    }
+
     /** @see org.apache.fop.layoutmgr.LayoutManager */
     public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
         LayoutManager curLM;
@@ -267,6 +287,9 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
             }
             // get KnuthElements from curLM
             returnedList = curLM.getNextKnuthElements(childLC, alignment);
+            if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) {
+                childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
+            }
             if (returnedList == null) {
                 // curLM returned null because it finished;
                 // just iterate once more to see if there is another child
@@ -276,6 +299,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
                 continue;
             }
             if (curLM instanceof InlineLevelLayoutManager) {
+                context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
                 // "wrap" the Position stored in each element of returnedList
                 ListIterator seqIter = returnedList.listIterator();
                 while (seqIter.hasNext()) {
@@ -283,7 +307,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
                     sequence.wrapPositions(this);
                 }
                 if (lastSequence != null && lastSequence.appendSequenceOrClose
-                        ((KnuthSequence) returnedList.get(0), this)) {
+                        ((KnuthSequence) returnedList.get(0))) {
                     returnedList.remove(0);
                 }
                 // add border and padding to the first complete sequence of this LM
@@ -293,13 +317,21 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
                 }
                 returnList.addAll(returnedList);
             } else { // A block LM
-                // TODO For now avoid having two different block LMs in a single sequence
-                if (curLM != lastChildLM && lastSequence != null) {
-                    lastSequence.endSequence();
-                }
                 BlockKnuthSequence sequence = new BlockKnuthSequence(returnedList);
                 sequence.wrapPositions(this);
-                if (lastSequence == null || !lastSequence.appendSequenceOrClose(sequence, this)) {
+                boolean appended = false;
+                if (lastSequence != null) {
+                    if (lastSequence.canAppendSequence(sequence)) {
+                        BreakElement bk = new BreakElement(new Position(this), 0, context);
+                        boolean keepTogether = (mustKeepTogether()
+                                                || context.isKeepWithNextPending()
+                                                || childLC.isKeepWithPreviousPending());
+                        appended = lastSequence.appendSequenceOrClose(sequence, keepTogether, bk);
+                    } else {
+                        lastSequence.endSequence();
+                    }
+                }
+                if (!appended) {
                     // add border and padding to the first complete sequence of this LM
                     if (!borderAdded) {
                         addKnuthElementsForBorderPaddingStart(sequence);
@@ -307,6 +339,11 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
                     }
                     returnList.add(sequence);
                 }
+                // propagate and clear
+                context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING,
+                                 childLC.isKeepWithNextPending());
+                childLC.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
+                childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
             }
             lastSequence = (KnuthSequence) returnList.getLast();
             lastChildLM = curLM;
index aa6c4b862ba9d1ebe168dd4f6f81584e77169132..e3ea556692584b5e3e84b07795aadd262f984c8f 100644 (file)
@@ -1312,7 +1312,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager
      * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether
      */
     public boolean mustKeepTogether() {
-        return false;
+        return ((BlockLevelLayoutManager) getParent()).mustKeepTogether();
     }
 
     /**
diff --git a/test/layoutengine/standard-testcases/inline_block_nested_6.xml b/test/layoutengine/standard-testcases/inline_block_nested_6.xml
new file mode 100644 (file)
index 0000000..eeb0bdd
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright 2005 The Apache Software Foundation
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks the value of the penalties between
+      KnuthBlockBoxes in inline context, with and without keep conditions.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
+          <fo:region-body/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+
+      <fo:page-sequence master-reference="normal" white-space-collapse="true">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block><fo:inline>Before
+              <fo:block id="b1" background-color="silver"><fo:inline>Before1
+                  <fo:block id="b11" background-color="grey">A1=B1,</fo:block>
+                  <fo:block id="b12">C1=D1.</fo:block>after1</fo:inline></fo:block>
+              <fo:block id="b2" background-color="lightgrey" keep-together.within-page="always"><fo:inline>Before2
+                  <fo:block id="b21" background-color="grey">A2=B2,</fo:block>
+                  <fo:block id="b22">C2=D2.</fo:block>after2</fo:inline></fo:block>
+              <fo:block id="b3" background-color="silver"><fo:inline>Before3
+                  <fo:block id="b31" keep-with-next.within-page="always" background-color="grey">A3=B3,</fo:block>
+                  <fo:block id="b32">C3=D3.</fo:block>after3</fo:inline></fo:block>after</fo:inline></fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <element-list category="breaker">
+      <skip>5</skip>
+      <!-- penalty between blocks b11 and b12, set by InlineLM in b1 -->
+      <penalty w="0" p="0"/>
+      <skip>6</skip>
+      <!-- penalty between blocks b21 and b22, set by InlineLM in b2 -->
+      <!-- keep-together.within-page="always" -->
+      <penalty w="0" p="1000"/>
+      <skip>6</skip>
+      <!-- penalty between blocks b31 and b32, set by InlineLM in b3 -->
+      <!-- keep-with-next.within-page="always" -->
+      <penalty w="0" p="1000"/>
+      <skip>5</skip>
+      <skip>3</skip>
+    </element-list>
+  </checks>
+</testcase>