]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugfixes:
authorVincent Hennebert <vhennebert@apache.org>
Mon, 30 Apr 2007 16:30:49 +0000 (16:30 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Mon, 30 Apr 2007 16:30:49 +0000 (16:30 +0000)
- NPE when break-before is set on the first row of a table with headers
- NPE when break-after is set on the last row of a table with headers or footers
- Invalid break class exception when break-after is set on the last block of a cell in the last row of a table
- double page break when break-before is set both on a table and its first row

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

src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableStepper.java
test/layoutengine/standard-testcases/table-cell_break-after_last-block.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-row_break-after_last-row-footer.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-row_break-after_last-row-header.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-row_break-before_first-row-header.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table_table-row_break-before.xml [new file with mode: 0644]

index 9794c731034f91607752cd7b9d08c58d93b47bf6..8abe1a3e8d450d4d4d1a609947f9b3586c4f5377 100644 (file)
@@ -179,12 +179,24 @@ public class TableContentLayoutManager implements PercentBaseContext {
         LinkedList returnList = getKnuthElementsForRowIterator(
                 bodyIter, context, alignment, TableRowIterator.BODY);
         if (headerAsFirst != null) {
-            returnList.add(0, headerAsFirst);
+            int insertionPoint = 0;
+            if (returnList.size() > 0 && ((ListElement)returnList.getFirst()).isForcedBreak()) {
+                insertionPoint++;
+            }
+            returnList.add(insertionPoint, headerAsFirst);
         } else if (headerAsSecondToLast != null) {
-            returnList.add(headerAsSecondToLast);
+            int insertionPoint = returnList.size();
+            if (returnList.size() > 0 && ((ListElement)returnList.getLast()).isForcedBreak()) {
+                insertionPoint--;
+            }
+            returnList.add(insertionPoint, headerAsSecondToLast);
         }
         if (footerAsLast != null) {
-            returnList.add(footerAsLast);
+            int insertionPoint = returnList.size();
+            if (returnList.size() > 0 && ((ListElement)returnList.getLast()).isForcedBreak()) {
+                insertionPoint--;
+            }
+            returnList.add(insertionPoint, footerAsLast);
         }
         return returnList;
     }
index 2d305d5fac11480717ca56d50d0f6a3cb6eef29c..155111ac468ccfc6bbb36c25d7b00607a91cd2e8 100644 (file)
@@ -29,6 +29,7 @@ import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthGlue;
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.ListElement;
+import org.apache.fop.layoutmgr.NonLeafPosition;
 import org.apache.fop.layoutmgr.PositionIterator;
 import org.apache.fop.layoutmgr.Position;
 import org.apache.fop.layoutmgr.RelSide;
@@ -248,7 +249,34 @@ public class TableLayoutManager extends BlockStackingLayoutManager
             log.debug("TableContentLM signals pending keep-with-previous");
             context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
         }
-        
+
+        // Check if the table's content starts/ends with a forced break
+        // TODO this is hacky and will need to be handled better eventually
+        if (contentKnuthElements.size() > 0) {
+            ListElement element = (ListElement)contentKnuthElements.getFirst();
+            if (element.isForcedBreak()) {
+                // The first row of the table(-body), or (the content of) one of its cells
+                // has a forced break-before
+                int breakBeforeTable = ((Table) fobj).getBreakBefore();
+                if (breakBeforeTable == EN_PAGE
+                        || breakBeforeTable == EN_COLUMN 
+                        || breakBeforeTable == EN_EVEN_PAGE 
+                        || breakBeforeTable == EN_ODD_PAGE) {
+                    // There is already a forced break before the table; remove this one
+                    // to prevent a double break
+                    contentKnuthElements.removeFirst();
+                } else {
+                    element.setPosition(new NonLeafPosition(this, null));
+                }
+            }
+            element = (ListElement)contentKnuthElements.getLast();
+            if (element.isForcedBreak()) {
+                // The last row of the table(-body), or (the content of) one of its cells
+                // has a forced break-after
+                element.setPosition(new NonLeafPosition(this, null));
+            }
+        }
+
         //Set index values on elements coming from the content LM
         Iterator iter = contentKnuthElements.iterator();
         while (iter.hasNext()) {
@@ -256,67 +284,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager
             notifyPos(el.getPosition());
         }
         log.debug(contentKnuthElements);
-        
-        if (contentKnuthElements.size() == 1
-                && ((ListElement)contentKnuthElements.getFirst()).isForcedBreak()) {
-            // a descendant of this block has break-before
-            if (returnList.size() == 0) {
-                // the first child (or its first child ...) has
-                // break-before;
-                // all this block, including space before, will be put in
-                // the
-                // following page
-                //FIX ME
-                //bSpaceBeforeServed = false;
-            }
-            contentList.addAll(contentKnuthElements);
-
-            // "wrap" the Position inside each element
-            // moving the elements from contentList to returnList
-            contentKnuthElements = new LinkedList();
-            wrapPositionElements(contentList, returnList);
-
-            return returnList;
-        } else {
-            /*
-            if (prevLM != null) {
-                // there is a block handled by prevLM
-                // before the one handled by curLM
-                if (mustKeepTogether() 
-                        || prevLM.mustKeepWithNext()
-                        || curLM.mustKeepWithPrevious()) {
-                    // add an infinite penalty to forbid a break between
-                    // blocks
-                    contentList.add(new KnuthPenalty(0,
-                            KnuthElement.INFINITE, false,
-                            new Position(this), false));
-                } else if (!((KnuthElement) contentList.getLast()).isGlue()) {
-                    // add a null penalty to allow a break between blocks
-                    contentList.add(new KnuthPenalty(0, 0, false,
-                            new Position(this), false));
-                } else {
-                    // the last element in contentList is a glue;
-                    // it is a feasible breakpoint, there is no need to add
-                    // a penalty
-                }
-            }*/
-            contentList.addAll(contentKnuthElements);
-            if (contentKnuthElements.size() > 0) {
-                if (((ListElement)contentKnuthElements.getLast()).isForcedBreak()) {
-                    // a descendant of this block has break-after
-                    if (false /*curLM.isFinished()*/) {
-                        // there is no other content in this block;
-                        // it's useless to add space after before a page break
-                        setFinished(true);
-                    }
-
-                    contentKnuthElements = new LinkedList();
-                    wrapPositionElements(contentList, returnList);
-
-                    return returnList;
-                }
-            }
-        }
+        contentList.addAll(contentKnuthElements);
         wrapPositionElements(contentList, returnList);
         if (getTable().isSeparateBorderModel()) {
             addKnuthElementsForBorderPaddingAfter(returnList, true);
index 2c676ae0be96e1c1ed5b0a536fa89fdf74b1f4d7..60ccf2b0a12e939b1cec05534f5504e9c0094daf 100644 (file)
@@ -299,6 +299,7 @@ public class TableStepper {
             addedBoxLen += boxLen;
 
             boolean forcedBreak = false;
+            int breakClass = -1;
             //Put all involved grid units into a list
             List gridUnitParts = new java.util.ArrayList(maxColumnCount);
             for (int i = 0; i < columnCount; i++) {
@@ -314,6 +315,7 @@ public class TableStepper {
                         gridUnitParts.add(new GridUnitPart(pgu, start[i], end[i]));
                         if (((KnuthElement)elementLists[i].get(end[i])).isForcedBreak()) {
                             forcedBreak = true;
+                            breakClass = ((KnuthPenalty)elementLists[i].get(end[i])).getBreakClass();
                         }
                     }
                     if (end[i] + 1 == elementLists[i].size()) {
@@ -410,7 +412,7 @@ public class TableStepper {
                 }
                 p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
             }
-            returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, -1, context));
+            returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context));
 
             if (log.isDebugEnabled()) {
                 log.debug("step=" + step + " (+" + increase + ")"
diff --git a/test/layoutengine/standard-testcases/table-cell_break-after_last-block.xml b/test/layoutengine/standard-testcases/table-cell_break-after_last-block.xml
new file mode 100644 (file)
index 0000000..d483218
--- /dev/null
@@ -0,0 +1,66 @@
+<?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 break-after on the last block child of a cell in the last row of a table
+      without headers nor footers works properly.
+    </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="10cm" page-width="15cm"
+          margin-top="1cm" margin-bottom="0" margin-left="1cm" margin-right="1cm">
+          <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>Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed" border-collapse="collapse" border="4pt solid black">
+            <fo:table-column number-columns-repeated="2" column-width="proportional-column-width(1)"/>
+            <fo:table-body>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block break-after="page">Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+          <fo:block>After the table</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <!-- Two pages -->
+    <eval expected="2" xpath="count(//pageViewport)"/>
+    <!-- Line "Before the table" + table on the first page -->
+    <eval expected="2" xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="Before the table" xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea/text[1]"/>
+    <!--  Line "After the table" on the second page -->
+    <eval expected="1" xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table" xpath="//pageViewport[@nr=2]//flow/block[1]/lineArea/text[1]"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-row_break-after_last-row-footer.xml b/test/layoutengine/standard-testcases/table-row_break-after_last-row-footer.xml
new file mode 100644 (file)
index 0000000..41e7369
--- /dev/null
@@ -0,0 +1,74 @@
+<?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 break-after on the last row of a table with footers works properly.
+    </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="10cm" page-width="15cm"
+          margin-top="1cm" margin-bottom="0" margin-left="1cm" margin-right="1cm">
+          <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>Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed" border-collapse="collapse" border="4pt solid black">
+            <fo:table-column number-columns-repeated="2" column-width="proportional-column-width(1)"/>
+            <fo:table-footer>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Footer 1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Footer 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-footer>
+            <fo:table-body>
+              <fo:table-row break-after="page">
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+          <fo:block>After the table</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <!-- Two pages -->
+    <eval expected="2" xpath="count(//pageViewport)"/>
+    <!-- Line "Before the table" + table on the first page -->
+    <eval expected="2" xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="Before the table" xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea/text[1]"/>
+    <!--  Line "After the table" on the second page -->
+    <eval expected="1" xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table" xpath="//pageViewport[@nr=2]//flow/block[1]/lineArea/text[1]"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-row_break-after_last-row-header.xml b/test/layoutengine/standard-testcases/table-row_break-after_last-row-header.xml
new file mode 100644 (file)
index 0000000..b23ec72
--- /dev/null
@@ -0,0 +1,74 @@
+<?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 break-after on the last row of a table with headers works properly.
+    </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="10cm" page-width="15cm"
+          margin-top="1cm" margin-bottom="0" margin-left="1cm" margin-right="1cm">
+          <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>Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed" border-collapse="collapse" border="4pt solid black">
+            <fo:table-column number-columns-repeated="2" column-width="proportional-column-width(1)"/>
+            <fo:table-header>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Header 1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Header 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-header>
+            <fo:table-body>
+              <fo:table-row break-after="page">
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+          <fo:block>After the table</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <!-- Two pages -->
+    <eval expected="2" xpath="count(//pageViewport)"/>
+    <!-- Line "Before the table" + table on the first page -->
+    <eval expected="2" xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="Before the table" xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea/text[1]"/>
+    <!--  Line "After the table" on the second page -->
+    <eval expected="1" xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table" xpath="//pageViewport[@nr=2]//flow/block[1]/lineArea/text[1]"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-row_break-before_first-row-header.xml b/test/layoutengine/standard-testcases/table-row_break-before_first-row-header.xml
new file mode 100644 (file)
index 0000000..f05f009
--- /dev/null
@@ -0,0 +1,74 @@
+<?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 break-before on the first row of a table with headers works properly.
+    </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="10cm" page-width="15cm"
+          margin-top="1cm" margin-bottom="0" margin-left="1cm" margin-right="1cm">
+          <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>Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed" border-collapse="collapse" border="4pt solid black" table-omit-header-at-break="true">
+            <fo:table-column number-columns-repeated="2" column-width="proportional-column-width(1)"/>
+            <fo:table-header>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Header 1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Header 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-header>
+            <fo:table-body>
+              <fo:table-row break-before="page">
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+          <fo:block>After the table</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <!-- Two pages -->
+    <eval expected="2" xpath="count(//pageViewport)"/>
+    <!-- Only one line on the first page -->
+    <eval expected="1" xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="Before the table" xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea/text[1]"/>
+    <!--  Table plus line "After the table" on the second page -->
+    <eval expected="2" xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table" xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea/text[1]"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table_table-row_break-before.xml b/test/layoutengine/standard-testcases/table_table-row_break-before.xml
new file mode 100644 (file)
index 0000000..e77ec4f
--- /dev/null
@@ -0,0 +1,76 @@
+<?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 there is only one page break when break-before is specified both on a
+      table and its first row.
+    </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="10cm" page-width="15cm"
+          margin-top="1cm" margin-bottom="0" margin-left="1cm" margin-right="1cm">
+          <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>Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed" border-collapse="collapse" border="4pt solid black"
+            break-before="page">
+            <fo:table-column number-columns-repeated="2" column-width="proportional-column-width(1)"/>
+            <fo:table-header>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Header 1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Header 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-header>
+            <fo:table-body>
+              <fo:table-row break-before="page">
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.1</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid black">
+                  <fo:block>Cell 1.2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+          <fo:block>After the table</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <!-- Two pages -->
+    <eval expected="2" xpath="count(//pageViewport)"/>
+    <!-- Only one line on the first page -->
+    <eval expected="1" xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="Before the table" xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea/text[1]"/>
+    <!--  Table plus line "After the table" on the second page -->
+    <eval expected="2" xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table" xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea/text[1]"/>
+  </checks>
+</testcase>