From 5250c87d0ea8ff16a23973244a3c9a410f44272b Mon Sep 17 00:00:00 2001
From: Vincent Hennebert
Date: Mon, 25 Feb 2008 11:30:43 +0000
Subject: [PATCH] - added full support for keep-with-previous on table-row and
in table-cell - 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
---
.../org/apache/fop/fo/flow/table/EffRow.java | 58 +++
.../fop/fo/flow/table/EmptyGridUnit.java | 3 +-
.../flow/table/FixedColRowGroupBuilder.java | 32 +-
.../apache/fop/fo/flow/table/GridUnit.java | 22 +-
.../fop/fo/flow/table/PrimaryGridUnit.java | 41 +-
.../fop/fo/flow/table/RowGroupBuilder.java | 11 +-
.../org/apache/fop/fo/flow/table/Table.java | 11 +-
.../apache/fop/fo/flow/table/TableBody.java | 12 +-
.../table/VariableColRowGroupBuilder.java | 12 +-
.../apache/fop/layoutmgr/LayoutContext.java | 57 ++-
.../fop/layoutmgr/table/ActiveCell.java | 20 +-
.../apache/fop/layoutmgr/table/CellPart.java | 6 -
.../table/RowGroupLayoutManager.java | 110 ++---
.../table/TableCellLayoutManager.java | 5 +-
.../table/TableContentLayoutManager.java | 91 ++---
.../layoutmgr/table/TableLayoutManager.java | 114 ++----
.../fop/layoutmgr/table/TableStepper.java | 32 +-
status.xml | 3 +
.../table-cell_block_keep-with-next.xml | 5 +-
.../table-cell_keep-together.xml | 209 ++++++++++
.../table-cell_keep-with-next.xml | 376 ++++++++++++++++++
.../table-cell_keep-with-previous.xml | 256 ++++++++++++
.../table-row_keep-together_2.xml | 203 ++++++++++
.../table-row_keep-with-next.xml | 7 +-
.../table-row_keep-with-next_3.xml | 205 ++++++++++
.../table-row_keep-with-previous.xml | 7 +-
.../table-row_keep-with-previous_2.xml | 254 ++++++++++++
.../table_break-before_break-after.xml | 8 +-
.../table_keep-together_2.xml | 181 +++++++++
29 files changed, 2040 insertions(+), 311 deletions(-)
create mode 100644 test/layoutengine/standard-testcases/table-cell_keep-together.xml
create mode 100644 test/layoutengine/standard-testcases/table-cell_keep-with-next.xml
create mode 100644 test/layoutengine/standard-testcases/table-cell_keep-with-previous.xml
create mode 100644 test/layoutengine/standard-testcases/table-row_keep-together_2.xml
create mode 100644 test/layoutengine/standard-testcases/table-row_keep-with-next_3.xml
create mode 100644 test/layoutengine/standard-testcases/table-row_keep-with-previous_2.xml
create mode 100644 test/layoutengine/standard-testcases/table_keep-together_2.xml
diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java
index 7989f3d9d..0b00b9620 100644
--- a/src/java/org/apache/fop/fo/flow/table/EffRow.java
+++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java
@@ -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.
+ * Note: 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).
*
Note: this works only after getNextKuthElements on the
* corresponding TableCellLM have been called!
*
@@ -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.
+ * Note: 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).
*
Note: this works only after getNextKuthElements on the
* corresponding TableCellLM have been called!
*
diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
index 583abcaa3..201029ff1 100644
--- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
@@ -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} */
diff --git a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
index 62cf3e26d..28a30c6f7 100644
--- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
@@ -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();
}
}
diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java
index edf0c99ea..23d1cc001 100644
--- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java
@@ -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)) {
diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
index c95f3f8c3..1a47a7dcf 100644
--- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
@@ -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.
*
diff --git a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
index 3f7549787..c954be711 100644
--- a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
@@ -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.
*
* If the source does contain explicit fo:table-row elements, then the
- * {@link #endRow(TableRow)} method will be called instead.
+ * {@link #endTableRow()} method will be called instead.
*
* @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;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/Table.java b/src/java/org/apache/fop/fo/flow/table/Table.java
index 2b6570dcc..7d6611435 100644
--- a/src/java/org/apache/fop/fo/flow/table/Table.java
+++ b/src/java/org/apache/fop/fo/flow/table/Table.java
@@ -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);
diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java
index c3642c260..de7bfda84 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableBody.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java
@@ -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) {
diff --git a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
index 801153ce9..d59870f0a 100644
--- a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
@@ -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();
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java
index beda11fe8..9eb38600b 100644
--- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java
+++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java
@@ -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" : "") + "]";
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
index c4bff5112..c1e4ae619 100644
--- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
+++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
@@ -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) {
diff --git a/src/java/org/apache/fop/layoutmgr/table/CellPart.java b/src/java/org/apache/fop/layoutmgr/table/CellPart.java
index 2adb543a9..560b70344 100644
--- a/src/java/org/apache/fop/layoutmgr/table/CellPart.java
+++ b/src/java/org/apache/fop/layoutmgr/table/CellPart.java
@@ -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());
- }
-
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
index 0127f4d81..c2e26e18d 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
@@ -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);
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
index fbc118723..289785d68 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
@@ -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) {
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
index c09b9b076..b9a118e28 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
@@ -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();
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
index 2e366f36d..1cbc3e50a 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
@@ -19,31 +19,32 @@
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;
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
index 2560b3aac..ba67e38e4 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
@@ -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;
}
diff --git a/status.xml b/status.xml
index 0dc2548ae..f618b0074 100644
--- a/status.xml
+++ b/status.xml
@@ -28,6 +28,9 @@
+
+ Added full support for keep-with-previous on fo:table-row and in fo:table-cell elements.
+
Turned on XInclude processing for the main source given on the command line.
diff --git a/test/layoutengine/standard-testcases/table-cell_block_keep-with-next.xml b/test/layoutengine/standard-testcases/table-cell_block_keep-with-next.xml
index 45df7e337..b4eb7aead 100644
--- a/test/layoutengine/standard-testcases/table-cell_block_keep-with-next.xml
+++ b/test/layoutengine/standard-testcases/table-cell_block_keep-with-next.xml
@@ -32,9 +32,8 @@
block1
-
-
-
+
+
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
index 000000000..e35f343ad
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-cell_keep-together.xml
@@ -0,0 +1,209 @@
+
+
+
+
+
+
+ This test checks that keep-together works on blocks in table-cells.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1. Before the table
+
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+ Cell 3.1 Line 1
+ Cell 3.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 2. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+
+ Cell 2.2 Line 1
+ Cell 2.2 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 3. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+
+ After the table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
index 000000000..f4cb03a01
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-cell_keep-with-next.xml
@@ -0,0 +1,376 @@
+
+
+
+
+
+
+ This test checks that keep-with-next works on blocks in table-cells.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+ Cell 3.1 Line 1
+ Cell 3.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 2. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 3. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 4. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.2 Line 1
+ Cell 2.2 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
index 000000000..2ad4dd449
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-cell_keep-with-previous.xml
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+ This test checks that keep-with-previous works on blocks in table-cells.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+ Cell 3.1 Line 1
+ Cell 3.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 2. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 3. Before the table
+ Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
index 000000000..0e2867b2e
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-row_keep-together_2.xml
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+ This test checks that keep-together works on table-row.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+ Cell 3.1 Line 1
+ Cell 3.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 2. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 3. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.2 Line 1
+ Cell 2.2 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/layoutengine/standard-testcases/table-row_keep-with-next.xml b/test/layoutengine/standard-testcases/table-row_keep-with-next.xml
index 5ceedb932..3657f2a90 100644
--- a/test/layoutengine/standard-testcases/table-row_keep-with-next.xml
+++ b/test/layoutengine/standard-testcases/table-row_keep-with-next.xml
@@ -32,9 +32,8 @@
block1
-
-
-
+
+
@@ -73,7 +72,7 @@
-
+
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
index 000000000..ffd4aafb9
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-row_keep-with-next_3.xml
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+ This test checks that keep-with-next works on table-row.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 2. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.2 Line 1
+ Cell 2.2 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/layoutengine/standard-testcases/table-row_keep-with-previous.xml b/test/layoutengine/standard-testcases/table-row_keep-with-previous.xml
index 466634552..34a8be4c1 100644
--- a/test/layoutengine/standard-testcases/table-row_keep-with-previous.xml
+++ b/test/layoutengine/standard-testcases/table-row_keep-with-previous.xml
@@ -31,10 +31,9 @@
- block1
-
-
-
+ block1
+
+
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
index 000000000..e6131308a
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table-row_keep-with-previous_2.xml
@@ -0,0 +1,254 @@
+
+
+
+
+
+
+ This test checks that keep-with-previous works on table-row.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+ Cell 3.1 Line 1
+ Cell 3.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 2. Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ 3. Before the table
+ Before the table
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/layoutengine/standard-testcases/table_break-before_break-after.xml b/test/layoutengine/standard-testcases/table_break-before_break-after.xml
index 31c1fd8cb..0ec629d87 100644
--- a/test/layoutengine/standard-testcases/table_break-before_break-after.xml
+++ b/test/layoutengine/standard-testcases/table_break-before_break-after.xml
@@ -55,11 +55,9 @@
-
+
+
+
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
index 000000000..0c3d400a0
--- /dev/null
+++ b/test/layoutengine/standard-testcases/table_keep-together_2.xml
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+ This test checks that keep-together works on tables.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ First line
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+ First line
+
+
+
+
+
+ Cell 1.1 Line 1
+ Cell 1.1 Line 2
+
+
+ Cell 1.2 Line 1
+ Cell 1.2 Line 2
+
+
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+ Cell 2.1 Line 1
+ Cell 2.1 Line 2
+
+
+
+
+ After the table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--
2.39.5