]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
- added full support for keep-with-previous on table-row and in table-cell
authorVincent Hennebert <vhennebert@apache.org>
Mon, 25 Feb 2008 11:30:43 +0000 (11:30 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Mon, 25 Feb 2008 11:30:43 +0000 (11:30 +0000)
- added more testcases for keeps in tables
- assign the right table-row element to grid units that are not on the first row spanned
- slightly re-worked the RowGroupBuilder interface to make it more SAX-like

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

29 files changed:
src/java/org/apache/fop/fo/flow/table/EffRow.java
src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
src/java/org/apache/fop/fo/flow/table/GridUnit.java
src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
src/java/org/apache/fop/fo/flow/table/Table.java
src/java/org/apache/fop/fo/flow/table/TableBody.java
src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
src/java/org/apache/fop/layoutmgr/LayoutContext.java
src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
src/java/org/apache/fop/layoutmgr/table/CellPart.java
src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
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
status.xml
test/layoutengine/standard-testcases/table-cell_block_keep-with-next.xml
test/layoutengine/standard-testcases/table-cell_keep-together.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-cell_keep-with-next.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-cell_keep-with-previous.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-row_keep-together_2.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-row_keep-with-next.xml
test/layoutengine/standard-testcases/table-row_keep-with-next_3.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table-row_keep-with-previous.xml
test/layoutengine/standard-testcases/table-row_keep-with-previous_2.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/table_break-before_break-after.xml
test/layoutengine/standard-testcases/table_keep-together_2.xml [new file with mode: 0644]

index 7989f3d9d30005dc7a8cde9b450c87a4c8af116a..0b00b9620e5a97c8c0b70c2ec1cd993933d778e7 100644 (file)
@@ -162,10 +162,65 @@ public class EffRow {
         }
     }
 
+    /**
+     * Returns true if the enclosing (if any) fo:table-row element of this row, or if any
+     * of the cells starting on this row, have keep-with-previous set.
+     * 
+     * @return true if this row must be kept with the previous content
+     */
+    public boolean mustKeepWithPrevious() {
+        boolean keepWithPrevious = false;
+        TableRow row = getTableRow();
+        if (row != null) {
+            keepWithPrevious = row.mustKeepWithPrevious();
+        }
+        for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
+            GridUnit gu = (GridUnit) iter.next();
+            if (gu.isPrimary()) {
+                keepWithPrevious |= gu.getPrimary().mustKeepWithPrevious();
+            }
+        }
+        return keepWithPrevious;
+    }
+
+    /**
+     * Returns true if the enclosing (if any) fo:table-row element of this row, or if any
+     * of the cells ending on this row, have keep-with-next set.
+     * 
+     * @return true if this row must be kept with the next content
+     */
+    public boolean mustKeepWithNext() {
+        boolean keepWithNext = false;
+        TableRow row = getTableRow();
+        if (row != null) {
+            keepWithNext = row.mustKeepWithNext();
+        }
+        for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
+            GridUnit gu = (GridUnit) iter.next();
+            if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) {
+                keepWithNext |= gu.getPrimary().mustKeepWithNext();
+            }
+        }
+        return keepWithNext;
+    }
+
+    /**
+     * Returns true if this row is enclosed by an fo:table-row element that has
+     * keep-together set.
+     * 
+     * @return true if this row must be kept together
+     */
+    public boolean mustKeepTogether() {
+        TableRow row = getTableRow();
+        return row != null && row.mustKeepTogether();
+    }
 
     /**
      * Returns the break class for this row. This is a combination of break-before set on
      * the first children of any cells starting on this row.
+     * <p><strong>Note:</strong> this method doesn't take into account break-before set on
+     * the enclosing fo:table-row element, if any, as it must be ignored if the row
+     * belongs to a group of spanned rows (see XSL-FO 1.1, 7.20.2).
      * <p><strong>Note:</strong> this works only after getNextKuthElements on the
      * corresponding TableCellLM have been called!</p>
      * 
@@ -187,6 +242,9 @@ public class EffRow {
     /**
      * Returns the break class for this row. This is a combination of break-after set on
      * the last children of any cells ending on this row.
+     * <p><strong>Note:</strong> this method doesn't take into account break-after set on
+     * the enclosing fo:table-row element, if any, as it must be ignored if the row
+     * belongs to a group of spanned rows (see XSL-FO 1.1, 7.20.1).
      * <p><strong>Note:</strong> this works only after getNextKuthElements on the
      * corresponding TableCellLM have been called!</p>
      * 
index 583abcaa3a9b17da8f911797e17d726f8a6e041d..201029ff1082764affba5d996c7cf836b8b0a89d 100644 (file)
@@ -33,7 +33,8 @@ public class EmptyGridUnit extends GridUnit {
      * @param colIndex column index, 0-based
      */
     EmptyGridUnit(Table table, TableRow row, int colIndex) {
-        super(table, row, 0, 0);
+        super(table, 0, 0);
+        setRow(row);
     }
 
     /** {@inheritDoc} */
index 62cf3e26de203f6c5bdfa9e21312c7be1374256d..28a30c6f74a068a5812268e5737180d6cb01f949 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.fop.fo.flow.table;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 
@@ -80,14 +81,14 @@ class FixedColRowGroupBuilder extends RowGroupBuilder {
             rows.add(effRow);
         }
         int columnIndex = cell.getColumnNumber() - 1;
-        PrimaryGridUnit pgu = new PrimaryGridUnit(cell, currentTableRow, columnIndex);
+        PrimaryGridUnit pgu = new PrimaryGridUnit(cell, columnIndex);
         List row = (List) rows.get(currentRowIndex);
         row.set(columnIndex, pgu);
         // TODO
         GridUnit[] cellRow = new GridUnit[cell.getNumberColumnsSpanned()];
         cellRow[0] = pgu;
         for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
-            GridUnit gu = new GridUnit(pgu, currentTableRow, j, 0);
+            GridUnit gu = new GridUnit(pgu, j, 0);
             row.set(columnIndex + j, gu);
             cellRow[j] = gu;
         }
@@ -96,7 +97,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder {
             row = (List) rows.get(currentRowIndex + i);
             cellRow = new GridUnit[cell.getNumberColumnsSpanned()];
             for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) {
-                GridUnit gu = new GridUnit(pgu, currentTableRow, j, i);
+                GridUnit gu = new GridUnit(pgu, j, i);
                 row.set(columnIndex + j, gu);
                 cellRow[j] = gu;
             }
@@ -111,21 +112,30 @@ class FixedColRowGroupBuilder extends RowGroupBuilder {
     }
 
     /** {@inheritDoc} */
-    void startRow(TableRow tableRow) {
+    void startTableRow(TableRow tableRow) {
         currentTableRow = tableRow;
     }
 
     /** {@inheritDoc} */
-    void endRow(TableRow row) {
-        if (currentRowIndex > 0 && row.getBreakBefore() != Constants.EN_AUTO) {
-            row.attributeWarning("break-before ignored because of row spanning "
+    void endTableRow() {
+        assert currentTableRow != null;
+        if (currentRowIndex > 0 && currentTableRow.getBreakBefore() != Constants.EN_AUTO) {
+            currentTableRow.attributeWarning("break-before ignored because of row spanning "
                     + "in progress (See XSL 1.1, 7.20.2)");
         }
-        if (currentRowIndex < rows.size() - 1 && row.getBreakAfter() != Constants.EN_AUTO) {
-            row.attributeWarning("break-after ignored because of row spanning "
+        if (currentRowIndex < rows.size() - 1
+                && currentTableRow.getBreakAfter() != Constants.EN_AUTO) {
+            currentTableRow.attributeWarning("break-after ignored because of row spanning "
                     + "in progress (See XSL 1.1, 7.20.1)");
         }
-        handleRowEnd(row);
+        for (Iterator iter = ((List) rows.get(currentRowIndex)).iterator(); iter.hasNext();) {
+            GridUnit gu = (GridUnit) iter.next();
+            // The row hasn't been filled with empty grid units yet
+            if (gu != null) {
+                gu.setRow(currentTableRow);
+            }
+        }
+        handleRowEnd(currentTableRow);
     }
 
     /** {@inheritDoc} */
@@ -174,7 +184,7 @@ class FixedColRowGroupBuilder extends RowGroupBuilder {
     }
 
     /** {@inheritDoc} */
-    void endTable(TableBody lastTablePart) {
+    void endTable() {
         borderResolver.endTable();
     }
 }
index edf0c99ea30cd92880fb44bc0c44ffec3bfb2d2b..23d1cc001273be9026b6a2a36aaa2c6667890732 100644 (file)
@@ -76,12 +76,11 @@ public class GridUnit {
      * Creates a new grid unit.
      * 
      * @param table the containing table
-     * @param row the table-row element this grid unit belongs to (if any)
      * @param colSpanIndex index of this grid unit in the span, in column direction
      * @param rowSpanIndex index of this grid unit in the span, in row direction
      */
-    protected GridUnit(Table table, TableRow row, int colSpanIndex, int rowSpanIndex) {
-        this(row, colSpanIndex, rowSpanIndex);
+    protected GridUnit(Table table, int colSpanIndex, int rowSpanIndex) {
+        this(colSpanIndex, rowSpanIndex);
         setBorders(table);
     }
 
@@ -89,12 +88,11 @@ public class GridUnit {
      * Creates a new grid unit.
      * 
      * @param cell table cell which occupies this grid unit
-     * @param row the table-row element this grid unit belongs to (if any)
      * @param colSpanIndex index of this grid unit in the span, in column direction
      * @param rowSpanIndex index of this grid unit in the span, in row direction
      */
-    protected GridUnit(TableCell cell, TableRow row, int colSpanIndex, int rowSpanIndex) {
-        this(row, colSpanIndex, rowSpanIndex);
+    protected GridUnit(TableCell cell, int colSpanIndex, int rowSpanIndex) {
+        this(colSpanIndex, rowSpanIndex);
         this.cell = cell;
         setBorders(cell.getTable());
     }
@@ -103,17 +101,15 @@ public class GridUnit {
      * Creates a new grid unit.
      * 
      * @param primary the before-start grid unit of the cell containing this grid unit
-     * @param row the table-row element this grid unit belongs to (if any)
      * @param colSpanIndex index of this grid unit in the span, in column direction
      * @param rowSpanIndex index of this grid unit in the span, in row direction
      */
-    GridUnit(PrimaryGridUnit primary, TableRow row, int colSpanIndex, int rowSpanIndex) {
-        this(primary.getCell(), row, colSpanIndex, rowSpanIndex);
+    GridUnit(PrimaryGridUnit primary, int colSpanIndex, int rowSpanIndex) {
+        this(primary.getCell(), colSpanIndex, rowSpanIndex);
         this.primary = primary;
     }
 
-    private GridUnit(TableRow row, int colSpanIndex, int rowSpanIndex) {
-        this.row = row;
+    private GridUnit(int colSpanIndex, int rowSpanIndex) {
         this.colSpanIndex = colSpanIndex;
         this.rowSpanIndex = rowSpanIndex;
     }
@@ -165,6 +161,10 @@ public class GridUnit {
         return row;
     }
 
+    void setRow(TableRow row) {
+        this.row = row;
+    }
+
     public TableBody getBody() {
         FONode node = getCell();
         while (node != null && !(node instanceof TableBody)) {
index c95f3f8c3982c2d6fdc3ae386c08e7bc5ac2068b..1a47a7dcfe9a60f14a0c80ee5686f4c1baf41431 100644 (file)
@@ -52,6 +52,8 @@ public class PrimaryGridUnit extends GridUnit {
     private boolean isSeparateBorderModel;
     private int halfBorderSeparationBPD;
 
+    private boolean keepWithPrevious;
+    private boolean keepWithNext;
     private int breakBefore = Constants.EN_AUTO;
     private int breakAfter = Constants.EN_AUTO;
 
@@ -59,11 +61,10 @@ public class PrimaryGridUnit extends GridUnit {
      * Creates a new primary grid unit.
      *
      * @param cell table cell which occupies this grid unit
-     * @param row the table-row element this grid unit belongs to (if any)
      * @param colIndex index of the column this grid unit belongs to, zero-based
      */
-    PrimaryGridUnit(TableCell cell, TableRow row, int colIndex) {
-        super(cell, row, 0, 0);
+    PrimaryGridUnit(TableCell cell, int colIndex) {
+        super(cell, 0, 0);
         this.colIndex = colIndex;
         this.isSeparateBorderModel = cell.getTable().isSeparateBorderModel(); // TODO
         this.halfBorderSeparationBPD = cell.getTable().getBorderSeparation().getBPD().getLength()
@@ -324,6 +325,40 @@ public class PrimaryGridUnit extends GridUnit {
         cellLM = new TableCellLayoutManager(cell, this);
     }
 
+    /**
+     * Returns true if the first child block (or its descendants) of this cell has
+     * keep-with-previous.
+     * 
+     * @return the value of keep-with-previous
+     */
+    public boolean mustKeepWithPrevious() {
+        return keepWithPrevious;
+    }
+
+    /**
+     * Don't use, reserved for TableCellLM. TODO
+     */
+    public void setKeepWithPrevious() {
+        this.keepWithPrevious = true;
+    }
+
+    /**
+     * Returns true if the last child block (or its descendants) of this cell has
+     * keep-with-next.
+     * 
+     * @return the value of keep-with-next
+     */
+    public boolean mustKeepWithNext() {
+        return keepWithNext;
+    }
+
+    /**
+     * Don't use, reserved for TableCellLM. TODO
+     */
+    public void setKeepWithNext() {
+        this.keepWithNext = true;
+    }
+
     /**
      * Returns the class of the before break for the first child element of this cell.
      * 
index 3f7549787682849a9ff39db4eb2b957d2d4517a1..c954be7111ad116eab02dfb4a86cc84a6267d524 100644 (file)
@@ -53,16 +53,14 @@ abstract class RowGroupBuilder {
      * 
      * @param tableRow the row being started
      */
-    abstract void startRow(TableRow tableRow);
+    abstract void startTableRow(TableRow tableRow);
 
     /**
      * Receives notification of the end of the current row. If the current row finishes
      * the row group, the {@link TableBody#addRowGroup(List)} method of the parent table
      * part will be called.
-     * 
-     * @param row the row being finished
      */
-    abstract void endRow(TableRow row);
+    abstract void endTableRow();
 
     /**
      * Receives notification of the end of the current row, when the source contains no
@@ -70,7 +68,7 @@ abstract class RowGroupBuilder {
      * {@link TableBody#addRowGroup(List)} method of the given table part will be called.
      * 
      * <p>If the source does contain explicit fo:table-row elements, then the
-     * {@link #endRow(TableRow)} method will be called instead.</p>
+     * {@link #endTableRow()} method will be called instead.</p>
      * 
      * @param part the part containing the current row
      */
@@ -95,8 +93,7 @@ abstract class RowGroupBuilder {
     /**
      * Receives notification of the end of the table.
      * 
-     * @param lastTablePart the last part of the table
      * @throws ValidationException if a row-spanning cell overflows one of the table's parts
      */
-    abstract void endTable(TableBody lastTablePart) throws ValidationException;
+    abstract void endTable() throws ValidationException;
 }
index 2b6570dcca733ee6c49596780282e6ead2a04a13..7d661143517dccc86f7a82123e5094c03fe88584 100644 (file)
@@ -126,8 +126,8 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
         orphanContentLimit = pList.get(PR_X_ORPHAN_CONTENT_LIMIT).getLength();
 
         if (!blockProgressionDimension.getOptimum(null).isAuto()) {
-            attributeWarning("only a value of \"auto\" for block-progression-dimension has a well-specified"
-                    + " behavior on fo:table. Falling back to \"auto\"");
+            attributeWarning("only a value of \"auto\" for block-progression-dimension has a"
+                    + " well-specified behavior on fo:table. Falling back to \"auto\"");
             // Anyway, the bpd of a table is not used by the layout code
         }
         if (tableLayout == EN_AUTO) {
@@ -226,11 +226,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
                        + ",table-body+)");
         }
         if (!inMarker()) {
-            if (tableFooter != null) {
-                rowGroupBuilder.endTable(tableFooter);
-            } else {
-                rowGroupBuilder.endTable((TableBody) getChildNodes().lastNode());
-            }
+            rowGroupBuilder.endTable();
             /* clean up */
             for (int i = columns.size(); --i >= 0;) {
                 TableColumn col = (TableColumn) columns.get(i);
@@ -290,6 +286,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
         }
     }
 
+    /** {@inheritDoc} */
     protected void setCollapsedBorders() {
         createBorder(CommonBorderPaddingBackground.START);
         createBorder(CommonBorderPaddingBackground.END);
index c3642c2606f8a5158c52706643f3976d472e7338..de7bfda841169bba35e8c40dc69545b77d0b180e 100644 (file)
@@ -140,7 +140,7 @@ public class TableBody extends TableCellContainer {
         if (!inMarker()) {
             RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
             if (tableRowsFound) {
-                rowGroupBuilder.endRow(lastRow);
+                rowGroupBuilder.endTableRow();
             } else if (!lastCellEndsRow) {
                 rowGroupBuilder.endRow(this);
             }
@@ -167,9 +167,9 @@ public class TableBody extends TableCellContainer {
             } else if (localName.equals("table-row")) {
                 tableRowsFound = true;
                 if (tableCellsFound) {
-                    invalidChildError(loc, nsURI, localName, "Either fo:table-rows" +
-                      " or fo:table-cells may be children of an " + getName() +
-                      " but not both");
+                    invalidChildError(loc, nsURI, localName, "Either fo:table-rows"
+                            + " or fo:table-cells may be children of an " + getName()
+                            + " but not both");
                 }
             } else if (localName.equals("table-cell")) {
                 tableCellsFound = true;
@@ -198,11 +198,11 @@ public class TableBody extends TableCellContainer {
                     getTable().getRowGroupBuilder().startTablePart(this);
                 } else {
                     columnNumberManager.prepareForNextRow(pendingSpans);
-                    getTable().getRowGroupBuilder().endRow(lastRow);
+                    getTable().getRowGroupBuilder().endTableRow();
                 }
                 rowsStarted = true;
                 lastRow = (TableRow) child;
-                getTable().getRowGroupBuilder().startRow(lastRow);
+                getTable().getRowGroupBuilder().startTableRow(lastRow);
                 break;
             case FO_TABLE_CELL:
                 if (!rowsStarted) {
index 801153ce9e667ac8d8e8b3fed1a1cae7a8ceb9bd..d59870f0a192585d9422b1f1328d3a232473a915 100644 (file)
@@ -64,19 +64,19 @@ class VariableColRowGroupBuilder extends RowGroupBuilder {
     }
 
     /** {@inheritDoc} */
-    void startRow(final TableRow tableRow) {
+    void startTableRow(final TableRow tableRow) {
         events.add(new Event() {
             public void play(RowGroupBuilder rowGroupBuilder) {
-                rowGroupBuilder.startRow(tableRow);
+                rowGroupBuilder.startTableRow(tableRow);
             }
         });
     }
 
     /** {@inheritDoc} */
-    void endRow(final TableRow row) {
+    void endTableRow() {
         events.add(new Event() {
             public void play(RowGroupBuilder rowGroupBuilder) {
-                rowGroupBuilder.endRow(row);
+                rowGroupBuilder.endTableRow();
             }
         });
     }
@@ -110,11 +110,11 @@ class VariableColRowGroupBuilder extends RowGroupBuilder {
     }
 
     /** {@inheritDoc} */
-    void endTable(final TableBody lastTablePart) throws ValidationException {
+    void endTable() throws ValidationException {
         RowGroupBuilder delegate = new FixedColRowGroupBuilder(table);
         for (Iterator eventIter = events.iterator(); eventIter.hasNext();) {
             ((Event) eventIter.next()).play(delegate);
         }
-        delegate.endTable(lastTablePart);
+        delegate.endTable();
     }
 }
index beda11fe82b5a76de88f94cfe851094e91cd1833..9eb38600b6309b3eda755971340f47c8e61ab39a 100644 (file)
@@ -133,6 +133,10 @@ public class LayoutContext {
     /** Amount of space to reserve at the end of each line */
     private int lineEndBorderAndPaddingWidth = 0;
 
+    private int breakBefore;
+
+    private int breakAfter;
+
     /**
      * Copy constructor for creating child layout contexts.
      * @param parentLC the parent layout context to copy from
@@ -482,7 +486,54 @@ public class LayoutContext {
     public void setSpaceAfter(int spaceAfter) {
         this.spaceAfter = spaceAfter;
     }
-    
+
+    /**
+     * Returns the value of the break before the element whose
+     * {@link LayoutManager#getNextKnuthElements(LayoutContext, int)} method has just been
+     * called.
+     * 
+     * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN},
+     * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, or
+     * {@link Constants#EN_ODD_PAGE}
+     */
+    public int getBreakBefore() {
+        return breakBefore;
+    }
+
+    /**
+     * Sets the value of the break before the current element.
+     * 
+     * @param breakBefore the value of the break-before
+     * @see #getBreakBefore()
+     */
+    public void setBreakBefore(int breakBefore) {
+        this.breakBefore = breakBefore;
+    }
+
+    /**
+     * Returns the value of the break after the element whose
+     * {@link LayoutManager#getNextKnuthElements(LayoutContext, int)} method has just been
+     * called.
+     * 
+     * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN},
+     * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, or
+     * {@link Constants#EN_ODD_PAGE}
+     */
+    public int getBreakAfter() {
+        return breakAfter;
+    }
+
+
+    /**
+     * Sets the value of the break after the current element.
+     * 
+     * @param breakAfter the value of the break-after
+     * @see #getBreakAfter()
+     */
+    public void setBreakAfter(int breakAfter) {
+        this.breakAfter = breakAfter;
+    }
+
     /** {@inheritDoc} */
     public String toString() {
         return "Layout Context:" +
@@ -499,7 +550,9 @@ public class LayoutContext {
         "\nIs Last Area: \t" + isLastArea() +
         "\nTry Hyphenate: \t" + tryHyphenate() + 
         "\nKeeps: \t[" + (isKeepWithNextPending() ? "keep-with-next" : "") + "][" 
-            + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending";
+            + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending" +
+        "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" 
+        + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
     }
 
 }
index c4bff5112d83fa2fc46f970b14592f4d57fff111..c1e4ae61920f051f79193a1fba185f7ee34306af 100644 (file)
@@ -27,7 +27,6 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.flow.table.ConditionalBorder;
 import org.apache.fop.fo.flow.table.EffRow;
-import org.apache.fop.fo.flow.table.GridUnit;
 import org.apache.fop.fo.flow.table.PrimaryGridUnit;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.layoutmgr.ElementListUtils;
@@ -158,10 +157,6 @@ class ActiveCell {
                 makeBoxForWholeRow = true;
             }
         }
-        if (pgu.isLastGridUnitRowSpan() && pgu.getRow() != null) {
-            makeBoxForWholeRow |= pgu.getRow().mustKeepTogether();
-            makeBoxForWholeRow |= tableLM.getTable().mustKeepTogether();
-        }
         if (makeBoxForWholeRow) {
             elementList = new java.util.ArrayList(1);
             int height = row.getHeight().opt;
@@ -427,12 +422,15 @@ class ActiveCell {
      */
     CellPart createCellPart() {
         if (nextStep.end + 1 == elementList.size()) {
-            if (pgu.getFlag(GridUnit.KEEP_WITH_NEXT_PENDING)) {
-                keepWithNextSignal = true;
-            }
-            if (pgu.getRow() != null && pgu.getRow().mustKeepWithNext()) {
-                keepWithNextSignal = true;
-            }
+            keepWithNextSignal = pgu.mustKeepWithNext();
+            // TODO if keep-with-next is set on the row, must every cell of the row
+            // contribute some content from children blocks?
+            // see http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200802.mbox/
+            // %3c47BDA379.4050606@anyware-tech.com%3e
+            // Assuming no, but if yes the following code should enable this behaviour
+//            if (pgu.getRow() != null && pgu.getRow().mustKeepWithNext()) {
+//                keepWithNextSignal = true;
+//            }
         }
         int bpBeforeFirst;
         if (nextStep.start == 0) {
index 2adb543a95bcfa1a460ef3b6008ea3bce490ca12..560b703443d234fbf3edfb1055c63c62496283bc 100644 (file)
@@ -19,7 +19,6 @@
 
 package org.apache.fop.layoutmgr.table;
 
-import org.apache.fop.fo.flow.table.GridUnit;
 import org.apache.fop.fo.flow.table.PrimaryGridUnit;
 
 /**
@@ -126,9 +125,4 @@ class CellPart {
         return sb.toString();
     }
 
-    boolean mustKeepWithPrevious() {
-        return pgu.getFlag(GridUnit.KEEP_WITH_PREVIOUS_PENDING)
-                || (pgu.getRow() != null && pgu.getRow().mustKeepWithPrevious());
-    }
-
 }
index 0127f4d81e54807b171a7db36ff1bbe9ed51fe85..c2e26e18dbdd1fec3adae68de7a1cdf30265a5a1 100644 (file)
@@ -32,19 +32,15 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit;
 import org.apache.fop.fo.flow.table.TableRow;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fo.properties.LengthRangeProperty;
-import org.apache.fop.layoutmgr.BreakElement;
 import org.apache.fop.layoutmgr.ElementListObserver;
-import org.apache.fop.layoutmgr.KnuthElement;
-import org.apache.fop.layoutmgr.KnuthPenalty;
 import org.apache.fop.layoutmgr.LayoutContext;
-import org.apache.fop.layoutmgr.ListElement;
 import org.apache.fop.layoutmgr.MinOptMaxUtil;
 import org.apache.fop.traits.MinOptMax;
 import org.apache.fop.util.BreakUtil;
 
 class RowGroupLayoutManager {
 
-    private static Log log = LogFactory.getLog(TableContentLayoutManager.class);
+    private static Log log = LogFactory.getLog(RowGroupLayoutManager.class);
 
     private EffRow[] rowGroup;
 
@@ -59,71 +55,30 @@ class RowGroupLayoutManager {
         this.tableStepper = tableStepper;
     }
 
-    /**
-     * 
-     * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN},
-     * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, or
-     * {@link Constants#EN_ODD_PAGE}
-     */
-    int getBreakBefore() {
-        TableRow rowFO = rowGroup[0].getTableRow();
-        int breakBefore;
-        if (rowFO == null) {
-            breakBefore = Constants.EN_AUTO;
-        } else {
-            breakBefore = rowFO.getBreakBefore(); 
-        }
-        return BreakUtil.compareBreakClasses(breakBefore, rowGroup[0].getBreakBefore());
-    }
-
-    /**
-     * 
-     * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN},
-     * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, or
-     * {@link Constants#EN_ODD_PAGE}
-     */
-    int getBreakAfter() {
-        TableRow rowFO = rowGroup[rowGroup.length - 1].getTableRow();
-        int breakAfter;
-        if (rowFO == null) {
-            breakAfter = Constants.EN_AUTO;
-        } else {
-            breakAfter = rowFO.getBreakAfter(); 
-        }
-        return BreakUtil.compareBreakClasses(breakAfter,
-                rowGroup[rowGroup.length - 1].getBreakAfter());
-    }
-
     public LinkedList getNextKnuthElements(LayoutContext context, int alignment, int bodyType) {
         LinkedList returnList = new LinkedList();
-
-        //Reset keep-with-next when remaining inside the table.
-        //The context flag is only used to propagate keep-with-next to the outside.
-        //The clearing is ok here because createElementsForRowGroup already handles
-        //the keep when inside a table.
-        context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING, false);
-
-        //Element list creation
         createElementsForRowGroup(context, alignment, bodyType, returnList);
 
-        //Handle keeps
-        if (context.isKeepWithNextPending()) {
-            log.debug("child LM (row group) signals pending keep-with-next");
+        context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING,
+                rowGroup[0].mustKeepWithPrevious());
+        context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING,
+                rowGroup[rowGroup.length - 1].mustKeepWithNext());
+
+        int breakBefore = Constants.EN_AUTO;
+        TableRow firstRow = rowGroup[0].getTableRow();
+        if (firstRow != null) {
+            breakBefore = firstRow.getBreakBefore(); 
         }
-        if (context.isKeepWithPreviousPending()) {
-            log.debug("child LM (row group) signals pending keep-with-previous");
-            if (returnList.size() > 0) {
-                //Modify last penalty
-                ListElement last = (ListElement)returnList.getLast();
-                if (last.isPenalty()) {
-                    BreakElement breakPoss = (BreakElement)last;
-                    //Only honor keep if there's no forced break
-                    if (!breakPoss.isForcedBreak()) {
-                        breakPoss.setPenaltyValue(KnuthPenalty.INFINITE);
-                    }
-                }
-            }
+        context.setBreakBefore(BreakUtil.compareBreakClasses(breakBefore,
+                rowGroup[0].getBreakBefore()));
+
+        int breakAfter = Constants.EN_AUTO;
+        TableRow lastRow = rowGroup[rowGroup.length - 1].getTableRow();
+        if (lastRow != null) {
+            breakAfter = lastRow.getBreakAfter(); 
         }
+        context.setBreakAfter(BreakUtil.compareBreakClasses(breakAfter,
+                rowGroup[rowGroup.length - 1].getBreakAfter()));
 
         return returnList;
     }
@@ -162,7 +117,8 @@ class RowGroupLayoutManager {
                     PrimaryGridUnit primary = gu.getPrimary();
                     
                     if (gu.isPrimary()) {
-                        primary.createCellLM(); // TODO a new LM must be created for every new static-content
+                        // TODO a new LM must be created for every new static-content
+                        primary.createCellLM();
                         primary.getCellLM().setParent(tableLM);
                      
                         //Determine the table-row if any
@@ -198,24 +154,7 @@ class RowGroupLayoutManager {
                         LinkedList elems = primary.getCellLM().getNextKnuthElements(
                                                 childLC, alignment);
                         ElementListObserver.observe(elems, "table-cell", primary.getCell().getId());
-
-                        if ((elems.size() > 0) 
-                                && ((KnuthElement)elems.getLast()).isForcedBreak()) {
-                            // a descendant of this block has break-after
-                            log.debug("Descendant of table-cell signals break: " 
-                                    + primary.getCellLM().isFinished());
-                        }
-                        
                         primary.setElements(elems);
-                        
-                        if (childLC.isKeepWithNextPending()) {
-                            log.debug("child LM signals pending keep-with-next");
-                            primary.setFlag(GridUnit.KEEP_WITH_NEXT_PENDING, true);
-                        }
-                        if (childLC.isKeepWithPreviousPending()) {
-                            log.debug("child LM signals pending keep-with-previous");
-                            primary.setFlag(GridUnit.KEEP_WITH_PREVIOUS_PENDING, true);
-                        }
                     }
 
                     //Calculate height of row, see CSS21, 17.5.3 Table height algorithms
@@ -284,11 +223,8 @@ class RowGroupLayoutManager {
                 log.debug("  height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]);
             }
         }
-        LinkedList returnedList = tableStepper.getCombinedKnuthElementsForRowGroup(context,
+        LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context,
                 rowGroup, bodyType);
-        if (returnedList != null) {
-            returnList.addAll(returnedList);
-        }
-        
+        returnList.addAll(elements);
     }
 }
index fbc1187236db8e4273dbbf2671c2055bebcaa1da..289785d685fadae8f1519421369feb7c5922ff0f 100644 (file)
@@ -173,7 +173,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
                 log.debug("child LM signals pending keep with next");
             }
             if (contentList.size() == 0 && childLC.isKeepWithPreviousPending()) {
-                context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+                primaryGridUnit.setKeepWithPrevious();
                 childLC.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, false);
             }
 
@@ -233,6 +233,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
             }
             prevLM = curLM;
         }
+        if (context.isKeepWithNextPending()) {
+            primaryGridUnit.setKeepWithNext();
+        }
 
         returnedList = new LinkedList();
         if (contentList.size() > 0) {
index c09b9b07677e252c1a3ab77cc8f4a1cc58371ddd..b9a118e28a011992c96fddfcd0643ac1da9824a2 100644 (file)
@@ -40,7 +40,7 @@ import org.apache.fop.fo.flow.table.TableRow;
 import org.apache.fop.layoutmgr.BreakElement;
 import org.apache.fop.layoutmgr.ElementListUtils;
 import org.apache.fop.layoutmgr.KnuthBox;
-import org.apache.fop.layoutmgr.KnuthPenalty;
+import org.apache.fop.layoutmgr.KnuthElement;
 import org.apache.fop.layoutmgr.KnuthPossPosIter;
 import org.apache.fop.layoutmgr.LayoutContext;
 import org.apache.fop.layoutmgr.ListElement;
@@ -107,7 +107,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
     ColumnSetup getColumns() {
         return getTableLM().getColumns();
     }
-    
+
     /** @return the net header height */
     protected int getHeaderNetHeight() {
         return this.headerNetHeight;
@@ -208,56 +208,57 @@ public class TableContentLayoutManager implements PercentBaseContext {
     private LinkedList getKnuthElementsForRowIterator(TableRowIterator iter, 
             LayoutContext context, int alignment, int bodyType) {
         LinkedList returnList = new LinkedList();
-        EffRow[] rowGroup = null;
-        int breakBetween = Constants.EN_AUTO;
-        while ((rowGroup = iter.getNextRowGroup()) != null) {
+        EffRow[] rowGroup = iter.getNextRowGroup();
+        // TODO homogenize the handling of keeps and breaks
+        context.unsetFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING
+                | LayoutContext.KEEP_WITH_NEXT_PENDING);
+        context.setBreakBefore(Constants.EN_AUTO);
+        context.setBreakAfter(Constants.EN_AUTO);
+        boolean keepWithPrevious = false;
+        int breakBefore = Constants.EN_AUTO;
+        if (rowGroup != null) {
             RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup,
                     stepper);
-             // TODO
-             // The RowGroupLM.getBreakBefore method will work correctly only after
-             // getNextKnuthElements is called. Indeed TableCellLM will set the values for
-             // breaks on PrimaryGridUnit once it has got the Knuth elements of its
-             // children. This can be changed once all the LMs adopt the same scheme of
-             // querying childrens LMs for breaks instead of producing penalty elements
             List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType);
-            breakBetween = BreakUtil.compareBreakClasses(breakBetween, rowGroupLM.getBreakBefore());
-            if (breakBetween != Constants.EN_AUTO) {
-                if (returnList.size() > 0) {
-                    BreakElement breakPoss = (BreakElement) returnList.getLast();
-                    breakPoss.setPenaltyValue(-KnuthPenalty.INFINITE);
-                    breakPoss.setBreakClass(breakBetween);
-                } else {
-                    returnList.add(new BreakElement(new Position(tableLM),
-                            0, -KnuthPenalty.INFINITE, breakBetween, context));
-                }
-            }
+            keepWithPrevious = context.isKeepWithPreviousPending();
+            boolean keepBetween = context.isKeepWithNextPending();
+            breakBefore = context.getBreakBefore();
+            int breakBetween = context.getBreakAfter();
             returnList.addAll(nextRowGroupElems);
-            breakBetween = rowGroupLM.getBreakAfter();
-        }
-        // Break after the table's last row
-        // TODO should eventually be handled at the table level
-        if (breakBetween != Constants.EN_AUTO) {
-            if (returnList.size() > 0 && ((ListElement) returnList.getLast()).isPenalty()) {
-                // May be a glue if the unbroken height is greater than the broken heights
-                BreakElement breakPoss = (BreakElement) returnList.getLast();
-                breakPoss.setPenaltyValue(-KnuthPenalty.INFINITE);
-                breakPoss.setBreakClass(breakBetween);
-            } else {
-                returnList.add(new BreakElement(new Position(tableLM),
-                        0, -KnuthPenalty.INFINITE, breakBetween, context));
-            }
-        }
-        if (returnList.size() > 0) {
-            //Remove the last penalty produced by the combining algorithm (see TableStepper), 
-            //for the last step
-            ListElement last = (ListElement)returnList.getLast();
-            if (last.isPenalty() || last instanceof BreakElement) {
-                if (!last.isForcedBreak()) {
-                    //Only remove if we don't signal a forced break
-                    returnList.removeLast();
+            while ((rowGroup = iter.getNextRowGroup()) != null) {
+                rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, stepper);
+                nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType);
+                int penaltyValue = 0;
+                keepBetween |= context.isKeepWithPreviousPending();
+                if (keepBetween || tableLM.getTable().mustKeepTogether()) {
+                    penaltyValue = KnuthElement.INFINITE;
+                }
+                breakBetween = BreakUtil.compareBreakClasses(breakBetween,
+                        context.getBreakBefore());
+                if (breakBetween != Constants.EN_AUTO) {
+                    penaltyValue = -KnuthElement.INFINITE;
+                }
+                TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM());
+                int penaltyLen = 0;
+                if (bodyType == TableRowIterator.BODY) {
+                    if (!getTableLM().getTable().omitHeaderAtBreak()) {
+                        penaltyLen += getHeaderNetHeight();
+                        penaltyPos.headerElements = getHeaderElements();
+                    }
+                    if (!getTableLM().getTable().omitFooterAtBreak()) {
+                        penaltyLen += getFooterNetHeight();
+                        penaltyPos.footerElements = getFooterElements();
+                    }
                 }
+                returnList.add(new BreakElement(penaltyPos, 
+                        penaltyLen, penaltyValue, breakBetween, context));
+                returnList.addAll(nextRowGroupElems);
+                breakBetween = context.getBreakAfter();
+                keepBetween = context.isKeepWithNextPending();
             }
         }
+        context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING, keepWithPrevious);
+        context.setBreakBefore(breakBefore);
 
         //fox:widow-content-limit
         int widowContentLimit = getTableLM().getTable().getWidowContentLimit().getValue(); 
index 2e366f36d29a44b26ae81c65f6d21bf0b7c499c5..1cbc3e50a3b9c24cb6f6cf72c79852a42c387d84 100644 (file)
 
 package org.apache.fop.layoutmgr.table;
 
+import java.util.Iterator;
+import java.util.LinkedList;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.datatypes.LengthBase;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.flow.table.Table;
 import org.apache.fop.fo.flow.table.TableColumn;
 import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.BreakElement;
 import org.apache.fop.layoutmgr.ConditionalElementListener;
 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;
 import org.apache.fop.layoutmgr.TraitSetter;
-import org.apache.fop.area.Area;
-import org.apache.fop.area.Block;
 import org.apache.fop.traits.MinOptMax;
 import org.apache.fop.traits.SpaceVal;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import org.apache.fop.datatypes.LengthBase;
-import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.FObj;
+import org.apache.fop.util.BreakUtil;
 
 /**
  * LayoutManager for a table FO.
@@ -150,25 +151,11 @@ public class TableLayoutManager extends BlockStackingLayoutManager
     public int getHalfBorderSeparationIPD() {
         return halfBorderSeparationIPD;
     }
-    
-    /**
-     * Handles the Knuth elements at the table level: mainly breaks, spaces and borders
-     * before and after the table. The Knuth elements for the table cells are handled by
-     * TableContentLayoutManager.
-     *
-     * @see org.apache.fop.layoutmgr.LayoutManager
-     * @see TableContentLayoutManager#getNextKnuthElements(LayoutContext, int)
-     */
+
+    /** {@inheritDoc} */
     public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
         
         LinkedList returnList = new LinkedList();
-        
-        if (!breakBeforeServed) {
-            breakBeforeServed = true;
-            if (addKnuthElementsForBreakBefore(returnList, context)) {
-                return returnList;
-            }
-        }
 
         /*
          * Compute the IPD and adjust it if necessary (overconstrained)
@@ -225,10 +212,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager
 
         // Elements for the table-header/footer/body
         LinkedList contentKnuthElements = null;
-        LinkedList contentList = new LinkedList();
-        //Position returnPosition = new NonLeafPosition(this, null);
-        //Body prevLM = null;
-
+        contentLM = new TableContentLayoutManager(this);
         LayoutContext childLC = new LayoutContext(0);
         /*
         childLC.setStackLimit(
@@ -237,46 +221,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager
         childLC.setRefIPD(context.getRefIPD());
         childLC.copyPendingMarksFrom(context);
 
-        if (contentLM == null) {
-            contentLM = new TableContentLayoutManager(this);
-        }
         contentKnuthElements = contentLM.getNextKnuthElements(childLC, alignment);
-        if (childLC.isKeepWithNextPending()) {
-            log.debug("TableContentLM signals pending keep-with-next");
-            context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
-        }
-        if (childLC.isKeepWithPreviousPending()) {
-            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()) {
@@ -284,19 +229,36 @@ public class TableLayoutManager extends BlockStackingLayoutManager
             notifyPos(el.getPosition());
         }
         log.debug(contentKnuthElements);
-        contentList.addAll(contentKnuthElements);
-        wrapPositionElements(contentList, returnList);
+        wrapPositionElements(contentKnuthElements, returnList);
+
+        if (mustKeepWithPrevious() || childLC.isKeepWithPreviousPending()) {
+            context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+        }
+        if (mustKeepWithNext() || childLC.isKeepWithNextPending()) {
+            context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+        }
+
         if (getTable().isSeparateBorderModel()) {
             addKnuthElementsForBorderPaddingAfter(returnList, true);
         }
         addKnuthElementsForSpaceAfter(returnList, alignment);
-        addKnuthElementsForBreakAfter(returnList, context);
-        if (mustKeepWithNext()) {
-            context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
+
+        //addKnuthElementsForBreakBefore(returnList, context);
+        int breakBefore = BreakUtil.compareBreakClasses(getTable().getBreakBefore(),
+                childLC.getBreakBefore());
+        if (breakBefore != Constants.EN_AUTO) {
+            returnList.addFirst(new BreakElement(getAuxiliaryPosition(), 
+                    0, -KnuthElement.INFINITE, breakBefore, context));
         }
-        if (mustKeepWithPrevious()) {
-            context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
+
+        //addKnuthElementsForBreakAfter(returnList, context);
+        int breakAfter = BreakUtil.compareBreakClasses(getTable().getBreakAfter(),
+                childLC.getBreakAfter());
+        if (breakAfter != Constants.EN_AUTO) {
+            returnList.add(new BreakElement(getAuxiliaryPosition(), 
+                    0, -KnuthElement.INFINITE, breakAfter, context));
         }
+
         setFinished(true);
         resetSpaces();
         return returnList;
index 2560b3aac3f3c46515fa514f556d8b8e1516566b..ba67e38e41dda26b0ba4802fb4850a010c52f892 100644 (file)
@@ -174,7 +174,6 @@ public class TableStepper {
         activateCells(activeCells, 0);
         calcTotalHeight();
 
-        boolean signalKeepWithNext = false;
         int cumulateLength = 0; // Length of the content accumulated before the break
         TableContentPosition lastTCPos = null;
         LinkedList returnList = new LinkedList();
@@ -202,10 +201,6 @@ public class TableStepper {
                 ActiveCell activeCell = (ActiveCell) iter.next();
                 CellPart part = activeCell.createCellPart();
                 cellParts.add(part);
-                if (returnList.size() == 0 && part.isFirstPart()
-                        && part.mustKeepWithPrevious()) {
-                    context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
-                }
             }
 
             //Create elements for step
@@ -234,15 +229,23 @@ public class TableStepper {
             }
 
             int p = 0;
-            signalKeepWithNext = false;
+            boolean keepWithNext = false;
             for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
                 ActiveCell activeCell = (ActiveCell) iter.next();
-                signalKeepWithNext |= activeCell.keepWithNextSignal();
+                keepWithNext |= activeCell.keepWithNextSignal();
             }
-            if (signalKeepWithNext || getTableLM().mustKeepTogether()) {
+            if (keepWithNext || getTableLM().mustKeepTogether()) {
                 p = KnuthPenalty.INFINITE;
             }
-            if (rowFinished && activeRowIndex < rowGroup.length - 1) {
+            if (!rowFinished) {
+                if (rowGroup[activeRowIndex].mustKeepTogether()) {
+                    p = KnuthPenalty.INFINITE;
+                }
+            } else if (activeRowIndex < rowGroup.length - 1) {
+                if (rowGroup[activeRowIndex].mustKeepWithNext()
+                        || rowGroup[activeRowIndex + 1].mustKeepWithPrevious()) {
+                    p = KnuthPenalty.INFINITE;
+                }
                 nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
                         rowGroup[activeRowIndex].getBreakAfter());
                 nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
@@ -264,13 +267,12 @@ public class TableStepper {
             laststep = step;
             step = getNextStep();
         } while (step >= 0);
-        if (signalKeepWithNext) {
-            //Last step signalled a keep-with-next. Since the last penalty will be removed,
-            //we have to signal the still pending last keep-with-next using the LayoutContext.
-            context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
-        }
-        if (lastTCPos != null) {
+        if (!returnList.isEmpty()) {
             lastTCPos.setFlag(TableContentPosition.LAST_IN_ROWGROUP, true);
+            // It's not up to TableStepper to decide whether there can/must be a break
+            // after the row group or not, but to ancestor stacking elements
+            assert returnList.getLast() instanceof BreakElement;
+            returnList.removeLast();
         }
         return returnList;
     }
index 0dc2548ae5932e56e6275279fbe1d6c114909875..f618b0074be350070be9f01419fcea6dec133b6a 100644 (file)
@@ -28,6 +28,9 @@
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Layout" dev="VH" type="add">
+        Added full support for keep-with-previous on fo:table-row and in fo:table-cell elements.
+      </action>
       <action context="Code" dev="MB" type="add">
         Turned on XInclude processing for the main source given on the command line.
       </action>
index 45df7e337ba7d0da4f0d5788f8dd9f78361c6b21..b4eb7aead1de76bb052fe3fbb0c63610e1e022da 100644 (file)
@@ -32,9 +32,8 @@
       <fo:page-sequence master-reference="normal">
         <fo:flow flow-name="xsl-region-body">
           <fo:block>block1</fo:block>
-          <fo:table table-layout="fixed">
-            <fo:table-column/>
-            <fo:table-column/>
+          <fo:table table-layout="fixed" width="100%">
+            <fo:table-column number-columns-repeated="2" column-width="proportional-column-width(1)"/>
             <fo:table-body>
               <fo:table-row>
                 <fo:table-cell id="cell1">
diff --git a/test/layoutengine/standard-testcases/table-cell_keep-together.xml b/test/layoutengine/standard-testcases/table-cell_keep-together.xml
new file mode 100644 (file)
index 0000000..e35f343
--- /dev/null
@@ -0,0 +1,209 @@
+<?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 keep-together works on blocks 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 master-name="page" page-height="3in" page-width="5in"
+          margin="0.5in">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+
+      <!-- table 1 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="118pt">1. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block keep-together="always">
+                    <fo:block>Cell 1.1 Line 1</fo:block>
+                    <fo:block>Cell 1.1 Line 2</fo:block>
+                  </fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 3.1 Line 1</fo:block>
+                  <fo:block>Cell 3.1 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>
+
+      <!-- table 2 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="118pt">2. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" number-rows-spanned="2">
+                  <fo:block keep-together="always">
+                    <fo:block>Cell 1.2 Line 1</fo:block>
+                    <fo:block>Cell 1.2 Line 2</fo:block>
+                  </fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.2 Line 1</fo:block>
+                  <fo:block>Cell 2.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>
+
+      <!-- table 3 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="100">3. 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 blue" number-rows-spanned="2">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block keep-together="always">
+                    <fo:block>Cell 2.1 Line 1</fo:block>
+                    <fo:block>Cell 2.1 Line 2</fo:block>
+                  </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>
+
+    <!-- table 1 -->
+    <eval expected="2"              xpath="count(//pageSequence[1]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="1. Before the table"  xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="48000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpd"/>
+    <eval expected="56000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-after"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea"/>
+
+    <!-- table 2 -->
+    <eval expected="2"              xpath="count(//pageSequence[2]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="1"              xpath="count(//pageViewport[@nr=3]//flow/block)"/>
+    <eval expected="2. Before the table"  xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=4]//flow/block)"/>
+    <eval expected="48000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpd"/>
+    <eval expected="56000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-after"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=4]//flow/block[2]/lineArea"/>
+
+    <!-- table 3 -->
+    <eval expected="2"                             xpath="count(//pageSequence[3]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=5]//flow/block)"/>
+    <eval expected="3. Before the table"                 xpath="//pageViewport[@nr=5]//flow/block[1]/lineArea"/>
+    <eval expected="23000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/@bpd"/>
+    <eval expected="23000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/@bpda"/>
+    <!-- cell 1.1 -->
+    <eval expected="21000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="25000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="21000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="21000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=5]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.1 Line 1"                     xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/block[1]/lineArea"/>
+    <eval expected="Cell 1.1 Line 2"                     xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/block[2]/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[3]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[3]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=5]//flow/block[2]/block[3]/@border-before"/>
+    <eval expected="(solid,#008080,2000,collapse-outer)" xpath="//pageViewport[@nr=5]//flow/block[2]/block[3]/@border-after"/>
+    <!-- page 2 -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=6]//flow/block)"/>
+    <eval expected="After the table"                     xpath="//pageViewport[@nr=6]//flow/block[2]/lineArea"/>
+    <eval expected="23000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/@bpd"/>
+    <eval expected="23000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/@bpda"/>
+    <!-- cell 1.1 -->
+    <eval expected="21000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="25000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="21000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="21000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="0"                             xpath="count(//pageViewport[@nr=6]//flow/block[1]/block[2]/block)"/>
+    <!-- cell 2.2 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected="(solid,#808000,2000,collapse-outer)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@border-after"/>
+
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-cell_keep-with-next.xml b/test/layoutengine/standard-testcases/table-cell_keep-with-next.xml
new file mode 100644 (file)
index 0000000..f4cb03a
--- /dev/null
@@ -0,0 +1,376 @@
+<?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 keep-with-next works on blocks 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 master-name="page" page-height="3in" page-width="5in"
+          margin="0.5in">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+
+      <!-- table 1 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="106pt">1. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block keep-with-next="always">Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 3.1 Line 1</fo:block>
+                  <fo:block>Cell 3.1 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>
+
+      <!-- table 2 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="106pt">2. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block keep-with-next="always">Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" number-rows-spanned="2">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+      <!-- table 3 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="78pt">3. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" number-rows-spanned="2">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block keep-with-next="always">Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+      <!-- table 4 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="88">4. 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 blue" number-rows-spanned="2">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 2.2 Line 1</fo:block>
+                  <fo:block keep-with-next="always">Cell 2.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>
+
+    <!-- table 1 -->
+    <eval expected="2"              xpath="count(//pageSequence[1]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="1. Before the table"  xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/@bpd"/>
+    <eval expected="16000"                xpath="//pageViewport[@nr=1]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=1]//flow/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 1"      xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 1"      xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/block/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpd"/>
+    <eval expected="40000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 2"      xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 2"      xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/block/lineArea"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-after"/>
+    <!-- cell 2.2 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpda"/>
+    <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-before"/>
+    <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-after"/>
+
+    <!-- table 2 -->
+    <eval expected="2"              xpath="count(//pageSequence[2]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=3]//flow/block)"/>
+    <eval expected="2. Before the table"  xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/@bpd"/>
+    <eval expected="16000"                xpath="//pageViewport[@nr=3]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=3]//flow/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 1"      xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 1"      xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/block/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=4]//flow/block)"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=4]//flow/block[2]/lineArea"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpd"/>
+    <eval expected="40000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 2"      xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/block/lineArea"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-after"/>
+    <!-- cell 1.2 -->
+    <eval expected="34000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[3]/block)"/>
+    <eval expected="Cell 1.2 Line 2"      xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/block/lineArea"/>
+
+    <!-- table 3 -->
+    <eval expected="2"              xpath="count(//pageSequence[3]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=5]//flow/block)"/>
+    <eval expected="3. Before the table"  xpath="//pageViewport[@nr=5]//flow/block[1]/lineArea"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=5]//flow/block[2]/@bpd"/>
+    <eval expected="16000"                xpath="//pageViewport[@nr=5]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=5]//flow/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=5]//flow/block[2]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=5]//flow/block[2]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 1"      xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/block[1]/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=5]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 1"      xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=6]//flow/block)"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=6]//flow/block[2]/lineArea"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=6]//flow/block[1]/@bpd"/>
+    <eval expected="40000"                xpath="//pageViewport[@nr=6]//flow/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=6]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=6]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=6]//flow/block[1]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 2"      xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/block[1]/lineArea"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=6]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=6]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[2]/@border-after"/>
+    <!-- cell 1.2 -->
+    <eval expected="34000"                xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=6]//flow/block[1]/block[3]/block)"/>
+    <eval expected="Cell 1.2 Line 2"      xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/block[1]/lineArea"/>
+
+    <!-- table 4 -->
+    <eval expected="2"                             xpath="count(//pageSequence[4]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=7]//flow/block)"/>
+    <eval expected="4. Before the table"                 xpath="//pageViewport[@nr=7]//flow/block[1]/lineArea"/>
+    <eval expected="34000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/@bpd"/>
+    <eval expected="34000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/@bpda"/>
+    <!-- cell 1.2 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=7]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected="(solid,#008080,2000,collapse-inner)" xpath="//pageViewport[@nr=7]//flow/block[2]/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="21000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="25000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=7]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=7]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="11000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[3]/@bpd"/>
+    <eval expected="11000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[3]/@bpda"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=7]//flow/block[2]/block[3]/@border-before"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=7]//flow/block[2]/block[3]/@border-after"/>
+    <eval expected="32000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[4]/@bpd"/>
+    <eval expected="32000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[4]/@bpda"/>
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=7]//flow/block[2]/block[4]/block)"/>
+    <eval expected="Cell 1.1 Line 1"                     xpath="//pageViewport[@nr=7]//flow/block[2]/block[4]/block[1]/lineArea"/>
+    <eval expected="Cell 1.1 Line 2"                     xpath="//pageViewport[@nr=7]//flow/block[2]/block[4]/block[2]/lineArea"/>
+    <!-- cell 2.2 -->
+    <eval expected="10000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[5]/@bpd"/>
+    <eval expected="12000"                               xpath="//pageViewport[@nr=7]//flow/block[2]/block[5]/@bpda"/>
+    <eval expected="(solid,#808000,2000,collapse-inner)" xpath="//pageViewport[@nr=7]//flow/block[2]/block[5]/@border-before"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=7]//flow/block[2]/block[5]/@border-after"/>
+    <eval expected="1"                             xpath="count(//pageViewport[@nr=7]//flow/block[2]/block[5]/block)"/>
+    <eval expected="Cell 2.2 Line 1"                     xpath="//pageViewport[@nr=7]//flow/block[2]/block[5]/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=8]//flow/block)"/>
+    <eval expected="After the table"                     xpath="//pageViewport[@nr=8]//flow/block[2]/lineArea"/>
+    <eval expected="12000"                               xpath="//pageViewport[@nr=8]//flow/block[1]/@bpd"/>
+    <eval expected="12000"                               xpath="//pageViewport[@nr=8]//flow/block[1]/@bpda"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                               xpath="//pageViewport[@nr=8]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="14000"                               xpath="//pageViewport[@nr=8]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=8]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=8]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="10000"                               xpath="//pageViewport[@nr=8]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="10000"                               xpath="//pageViewport[@nr=8]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="0"                             xpath="count(//pageViewport[@nr=8]//flow/block[1]/block[2]/block)"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                               xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="14000"                               xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/@border-after"/>
+    <eval expected="1"                             xpath="count(//pageViewport[@nr=8]//flow/block[1]/block[3]/block)"/>
+    <eval expected="Cell 2.2 Line 2"                     xpath="//pageViewport[@nr=8]//flow/block[1]/block[3]/block[1]/lineArea"/>
+
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-cell_keep-with-previous.xml b/test/layoutengine/standard-testcases/table-cell_keep-with-previous.xml
new file mode 100644 (file)
index 0000000..2ad4dd4
--- /dev/null
@@ -0,0 +1,256 @@
+<?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 keep-with-previous works on blocks 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 master-name="page" page-height="3in" page-width="5in"
+          margin="0.5in">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+
+      <!-- table 1 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="106pt">1. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block keep-with-previous="always">Cell 3.1 Line 1</fo:block>
+                  <fo:block>Cell 3.1 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>
+
+      <!-- table 2 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="106pt">2. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" number-rows-spanned="2">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block keep-with-previous="always">Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+      <!-- table 3 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="124">3. Before the table</fo:block>
+          <fo:block>Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" number-rows-spanned="2">
+                  <fo:block keep-with-previous="always">Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+    <!-- table 1 -->
+    <eval expected="2"              xpath="count(//pageSequence[1]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="1. Before the table"  xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/@bpd"/>
+    <eval expected="16000"                xpath="//pageViewport[@nr=1]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=1]//flow/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 1"      xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 1"      xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/block/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpd"/>
+    <eval expected="40000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 2"      xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 2"      xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/block/lineArea"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-after"/>
+    <!-- cell 2.2 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpda"/>
+    <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-before"/>
+    <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-after"/>
+
+    <!-- table 2 -->
+    <eval expected="2"              xpath="count(//pageSequence[2]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=3]//flow/block)"/>
+    <eval expected="2. Before the table"  xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/@bpd"/>
+    <eval expected="16000"                xpath="//pageViewport[@nr=3]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=3]//flow/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 1"      xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 1"      xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/block/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=4]//flow/block)"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=4]//flow/block[2]/lineArea"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpd"/>
+    <eval expected="40000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 2"      xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/block/lineArea"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-after"/>
+    <!-- cell 1.2 -->
+    <eval expected="34000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[3]/block)"/>
+    <eval expected="Cell 1.2 Line 2"      xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/block/lineArea"/>
+
+    <!-- table 3 -->
+    <eval expected="2"              xpath="count(//pageSequence[3]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="1"              xpath="count(//pageViewport[@nr=5]//flow/block)"/>
+    <eval expected="3. Before the table"  xpath="//pageViewport[@nr=5]//flow/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="3"              xpath="count(//pageViewport[@nr=6]//flow/block)"/>
+    <eval expected="Before the table"     xpath="//pageViewport[@nr=6]//flow/block[1]/lineArea"/>
+    <eval expected="48000"                xpath="//pageViewport[@nr=6]//flow/block[2]/@bpd"/>
+    <eval expected="56000"                xpath="//pageViewport[@nr=6]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=6]//flow/block[2]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=6]//flow/block[2]/@border-after"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=6]//flow/block[3]/lineArea"/>
+
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/table-row_keep-together_2.xml b/test/layoutengine/standard-testcases/table-row_keep-together_2.xml
new file mode 100644 (file)
index 0000000..0e2867b
--- /dev/null
@@ -0,0 +1,203 @@
+<?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 keep-together works on table-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="3in" page-width="5in"
+          margin="0.5in">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+
+      <!-- table 1 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="118pt">1. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" border="4pt solid black">
+            <fo:table-column number-columns-repeated="2"
+              column-width="proportional-column-width(1)"/>
+            <fo:table-body>
+              <fo:table-row keep-together="always">
+                <fo:table-cell border="2pt solid blue" keep-together="auto">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" keep-together="auto">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 3.1 Line 1</fo:block>
+                  <fo:block>Cell 3.1 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>
+
+      <!-- table 2 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="118">2. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" border="4pt solid black">
+            <fo:table-column number-columns-repeated="2"
+              column-width="proportional-column-width(1)"/>
+            <fo:table-body>
+              <fo:table-row keep-together="always">
+                <fo:table-cell border="2pt solid blue" keep-together="auto">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" number-rows-spanned="2" keep-together="auto">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+      <!-- table 3 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="100">3. 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 blue" number-rows-spanned="2">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-together="always">
+                <fo:table-cell border="2pt solid olive" keep-together="auto">
+                  <fo:block>Cell 2.2 Line 1</fo:block>
+                  <fo:block>Cell 2.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>
+
+    <!-- table 1 -->
+    <eval expected="2"              xpath="count(//pageSequence[1]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="1. Before the table"  xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="48000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpd"/>
+    <eval expected="56000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-after"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea"/>
+
+    <!-- table 2 -->
+    <eval expected="2"              xpath="count(//pageSequence[2]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="1"              xpath="count(//pageViewport[@nr=3]//flow/block)"/>
+    <eval expected="2. Before the table"  xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=4]//flow/block)"/>
+    <eval expected="48000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpd"/>
+    <eval expected="56000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-after"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=4]//flow/block[2]/lineArea"/>
+
+    <!-- table 3 -->
+    <eval expected="2"                             xpath="count(//pageSequence[3]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=5]//flow/block)"/>
+    <eval expected="3. Before the table"                 xpath="//pageViewport[@nr=5]//flow/block[1]/lineArea"/>
+    <eval expected="23000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/@bpd"/>
+    <eval expected="23000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/@bpda"/>
+    <!-- cell 1.1 -->
+    <eval expected="21000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="25000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=5]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="21000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="21000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=5]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.1 Line 1"                     xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/block[1]/lineArea"/>
+    <eval expected="Cell 1.1 Line 2"                     xpath="//pageViewport[@nr=5]//flow/block[2]/block[2]/block[2]/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[3]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=5]//flow/block[2]/block[3]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=5]//flow/block[2]/block[3]/@border-before"/>
+    <eval expected="(solid,#008080,2000,collapse-outer)" xpath="//pageViewport[@nr=5]//flow/block[2]/block[3]/@border-after"/>
+    <!-- page 2 -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=6]//flow/block)"/>
+    <eval expected="After the table"                     xpath="//pageViewport[@nr=6]//flow/block[2]/lineArea"/>
+    <eval expected="23000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/@bpd"/>
+    <eval expected="23000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/@bpda"/>
+    <!-- cell 1.1 -->
+    <eval expected="21000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="25000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="21000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="21000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="0"                             xpath="count(//pageViewport[@nr=6]//flow/block[1]/block[2]/block)"/>
+    <!-- cell 2.2 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected="(solid,#808000,2000,collapse-outer)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=6]//flow/block[1]/block[3]/@border-after"/>
+
+  </checks>
+</testcase>
index 5ceedb932b061f290b44279a895fc568d53b03c7..3657f2a903cd59b40a77dad00b590b87787c8e33 100644 (file)
@@ -32,9 +32,8 @@
       <fo:page-sequence master-reference="normal">
         <fo:flow flow-name="xsl-region-body">
           <fo:block>block1</fo:block>
-          <fo:table table-layout="fixed">
-            <fo:table-column/>
-            <fo:table-column/>
+          <fo:table table-layout="fixed" width="100%">
+            <fo:table-column number-columns-repeated="2" column-width="proportional-column-width(1)"/>
             <fo:table-body>
               <fo:table-row keep-with-next.within-page="always">
                 <fo:table-cell id="cell1">
@@ -73,7 +72,7 @@
       <box w="14400"/>
       <penalty w="0" p="0"/>
       <box w="14400"/>
-      <penalty w="0" p="INF"/>
+      <penalty w="0" p="0"/>
       <box w="14400"/>
       <penalty w="0" p="INF"/>
       <box w="14400"/>
diff --git a/test/layoutengine/standard-testcases/table-row_keep-with-next_3.xml b/test/layoutengine/standard-testcases/table-row_keep-with-next_3.xml
new file mode 100644 (file)
index 0000000..ffd4aaf
--- /dev/null
@@ -0,0 +1,205 @@
+<?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 keep-with-next works on table-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="3in" page-width="5in"
+          margin="0.5in">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+
+      <!-- table 1 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="106pt">1. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" border="4pt solid black">
+            <fo:table-column number-columns-repeated="2"
+              column-width="proportional-column-width(1)"/>
+            <fo:table-body>
+              <fo:table-row keep-with-next="always">
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" number-rows-spanned="2">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+      <!-- table 2 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="88">2. 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 blue" number-rows-spanned="2">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-next="always">
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 2.2 Line 1</fo:block>
+                  <fo:block>Cell 2.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>
+
+    <!-- table 1 -->
+    <eval expected="2"              xpath="count(//pageSequence[1]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="1. Before the table"  xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/@bpd"/>
+    <eval expected="16000"                xpath="//pageViewport[@nr=1]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=1]//flow/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 1"      xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 1"      xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/block/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpd"/>
+    <eval expected="40000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 2"      xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/block/lineArea"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-after"/>
+    <!-- cell 1.2 -->
+    <eval expected="34000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[3]/block)"/>
+    <eval expected="Cell 1.2 Line 2"      xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/block/lineArea"/>
+
+    <!-- table 2 -->
+    <eval expected="2"                             xpath="count(//pageSequence[2]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=3]//flow/block)"/>
+    <eval expected="2. Before the table"                 xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea"/>
+    <eval expected="34000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/@bpd"/>
+    <eval expected="34000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/@bpda"/>
+    <!-- cell 1.2 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected="(solid,#008080,2000,collapse-inner)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="21000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="25000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="11000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[3]/@bpd"/>
+    <eval expected="11000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[3]/@bpda"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=3]//flow/block[2]/block[3]/@border-before"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=3]//flow/block[2]/block[3]/@border-after"/>
+    <eval expected="32000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[4]/@bpd"/>
+    <eval expected="32000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[4]/@bpda"/>
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[4]/block)"/>
+    <eval expected="Cell 1.1 Line 1"                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[4]/block[1]/lineArea"/>
+    <eval expected="Cell 1.1 Line 2"                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[4]/block[2]/lineArea"/>
+    <!-- cell 2.2 -->
+    <eval expected="10000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[5]/@bpd"/>
+    <eval expected="12000"                               xpath="//pageViewport[@nr=3]//flow/block[2]/block[5]/@bpda"/>
+    <eval expected="(solid,#808000,2000,collapse-inner)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[5]/@border-before"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=3]//flow/block[2]/block[5]/@border-after"/>
+    <eval expected="1"                             xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[5]/block)"/>
+    <eval expected="Cell 2.2 Line 1"                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[5]/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=4]//flow/block)"/>
+    <eval expected="After the table"                     xpath="//pageViewport[@nr=4]//flow/block[2]/lineArea"/>
+    <eval expected="12000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/@bpd"/>
+    <eval expected="12000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/@bpda"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="14000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="10000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="10000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="0"                             xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[2]/block)"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="14000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected=""                                    xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-after"/>
+    <eval expected="1"                             xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[3]/block)"/>
+    <eval expected="Cell 2.2 Line 2"                     xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/block[1]/lineArea"/>
+
+  </checks>
+</testcase>
index 466634552e05307572614acac4f548f539c7e78b..34a8be4c1b3861ea4e7ea5e7a049943edab5bbfc 100644 (file)
       </fo:layout-master-set>
       <fo:page-sequence master-reference="normal">
         <fo:flow flow-name="xsl-region-body">
-          <fo:block>block1</fo:block>
-          <fo:table table-layout="fixed">
-            <fo:table-column/>
-            <fo:table-column/>
+          <fo:block space-after="1.5*14.4pt">block1</fo:block>
+          <fo:table table-layout="fixed" width="100%">
+            <fo:table-column number-columns-repeated="2" column-width="proportional-column-width(1)"/>
             <fo:table-body>
               <fo:table-row keep-with-previous.within-page="always">
                 <fo:table-cell id="cell1">
diff --git a/test/layoutengine/standard-testcases/table-row_keep-with-previous_2.xml b/test/layoutengine/standard-testcases/table-row_keep-with-previous_2.xml
new file mode 100644 (file)
index 0000000..e613130
--- /dev/null
@@ -0,0 +1,254 @@
+<?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 keep-with-previous works on table-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="3in" page-width="5in"
+          margin="0.5in">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+
+      <!-- table 1 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="106pt">1. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-previous="always">
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 3.1 Line 1</fo:block>
+                  <fo:block>Cell 3.1 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>
+
+      <!-- table 2 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="106pt">2. Before the table</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" 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 blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal" number-rows-spanned="2">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row keep-with-previous="always">
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+      <!-- table 3 -->
+      <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="124">3. Before the table</fo:block>
+          <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 keep-with-previous="always">
+                <fo:table-cell border="2pt solid blue" number-rows-spanned="2">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+    <!-- table 1 -->
+    <eval expected="2"              xpath="count(//pageSequence[1]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="1. Before the table"  xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/@bpd"/>
+    <eval expected="16000"                xpath="//pageViewport[@nr=1]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=1]//flow/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 1"      xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 1"      xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/block/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=2]//flow/block)"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpd"/>
+    <eval expected="40000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 2"      xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 2"      xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/block/lineArea"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-after"/>
+    <!-- cell 2.2 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpda"/>
+    <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-before"/>
+    <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-after"/>
+
+    <!-- table 2 -->
+    <eval expected="2"              xpath="count(//pageSequence[2]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=3]//flow/block)"/>
+    <eval expected="2. Before the table"  xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/@bpd"/>
+    <eval expected="16000"                xpath="//pageViewport[@nr=3]//flow/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=3]//flow/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 1"      xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/block/lineArea"/>
+    <!-- cell 1.2 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-before"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[2]/block)"/>
+    <eval expected="Cell 1.2 Line 1"      xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/block/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="2"              xpath="count(//pageViewport[@nr=4]//flow/block)"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=4]//flow/block[2]/lineArea"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpd"/>
+    <eval expected="40000"                xpath="//pageViewport[@nr=4]//flow/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="10000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="12000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[1]/block)"/>
+    <eval expected="Cell 1.1 Line 2"      xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/block/lineArea"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-after"/>
+    <!-- cell 1.2 -->
+    <eval expected="34000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="36000"                xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected=""                     xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-after"/>
+    <eval expected="1"              xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[3]/block)"/>
+    <eval expected="Cell 1.2 Line 2"      xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/block/lineArea"/>
+
+    <!-- table 3 -->
+    <eval expected="2"              xpath="count(//pageSequence[3]/pageViewport)"/>
+    <!-- page 1 -->
+    <eval expected="1"              xpath="count(//pageViewport[@nr=5]//flow/block)"/>
+    <eval expected="3. Before the table"  xpath="//pageViewport[@nr=5]//flow/block[1]/lineArea"/>
+    <!-- page 2 -->
+    <eval expected="3"              xpath="count(//pageViewport[@nr=6]//flow/block)"/>
+    <eval expected="Before the table"     xpath="//pageViewport[@nr=6]//flow/block[1]/lineArea"/>
+    <eval expected="46000"                xpath="//pageViewport[@nr=6]//flow/block[2]/@bpd"/>
+    <eval expected="46000"                xpath="//pageViewport[@nr=6]//flow/block[2]/@bpda"/>
+    <eval expected="After the table"      xpath="//pageViewport[@nr=6]//flow/block[3]/lineArea"/>
+
+  </checks>
+</testcase>
index 31c1fd8cba7d3b070884c25cb22591aa38a49c4b..0ec629d87608b8056a22024560c684f5f7344efb 100644 (file)
     <eval expected="5" xpath="count(//pageViewport)"/>
     <!-- table -->
     <eval expected="18400" xpath="//pageViewport[@nr=3]//flow/block[1]/@bpd"/>
-    <!--
-    <eval expected="26400" xpath="//pageViewport[@nr=3]//flow/block[1]/@bpda"/>
-    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=3]//flow/block[1]/@border-before"/>
-    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=3]//flow/block[1]/@border-after"/>
-    -->
+    <!--eval expected="26400" xpath="//pageViewport[@nr=3]//flow/block[1]/@bpda"/-->
+    <!--eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=3]//flow/block[1]/@border-before"/-->
+    <!--eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=3]//flow/block[1]/@border-after"/-->
     <!-- cell 1 -->
     <eval expected="14400" xpath="//pageViewport[@nr=3]//flow/block[1]/block[1]/@bpd"/>
     <eval expected="18400" xpath="//pageViewport[@nr=3]//flow/block[1]/block[1]/@bpda"/>
diff --git a/test/layoutengine/standard-testcases/table_keep-together_2.xml b/test/layoutengine/standard-testcases/table_keep-together_2.xml
new file mode 100644 (file)
index 0000000..0c3d400
--- /dev/null
@@ -0,0 +1,181 @@
+<?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 keep-together works on tables.
+    </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="3in" page-width="5in"
+          margin="0.5in">
+          <fo:region-body background-color="#F0F0F0"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+
+      <!-- table 1 -->
+      <fo:page-sequence master-reference="page" font-family="serif" font-size="8pt"
+        line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="106pt">First line</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="separate" border="4pt solid black"
+            keep-together="always">
+            <fo:table-column number-columns-repeated="2"
+              column-width="proportional-column-width(1)"/>
+            <fo:table-body keep-together="auto">
+              <fo:table-row>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+    <!-- table 2 -->
+      <fo:page-sequence master-reference="page" font-family="serif" font-size="8pt"
+        line-height="10pt">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block space-after="100">First line</fo:block>
+          <fo:table width="100%" table-layout="fixed"
+            border-collapse="collapse" border="4pt solid black"
+            keep-together="always">
+            <fo:table-column number-columns-repeated="2"
+              column-width="proportional-column-width(1)"/>
+            <fo:table-body keep-together="auto">
+              <fo:table-row>
+                <fo:table-cell border="2pt solid blue">
+                  <fo:block>Cell 1.1 Line 1</fo:block>
+                  <fo:block>Cell 1.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid teal">
+                  <fo:block>Cell 1.2 Line 1</fo:block>
+                  <fo:block>Cell 1.2 Line 2</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+              <fo:table-row>
+                <fo:table-cell border="2pt solid green">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 Line 2</fo:block>
+                </fo:table-cell>
+                <fo:table-cell border="2pt solid olive">
+                  <fo:block>Cell 2.1 Line 1</fo:block>
+                  <fo:block>Cell 2.1 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>
+
+    <!-- table 1 -->
+    <!-- Two pages -->
+    <eval expected="2"              xpath="count(//pageSequence[1]/pageViewport)"/>
+    <!-- Only one line on the first page -->
+    <eval expected="1"              xpath="count(//pageViewport[@nr=1]//flow/block)"/>
+    <eval expected="First line"           xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea/text[1]"/>
+    <!-- Line "Before the table" plus the table itself 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]"/>
+    <!-- table -->
+    <eval expected="48000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpd"/>
+    <eval expected="56000"                xpath="//pageViewport[@nr=2]//flow/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-before"/>
+    <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-after"/>
+    <!-- cell 1.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-after"/>
+    <!-- cell 1.2 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-after"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-after"/>
+    <!-- cell 2.2 -->
+    <eval expected="20000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpd"/>
+    <eval expected="24000"                xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpda"/>
+    <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-before"/>
+    <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-after"/>
+
+    <!-- table 2 -->
+    <!-- Two pages -->
+    <eval expected="2" xpath="count(//pageSequence[2]/pageViewport)"/>
+    <!-- Only one line on the first page -->
+    <eval expected="1"                                   xpath="count(//pageViewport[@nr=3]//flow/block)"/>
+    <eval expected="First line"                          xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea/text[1]"/>
+    <!-- Line "Before the table" plus the table itself on the second page -->
+    <eval expected="2"                             xpath="count(//pageViewport[@nr=4]//flow/block)"/>
+    <eval expected="After the table"                     xpath="//pageViewport[@nr=4]//flow/block[2]/lineArea/text[1]"/>
+    <!-- table -->
+    <eval expected="46000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/@bpd"/>
+    <eval expected="46000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/@bpda"/>
+    <!-- cell 1.1 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-before"/>
+    <eval expected="(solid,#0000ff,2000,collapse-inner)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-after"/>
+    <!-- cell 1.2 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpda"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-before"/>
+    <eval expected="(solid,#008080,2000,collapse-inner)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-after"/>
+    <!-- cell 2.1 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpda"/>
+    <eval expected="(solid,#008000,2000,collapse-inner)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-after"/>
+    <!-- cell 2.2 -->
+    <eval expected="20000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[4]/@bpd"/>
+    <eval expected="26000"                               xpath="//pageViewport[@nr=4]//flow/block[1]/block[4]/@bpda"/>
+    <eval expected="(solid,#808000,2000,collapse-inner)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[4]/@border-before"/>
+    <eval expected="(solid,#000000,4000,collapse-outer)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[4]/@border-after"/>
+
+  </checks>
+</testcase>