]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugfix: An IllegalArgumentException was thrown when break-before was used inside...
authorVincent Hennebert <vhennebert@apache.org>
Mon, 16 Jul 2012 19:09:00 +0000 (19:09 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Mon, 16 Jul 2012 19:09:00 +0000 (19:09 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1362203 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
src/java/org/apache/fop/layoutmgr/PageBreaker.java
src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
status.xml
test/layoutengine/standard-testcases/list-item-body_break-before.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/list-item-body_break-before_multicolumn.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-sequence_last-page_space-before.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-cell_break-before_multicolumn.xml [new file with mode: 0644]

index 0f7dda3e70c525267ff732922d4e32a048604b1d..843748226d32f2d20c21ec1bf199ee1e59fa65dd 100644 (file)
@@ -506,7 +506,17 @@ public abstract class AbstractBreaker {
                 ListElement lastBreakElement = effectiveList.getElement(endElementIndex);
                 if (lastBreakElement.isPenalty()) {
                     KnuthPenalty pen = (KnuthPenalty)lastBreakElement;
-                    lastBreakClass = pen.getBreakClass();
+                    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;
                 }
index adce89ac0343e6eb13980a18655667cb0597e632..53e59e6efebafe0096e761076abbdd01bd86c21e 100644 (file)
@@ -1044,10 +1044,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl
         return true;
     }
 
-    public int getBreakBefore() {
-        return BreakOpportunityHelper.getBreakBefore(this);
-    }
-
 }
 
 
index 03b2d380c23f902479918c6aecdb404d15d6ca52..711bf492f38cd3ae8fc43a9b5e62525980d8fdd2 100644 (file)
@@ -504,8 +504,4 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co
         return true;
     }
 
-    public int getBreakBefore() {
-        return BreakOpportunityHelper.getBreakBefore(this);
-    }
-
 }
index 78ab6711ac7e593fa8b665a4df7ee2ee25d641ff..d0586aa95f4871efbf87fa723e9b968d8e480562 100644 (file)
@@ -1035,7 +1035,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
      * @return true if an element has been added due to a break-before.
      */
     protected boolean addKnuthElementsForBreakBefore(List returnList, LayoutContext context) {
-        int breakBefore = BreakOpportunityHelper.getBreakBefore(this);
+        int breakBefore = getBreakBefore();
         if (breakBefore == EN_PAGE
                 || breakBefore == EN_COLUMN
                 || breakBefore == EN_EVEN_PAGE
@@ -1049,6 +1049,17 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
         }
     }
 
+    /**
+     * Returns the highest priority break-before value on this layout manager or its
+     * relevant descendants.
+     *
+     * @return the break-before value (Constants.EN_*)
+     * @see BreakOpportunity#getBreakBefore()
+     */
+    public int getBreakBefore() {
+        return BreakOpportunityHelper.getBreakBefore(this);
+    }
+
     /**
      * Creates Knuth elements for break-after and adds them to the return list.
      * @param returnList return list to add the additional elements to
index 777180c55b32a3afd1806d81e33c213649a665dc..791adc7637be6edf23f7515a6dbdcf6a281c3486 100644 (file)
@@ -521,7 +521,6 @@ public class PageBreaker extends AbstractBreaker {
             return;
         case Constants.EN_COLUMN:
         case Constants.EN_AUTO:
-        case Constants.EN_PAGE:
         case -1:
             PageViewport pv = curPage.getPageViewport();
 
@@ -545,6 +544,7 @@ public class PageBreaker extends AbstractBreaker {
                 /*curPage = */pslm.makeNewPage(false);
             }
             return;
+        case Constants.EN_PAGE:
         default:
             log.debug("handling break-before after page " + pslm.getCurrentPageNum()
                 + " breakVal=" + getBreakClassName(breakVal));
@@ -560,7 +560,7 @@ public class PageBreaker extends AbstractBreaker {
     }
 
     /**
-     * Check if a blank page is needed to accomodate
+     * Check if a blank page is needed to accommodate
      * desired even or odd page number.
      * @param breakVal - value of break-before or break-after trait.
      */
index a84069082eb09e17b16637384a201853bcd10fe0..4db101cd35fbd4804f1d0fa459f1f7af939b1165 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.fop.layoutmgr.list;
 
 import java.util.LinkedList;
+import java.util.List;
 
 import org.apache.fop.area.Area;
 import org.apache.fop.area.Block;
@@ -28,9 +29,11 @@ import org.apache.fop.fo.flow.ListItemBody;
 import org.apache.fop.fo.flow.ListItemLabel;
 import org.apache.fop.fo.properties.KeepProperty;
 import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.BreakOpportunity;
 import org.apache.fop.layoutmgr.Keep;
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.ListElement;
 import org.apache.fop.layoutmgr.NonLeafPosition;
 import org.apache.fop.layoutmgr.Position;
 import org.apache.fop.layoutmgr.PositionIterator;
@@ -40,7 +43,7 @@ import org.apache.fop.layoutmgr.TraitSetter;
 /**
  * LayoutManager for a list-item-label or list-item-body FO.
  */
-public class ListItemContentLayoutManager extends BlockStackingLayoutManager {
+public class ListItemContentLayoutManager extends BlockStackingLayoutManager implements BreakOpportunity {
 
     private Block curBlockArea;
 
@@ -220,5 +223,16 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager {
     public Keep getKeepWithPrevious() {
         return Keep.KEEP_AUTO;
     }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) {
+        List<ListElement> elements = new LinkedList<ListElement>();
+        do {
+            elements.addAll(super.getNextKnuthElements(context, alignment));
+        } while (!isFinished());
+        return elements;
+    }
+
 }
 
index bc7daa24f30eff5a31cdd44905cc074e1c1a068c..dd2e8d6e1cde74c4139569f68e798adf992d9762 100644 (file)
@@ -35,6 +35,8 @@ import org.apache.fop.fo.flow.ListItemLabel;
 import org.apache.fop.fo.properties.KeepProperty;
 import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
 import org.apache.fop.layoutmgr.BreakElement;
+import org.apache.fop.layoutmgr.BreakOpportunity;
+import org.apache.fop.layoutmgr.BreakOpportunityHelper;
 import org.apache.fop.layoutmgr.ConditionalElementListener;
 import org.apache.fop.layoutmgr.ElementListObserver;
 import org.apache.fop.layoutmgr.ElementListUtils;
@@ -56,13 +58,14 @@ import org.apache.fop.layoutmgr.SpaceResolver;
 import org.apache.fop.layoutmgr.TraitSetter;
 import org.apache.fop.traits.MinOptMax;
 import org.apache.fop.traits.SpaceVal;
+import org.apache.fop.util.BreakUtil;
 
 /**
  * LayoutManager for a list-item FO.
  * The list item contains a list item label and a list item body.
  */
-public class ListItemLayoutManager extends BlockStackingLayoutManager
-                    implements ConditionalElementListener {
+public class ListItemLayoutManager extends BlockStackingLayoutManager implements ConditionalElementListener,
+        BreakOpportunity {
 
     /** logging instance */
     private static Log log = LogFactory.getLog(ListItemLayoutManager.class);
@@ -204,6 +207,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
 
         // label
         childLC = makeChildLayoutContext(context);
+        childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
         label.initialize();
         labelList = label.getNextKnuthElements(childLC, alignment);
 
@@ -217,6 +221,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
 
         // body
         childLC = makeChildLayoutContext(context);
+        childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
         body.initialize();
         bodyList = body.getNextKnuthElements(childLC, alignment);
 
@@ -296,16 +301,23 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
             //Additional penalty height from penalties in the source lists
             int additionalPenaltyHeight = 0;
             int stepPenalty = 0;
+            int breakClass = EN_AUTO;
             KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]);
             if (endEl instanceof KnuthPenalty) {
                 additionalPenaltyHeight = endEl.getWidth();
-                stepPenalty = Math.max(stepPenalty, endEl.getPenalty());
+                stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math
+                        .max(stepPenalty, endEl.getPenalty());
+                breakClass = BreakUtil.compareBreakClasses(breakClass,
+                        ((KnuthPenalty) endEl).getBreakClass());
             }
             endEl = (KnuthElement)elementLists[1].get(end[1]);
             if (endEl instanceof KnuthPenalty) {
                 additionalPenaltyHeight = Math.max(
                         additionalPenaltyHeight, endEl.getWidth());
-                stepPenalty = Math.max(stepPenalty, endEl.getPenalty());
+                stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math
+                        .max(stepPenalty, endEl.getPenalty());
+                breakClass = BreakUtil.compareBreakClasses(breakClass,
+                        ((KnuthPenalty) endEl).getBreakClass());
             }
 
             int boxHeight = step - addedBoxHeight - penaltyHeight;
@@ -343,9 +355,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
                 int p = stepPenalty;
                 if (p > -KnuthElement.INFINITE) {
                     p = Math.max(p, keep.getPenalty());
+                    breakClass = keep.getContext();
                 }
-                returnList.add(new BreakElement(stepPosition, penaltyHeight, p, keep.getContext(),
-                        context));
+                returnList.add(new BreakElement(stepPosition, penaltyHeight, p, breakClass, context));
             }
         }
 
@@ -693,6 +705,13 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
         body.reset();
     }
 
+    @Override
+    public int getBreakBefore() {
+        int breakBefore = BreakOpportunityHelper.getBreakBefore(this);
+        breakBefore = BreakUtil.compareBreakClasses(breakBefore, label.getBreakBefore());
+        breakBefore = BreakUtil.compareBreakClasses(breakBefore, body.getBreakBefore());
+        return breakBefore;
+    }
 
 }
 
index 3a433044f3ac7903b8f51d2b7da604b4542f633e..35acb0e49ee6351fade51a233ecccdff6d1ac1a3 100644 (file)
@@ -63,6 +63,9 @@
       documents. Example: the fix of marks layering will be such a case when it's done.
     -->
     <release version="FOP Trunk" date="TBD">
+      <action context="Layout" dev="VH" type="fix">
+        An IllegalArgumentException was thrown when break-before was used inside a list.
+      </action>
       <action context="Layout" dev="VH" type="fix">
         When restarting layout for the last page, discard glues and penalties at the beginning of 
         the restarted Knuth sequence.
diff --git a/test/layoutengine/standard-testcases/list-item-body_break-before.xml b/test/layoutengine/standard-testcases/list-item-body_break-before.xml
new file mode 100644 (file)
index 0000000..64e45ad
--- /dev/null
@@ -0,0 +1,96 @@
+<?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 basic breaks in list bodies.</p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master margin="5pt" page-width="11cm" page-height="3cm"
+          master-name="page">
+          <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:list-block provisional-distance-between-starts="20pt"
+            provisional-label-separation="5pt">
+            <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>
+                  This content starts on page 1 and overflows to page 2. This content starts on page 1 and
+                  overflows to page 2. This content starts on page 1 and overflows to page 2. This content
+                  starts on page 1 and overflows to page 2. This content starts on page 1 and overflows to
+                  page 2. This content starts on page 1 and overflows to page 2. This content starts on page 1
+                  and overflows to page 2.
+                  <fo:block break-before="page" />
+                  This content is on page 3.
+                  <fo:block break-before="page" />
+                  This content is on page 4.
+                </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>
+                  <fo:block break-before="page" />
+                  This content is on page 5.
+                </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 break-before="page">
+                  This content is on page 6.
+                </fo:block>
+              </fo:list-item-body>
+            </fo:list-item>
+            <fo:list-item break-before="page">
+              <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>
+                  This content is on page 7.
+                </fo:block>
+              </fo:list-item-body>
+            </fo:list-item>
+          </fo:list-block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="3" xpath="//lineArea[starts-with(., 'This content is on page 3.')]/ancestor::pageViewport/@nr" />
+    <eval expected="4" xpath="//lineArea[starts-with(., 'This content is on page 4.')]/ancestor::pageViewport/@nr" />
+    <eval expected="5" xpath="//lineArea[starts-with(., '(b)')]/ancestor::pageViewport/@nr" />
+    <eval expected="6" xpath="//lineArea[starts-with(., '(c)')]/ancestor::pageViewport/@nr" />
+    <eval expected="7" xpath="//lineArea[starts-with(., '(d)')]/ancestor::pageViewport/@nr" />
+  </checks>
+</testcase>
\ No newline at end of file
diff --git a/test/layoutengine/standard-testcases/list-item-body_break-before_multicolumn.xml b/test/layoutengine/standard-testcases/list-item-body_break-before_multicolumn.xml
new file mode 100644 (file)
index 0000000..a47daf1
--- /dev/null
@@ -0,0 +1,56 @@
+<?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 basic breaks in list bodies.</p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master margin="2cm" page-width="15.0cm" page-height="7.0cm"
+          master-name="page">
+          <fo:region-body 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:list-block provisional-distance-between-starts="20pt" provisional-label-separation="5pt">
+            <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>
+                  On first page, first column
+                  <fo:block id="block-3" break-before="page" />
+                  On second page, first column, NOT first page, first column NEITHER first page, second column.
+                </fo:block>
+              </fo:list-item-body>
+            </fo:list-item>
+          </fo:list-block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="1" xpath="//lineArea[starts-with(., 'On first page')]/ancestor::pageViewport/@nr" />
+    <eval expected="2" xpath="//lineArea[starts-with(., 'On second page')]/ancestor::pageViewport/@nr" />
+    <eval expected="1" xpath="count(//block[@prod-id='block-3']/ancestor::flow)" />
+  </checks>
+</testcase>
\ No newline at end of file
diff --git a/test/layoutengine/standard-testcases/page-sequence_last-page_space-before.xml b/test/layoutengine/standard-testcases/page-sequence_last-page_space-before.xml
new file mode 100644 (file)
index 0000000..81f7161
--- /dev/null
@@ -0,0 +1,59 @@
+<?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>When layout is re-started for the last page, the space-before on the first element to appear 
+      on that page must be discarded.</p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="page"
+          page-height="40pt" page-width="110pt" margin="5pt">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference master-reference="page" page-position="last"/>
+            <fo:conditional-page-master-reference master-reference="page" page-position="any"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block-container height="30pt">
+            <fo:block>Filler 1</fo:block>
+            <fo:block>Filler 2</fo:block>
+            <fo:block>Filler 3</fo:block>
+          </fo:block-container>
+          <fo:block-container height="20pt" keep-with-next.within-page="always">
+            <fo:block>Before line 1</fo:block>
+          </fo:block-container>
+          <fo:block>Before the page break</fo:block>
+          <fo:block space-before="10pt">After the page break</fo:block>
+          <fo:block>After line 1</fo:block>
+          <fo:block>After line 2</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="3" xpath="count(//pageViewport)"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-cell_break-before_multicolumn.xml b/test/layoutengine/standard-testcases/table-cell_break-before_multicolumn.xml
new file mode 100644 (file)
index 0000000..cb8398a
--- /dev/null
@@ -0,0 +1,68 @@
+<?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 basic breaks in table cells.</p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master margin="2cm" page-width="21.0cm" page-height="29.7cm"
+          master-name="A4-portrait">
+          <fo:region-body column-count="2" />
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="A4-portrait">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:table>
+            <fo:table-body>
+              <fo:table-row>
+                <fo:table-cell>
+                  <fo:block>Page 1, Column 1, Cell 1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell>
+                  <fo:block>Page 1, Column 1, Cell 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell>
+                  <fo:block>Page 1, Column 1, Cell 3</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell>
+                  <fo:block id="block-4">Page 2, Column 1, Cell 1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell>
+                  <fo:block break-before="page">Page 2, Column 1, Cell 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell>
+                  <fo:block>Page 2, Column 1, Cell 3</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="1" xpath="//lineArea[starts-with(., 'Page 1')]/ancestor::pageViewport/@nr" />
+    <eval expected="2" xpath="//lineArea[starts-with(., 'Page 2')]/ancestor::pageViewport/@nr" />
+    <eval expected="1" xpath="count(//block[@prod-id='block-4']/ancestor::flow)" />
+  </checks>
+</testcase>
\ No newline at end of file