aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVincent Hennebert <vhennebert@apache.org>2007-11-13 16:24:32 +0000
committerVincent Hennebert <vhennebert@apache.org>2007-11-13 16:24:32 +0000
commit5675e7ef51aeb29596ab0f6e5f6af6e485759d8f (patch)
treeb179d94d2bbf036fa109023ada64bf2bf792a924 /src
parent6173b3f00ff40c590420cc4119bb3a486cff2b27 (diff)
downloadxmlgraphics-fop-5675e7ef51aeb29596ab0f6e5f6af6e485759d8f.tar.gz
xmlgraphics-fop-5675e7ef51aeb29596ab0f6e5f6af6e485759d8f.zip
Moved the creation of grid units to the FO tree building stage. Brought a few improvements along with the move:
- bugfix: border-resolution for border-end on row-spanning cells was wrong - bugfix: in case of missing cells the border-end of the table was applied to an inner cell, instead of the cell in the last column (but missing cells aren't painted yet :-\) - bugfix: in collapsing-border model, border-before and -after specified on table-column were applied to every cell of the column, instead of only the first and the last ones - border resolution is now made progressively when possible, and no longer triggers the fetching of all the rows of the table Added testcases for the border conflict resolution (between the various elements of a table and not only the cells) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@594571 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r--src/java/org/apache/fop/fo/flow/RetrieveMarker.java13
-rw-r--r--src/java/org/apache/fop/fo/flow/table/BorderResolver.java56
-rw-r--r--src/java/org/apache/fop/fo/flow/table/BorderSpecification.java71
-rw-r--r--src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java169
-rw-r--r--src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java148
-rw-r--r--src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java98
-rw-r--r--src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java44
-rw-r--r--src/java/org/apache/fop/fo/flow/table/Table.java48
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableBody.java67
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCell.java19
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCellContainer.java7
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableColumn.java24
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFObj.java60
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFooter.java10
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableHeader.java5
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableRow.java23
-rw-r--r--src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java82
-rwxr-xr-xsrc/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java8
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java94
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java299
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/EffRow.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java48
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/GridUnit.java227
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java20
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java106
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java113
26 files changed, 1153 insertions, 712 deletions
diff --git a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java
index f2679d04b..7356bc72e 100644
--- a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java
+++ b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java
@@ -23,12 +23,13 @@ import java.util.Iterator;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOText;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.FObjMixed;
-import org.apache.fop.fo.FOText;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableFObj;
import org.xml.sax.Locator;
/**
@@ -126,6 +127,12 @@ public class RetrieveMarker extends FObjMixed {
getLocator(),
pList,
newPropertyList);
+ if (newChild instanceof TableFObj) {
+ // TODO calling startOfNode (and endOfNode, below) on other fobjs may
+ // have undesirable side-effects. This is really ugly and will need to
+ // be addressed sooner or later
+ ((TableFObj) newChild).startOfNode();
+ }
addChildTo(newChild, (FObj) newParent);
if (newChild.getNameId() == FO_TABLE) {
Table t = (Table) child;
@@ -138,6 +145,10 @@ public class RetrieveMarker extends FObjMixed {
}
cloneSubtree(child.getChildNodes(), newChild,
marker, newPropertyList);
+ if (newChild instanceof TableFObj) {
+ // TODO this is ugly
+ ((TableFObj) newChild).endOfNode();
+ }
} else if (child instanceof FOText) {
FOText ft = (FOText) newChild;
ft.bind(parentPropertyList);
diff --git a/src/java/org/apache/fop/fo/flow/table/BorderResolver.java b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
new file mode 100644
index 000000000..0a8f3d39e
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
@@ -0,0 +1,56 @@
+/*
+ * 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$ */
+
+package org.apache.fop.fo.flow.table;
+
+import java.util.List;
+
+/**
+ * A class dedicated to the resolution of borders in tables. It receives a series of
+ * events as the table is parsed and performs border resolution accordingly.
+ */
+interface BorderResolver {
+
+ /**
+ * Receives notification of the end of a row.
+ *
+ * @param row the row that has just been finished
+ * @param container the FO element holding the given row
+ */
+ void endRow(List/*<GridUnit>*/ row, TableCellContainer container);
+
+ /**
+ * Receives notification of the start of a table-header/footer/body.
+ *
+ * @param part the part that has started
+ */
+ void startPart(TableBody part);
+
+ /**
+ * Receives notification of the end of a table-header/footer/body.
+ *
+ * @param part the part that has ended
+ */
+ void endPart(TableBody part);
+
+ /**
+ * Receives notification of the end of the table.
+ */
+ void endTable();
+}
diff --git a/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java b/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
new file mode 100644
index 000000000..214f9be07
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
@@ -0,0 +1,71 @@
+/*
+ * 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$ */
+
+package org.apache.fop.fo.flow.table;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
+
+/**
+ * A border's informations, along with the FO element which declared it. Used for border
+ * resolution in the collapsing-border model.
+ */
+public/*TODO*/ class BorderSpecification {
+
+ private BorderInfo borderInfo;
+
+ private int holder;
+
+ /**
+ * Creates a new border specification.
+ *
+ * @param borderInfo the border's informations
+ * @param holder the FO element declaring this border
+ */
+ public/*TODO*/ BorderSpecification(BorderInfo borderInfo, int holder) {
+ this.borderInfo = borderInfo;
+ this.holder = holder;
+ }
+
+ /**
+ * Returns this border's informations.
+ *
+ * @return this border's informations
+ */
+ public/*TODO*/ BorderInfo getBorderInfo() {
+ return borderInfo;
+ }
+
+ /**
+ * Returns the FO element declaring this border.
+ *
+ * @return one of {@link Constants#FO_TABLE}, {@link Constants#FO_TABLE_COLUMN},
+ * {@link Constants#FO_TABLE_HEADER}, {@link Constants#FO_TABLE_FOOTER},
+ * {@link Constants#FO_TABLE_BODY}, {@link Constants#FO_TABLE_ROW},
+ * {@link Constants#FO_TABLE_CELL}
+ */
+ public/*TODO*/ int getHolder() {
+ return holder;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "{" + borderInfo + ", " + holder + "}";
+ }
+}
diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
new file mode 100644
index 000000000..732acb6be
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
@@ -0,0 +1,169 @@
+/*
+ * 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$ */
+
+package org.apache.fop.fo.flow.table;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.layoutmgr.table.GridUnit;
+
+/**
+ * A class that implements the border-collapsing model.
+ */
+class CollapsingBorderResolver implements BorderResolver {
+
+ private Table table;
+
+ private List previousRow;
+
+ /**
+ * The flow of rows is interrupted by the table-footer. Save the header's last row (if
+ * any) for resolution between it and the body's first row.
+ */
+ private List previousRowSave;
+
+ private TableBody currentTablePart;
+
+ private boolean firstInTable;
+
+ private boolean firstInPart;
+
+ private List footerFirstRow;
+
+ private List footerLastRow;
+
+ private boolean inFooter;
+
+ CollapsingBorderResolver(Table table) {
+ this.table = table;
+ firstInTable = true;
+ }
+
+ /** {@inheritDoc} */
+ public void endRow(List row, TableCellContainer container) {
+ // Resolve before- and after-borders for the table-row
+ if (container instanceof TableRow) {
+ TableRow tableRow = (TableRow) container;
+ for (Iterator iter = row.iterator(); iter.hasNext();) {
+ GridUnit gu = (GridUnit) iter.next();
+ if (gu.getRowSpanIndex() == 0) {
+ gu.resolveBorder(CommonBorderPaddingBackground.BEFORE, tableRow);
+ }
+ if (gu.isLastGridUnitRowSpan()) {
+ gu.resolveBorder(CommonBorderPaddingBackground.AFTER, tableRow);
+ }
+ }
+ }
+ if (inFooter) {
+ if (footerFirstRow == null) {
+ footerFirstRow = row;
+ }
+ footerLastRow = row;
+ } else if (firstInTable) {
+ // Resolve border-before for the first row in the table
+ for (int i = 0; i < row.size(); i++) {
+ TableColumn column = table.getColumn(i);
+ ((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE, column);
+ }
+ firstInTable = false;
+ }
+ if (firstInPart) {
+ // Resolve border-before for the first row in the part
+ for (int i = 0; i < row.size(); i++) {
+ ((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE,
+ currentTablePart);
+ }
+ firstInPart = false;
+ }
+ if (previousRow != null) {
+ // Resolve after/before borders between rows
+ for (int i = 0; i < row.size(); i++) {
+ GridUnit gu = (GridUnit) row.get(i);
+ if (gu.getRowSpanIndex() == 0) {
+ GridUnit beforeGU = (GridUnit) previousRow.get(i);
+ gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE);
+ }
+ }
+ }
+ // Resolve start/end borders in the row
+ Iterator guIter = row.iterator();
+ GridUnit gu = (GridUnit) guIter.next();
+ gu.resolveBorder(CommonBorderPaddingBackground.START, container);
+ while (guIter.hasNext()) {
+ GridUnit guEnd = (GridUnit) guIter.next();
+ if (gu.isLastGridUnitColSpan()) {
+ gu.resolveBorder(guEnd, CommonBorderPaddingBackground.END);
+ }
+ gu = guEnd;
+ }
+ gu.resolveBorder(CommonBorderPaddingBackground.END, container);
+
+ previousRow = row;
+ }
+
+ /** {@inheritDoc} */
+ public void startPart(TableBody part) {
+ firstInPart = true;
+ currentTablePart = part;
+ if (part.isTableFooter()) {
+ inFooter = true;
+ previousRowSave = previousRow;
+ previousRow = null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endPart(TableBody part) {
+ // Resolve border-after for the last row in the part
+ for (int i = 0; i < previousRow.size(); i++) {
+ ((GridUnit) previousRow.get(i))
+ .resolveBorder(CommonBorderPaddingBackground.AFTER, part);
+ }
+ if (inFooter) {
+ inFooter = false;
+ previousRow = previousRowSave;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void endTable() {
+ if (footerFirstRow != null) {
+ // Resolve after/before border between the last row of table-body and the
+ // first row of table-footer
+ for (int i = 0; i < footerFirstRow.size(); i++) {
+ GridUnit gu = (GridUnit) footerFirstRow.get(i);
+ GridUnit beforeGU = (GridUnit) previousRow.get(i);
+ gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE);
+ }
+ }
+ List lastRow;
+ if (footerLastRow != null) {
+ lastRow = footerLastRow;
+ } else {
+ lastRow = previousRow;
+ }
+ // Resolve border-after for the last row of the table
+ for (int i = 0; i < lastRow.size(); i++) {
+ TableColumn column = table.getColumn(i);
+ ((GridUnit) lastRow.get(i)).resolveBorder(CommonBorderPaddingBackground.AFTER, column);
+ }
+ }
+}
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 22e5c02b8..602ae84a6 100644
--- a/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
@@ -19,6 +19,15 @@
package org.apache.fop.fo.flow.table;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.layoutmgr.table.EmptyGridUnit;
+import org.apache.fop.layoutmgr.table.GridUnit;
+import org.apache.fop.layoutmgr.table.PrimaryGridUnit;
+
/**
* A row group builder optimised for a fixed number of columns, known before the parsing
@@ -26,10 +35,149 @@ package org.apache.fop.fo.flow.table;
*/
class FixedColRowGroupBuilder extends RowGroupBuilder {
+ /** Number of columns in the corresponding table. */
+ private int numberOfColumns;
+
+ /** 0-based, index in the row group. */
+ private int currentRowIndex;
+
+ /** The rows belonging to this row group. List of List of {@link GridUnit}s. */
+ private List/*<List<GridUnit>>*/ rows;
+
+ private boolean firstInTable = true;
+
+ private boolean firstInPart = true;
+
+ /** The last encountered row. This is the last row of the table if it has no footer. */
+ private List lastRow;
+
+ private BorderResolver borderResolver;
+
+ private boolean inFooter;
+
+ private List lastFooterRow;
FixedColRowGroupBuilder(Table t) {
super(t);
numberOfColumns = t.getNumberOfColumns();
+ if (t.isSeparateBorderModel()) {
+ borderResolver = new SeparateBorderResolver();
+ } else {
+ borderResolver = new CollapsingBorderResolver(t);
+ }
+ initialize();
+ }
+
+ /**
+ * Prepares this builder for creating a new row group.
+ */
+ private void initialize() {
+ rows = new ArrayList();
+ currentRowIndex = 0;
}
+ /** {@inheritDoc} */
+ void addTableCell(TableCell cell) {
+ for (int i = rows.size(); i < currentRowIndex + cell.getNumberRowsSpanned(); i++) {
+ List effRow = new ArrayList(numberOfColumns);
+ for (int j = 0; j < numberOfColumns; j++) {
+ effRow.add(null);
+ }
+ rows.add(effRow);
+ }
+ int columnIndex = cell.getColumnNumber() - 1;
+ PrimaryGridUnit pgu = new PrimaryGridUnit(cell, table.getColumn(columnIndex), columnIndex,
+ currentRowIndex);
+ 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, table.getColumn(columnIndex + j),
+ columnIndex + j, j, 0);
+ row.set(columnIndex + j, gu);
+ cellRow[j] = gu;
+ }
+ pgu.addRow(cellRow);
+ for (int i = 1; i < cell.getNumberRowsSpanned(); i++) {
+ row = (List) rows.get(currentRowIndex + i);
+ cellRow = new GridUnit[cell.getNumberColumnsSpanned()];
+ for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) {
+ GridUnit gu = new GridUnit(pgu, table.getColumn(columnIndex + j),
+ columnIndex + j, j, i);
+ row.set(columnIndex + j, gu);
+ cellRow[j] = gu;
+ }
+ pgu.addRow(cellRow);
+ }
+ }
+
+ private static void setFlagForCols(int flag, List row) {
+ for (ListIterator iter = row.listIterator(); iter.hasNext();) {
+ ((GridUnit) iter.next()).setFlag(flag);
+ }
+ }
+
+ /** {@inheritDoc} */
+ void endRow(TableCellContainer container) {
+ List currentRow = (List) rows.get(currentRowIndex);
+ lastRow = currentRow;
+ // Fill gaps with empty grid units
+ for (int i = 0; i < numberOfColumns; i++) {
+ if (currentRow.get(i) == null) {
+ currentRow.set(i, new EmptyGridUnit(table, currentRowIndex, i));
+ }
+ }
+ borderResolver.endRow(currentRow, container);
+ ((GridUnit) currentRow.get(0)).setFlag(GridUnit.IN_FIRST_COLUMN);
+ ((GridUnit) currentRow.get(numberOfColumns - 1)).setFlag(GridUnit.IN_LAST_COLUMN);
+ if (inFooter) {
+ lastFooterRow = currentRow;
+ } else if (firstInTable) {
+ setFlagForCols(GridUnit.FIRST_IN_TABLE, currentRow);
+ firstInTable = false;
+ }
+ if (firstInPart) {
+ setFlagForCols(GridUnit.FIRST_IN_PART, currentRow);
+ firstInPart = false;
+ }
+ if (currentRowIndex == rows.size() - 1) {
+ // Means that the current row has no cell spanning over following rows
+ container.getTablePart().addRowGroup(rows);
+ initialize();
+ } else {
+ currentRowIndex++;
+ }
+ }
+
+ /** {@inheritDoc} */
+ void startTablePart(TableBody part) {
+ firstInPart = true;
+ inFooter = part.isTableFooter();
+ borderResolver.startPart(part);
+ }
+
+ /** {@inheritDoc} */
+ void endTablePart(TableBody tableBody) throws ValidationException {
+ if (rows.size() > 0) {
+ throw new ValidationException(
+ "A table-cell is spanning more rows than available in its parent element.");
+ }
+ setFlagForCols(GridUnit.LAST_IN_PART, lastRow);
+ borderResolver.endPart(tableBody);
+ inFooter = false;
+ }
+
+ /** {@inheritDoc} */
+ void endTable(TableBody lastTablePart) {
+ List lastTableRow;
+ if (lastFooterRow != null) {
+ lastTableRow = lastFooterRow;
+ } else {
+ lastTableRow = lastRow;
+ }
+ setFlagForCols(GridUnit.LAST_IN_TABLE, lastTableRow);
+ borderResolver.endTable();
+ }
}
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 2f9a009c2..7f09f7d46 100644
--- a/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
@@ -19,12 +19,8 @@
package org.apache.fop.fo.flow.table;
-import java.util.ArrayList;
-import java.util.List;
-
import org.apache.fop.fo.ValidationException;
import org.apache.fop.layoutmgr.table.GridUnit;
-import org.apache.fop.layoutmgr.table.PrimaryGridUnit;
/**
* A class that creates groups of rows belonging to a same set of spans. The first row of
@@ -34,16 +30,7 @@ import org.apache.fop.layoutmgr.table.PrimaryGridUnit;
*/
abstract class RowGroupBuilder {
- /** Number of columns in the corresponding table. */
- protected int numberOfColumns;
-
- /** 0-based, index in the row group. */
- private int currentRowIndex;
-
- private Table table;
-
- /** The rows belonging to this row group. List of List of {@link GridUnit}s. */
- protected List rows;
+ protected Table table;
/**
* Creates and initialises a new builder for the given table.
@@ -52,81 +39,48 @@ abstract class RowGroupBuilder {
*/
protected RowGroupBuilder(Table t) {
table = t;
- initialize();
}
+
/**
- * Prepares this builder for creating a new row group.
+ * Adds a table-cell to the current row-group, creating {@link GridUnit}s accordingly.
+ *
+ * @param cell the cell to add
*/
- private void initialize() {
- rows = new ArrayList();
- currentRowIndex = 0;
- }
+ abstract void addTableCell(TableCell cell);
/**
- * Adds a table-cell to the row-group, creating {@link GridUnit}s accordingly.
+ * 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 (i.e., the given container itself or its parent if this is a table-row) will
+ * be called
*
- * @param cell
+ * @param container the parent element of the current row
*/
- void addTableCell(TableCell cell) {
- for (int i = rows.size(); i < currentRowIndex + cell.getNumberRowsSpanned(); i++) {
- List effRow = new ArrayList(numberOfColumns);
- for (int j = 0; j < numberOfColumns; j++) {
- effRow.add(null);
- }
- rows.add(effRow);
- }
- int columnIndex = cell.getColumnNumber() - 1;
- PrimaryGridUnit pgu = new PrimaryGridUnit(cell, table.getColumn(columnIndex), columnIndex,
- currentRowIndex);
- List row = (List) rows.get(currentRowIndex);
- row.set(columnIndex, pgu);
- for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
- row.set(j + columnIndex,
- new GridUnit(pgu, table.getColumn(columnIndex + j), columnIndex + j, j));
- }
- for (int i = 1; i < cell.getNumberRowsSpanned(); i++) {
- row = (List) rows.get(currentRowIndex + i);
- for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) {
- row.set(j + columnIndex,
- new GridUnit(pgu, table.getColumn(columnIndex + j), columnIndex + j, j));
- }
- }
-
- }
+ abstract void endRow(TableCellContainer container);
/**
- * Signals that a table row has just ended, potentially finishing the current row
- * group.
+ * Receives notification of the start of a table-header/footer/body.
*
- * @param body the table-body containing the row. Its
- * {@link TableBody#addRowGroup(List)} method will be called if the current row group
- * is finished.
+ * @param part the part being started
*/
- void signalRowEnd(TableBody body) {
- if (currentRowIndex == rows.size() - 1) {
- // Means that the current row has no cell spanning over following rows
- body.addRowGroup(rows);
- initialize();
- } else {
- currentRowIndex++;
- }
- }
+ abstract void startTablePart(TableBody part);
/**
- * Signals that the end of a table-header/footer/body has been reached. The current
+ * Receives notification of the end of a table-header/footer/body. The current
* row-group is checked for emptiness. This row group builder is reset for handling
* further possible table parts.
*
- * @param tableBody the table part being finished
- * @throws ValidationException if a cell is spanning further than the given table part
+ * @param tableBody the table part being ended
+ * @throws ValidationException if a row-spanning cell overflows the given table part
*/
- void signalEndOfPart(TableBody tableBody) throws ValidationException {
- if (rows.size() > 0) {
- throw new ValidationException(
- "A table-cell is spanning more rows than available in its parent element.");
- }
- initialize();
- }
+ abstract void endTablePart(TableBody tableBody) throws ValidationException;
+ /**
+ * 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;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
new file mode 100644
index 000000000..37e3cb6e8
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
@@ -0,0 +1,44 @@
+/*
+ * 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$ */
+
+package org.apache.fop.fo.flow.table;
+
+import java.util.List;
+
+/**
+ * A resolver for the separate-border model. Basically this class does nothing.
+ */
+class SeparateBorderResolver implements BorderResolver {
+
+ /** {@inheritDoc} */
+ public void endRow(List row, TableCellContainer container) {
+ }
+
+ /** {@inheritDoc} */
+ public void startPart(TableBody part) {
+ }
+
+ /** {@inheritDoc} */
+ public void endPart(TableBody part) {
+ }
+
+ /** {@inheritDoc} */
+ public void endTable() {
+ }
+}
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 07fc95f7e..b2f240c72 100644
--- a/src/java/org/apache/fop/fo/flow/table/Table.java
+++ b/src/java/org/apache/fop/fo/flow/table/Table.java
@@ -20,7 +20,6 @@
package org.apache.fop.fo.flow.table;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import org.apache.fop.apps.FOPException;
@@ -154,7 +153,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startTable(this);
}
@@ -211,7 +210,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
if (!tableBodyFound) {
missingChildElementError(
@@ -219,6 +218,11 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
+ ",table-body+)");
}
if (!inMarker()) {
+ if (tableFooter != null) {
+ rowGroupBuilder.endTable(tableFooter);
+ } else {
+ rowGroupBuilder.endTable((TableBody) getChildNodes().lastNode());
+ }
/* clean up */
for (int i = columns.size(); --i >= 0;) {
TableColumn col = (TableColumn) columns.get(i);
@@ -278,6 +282,13 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
}
}
+ protected void setCollapsedBorders() {
+ createBorder(CommonBorderPaddingBackground.START);
+ createBorder(CommonBorderPaddingBackground.END);
+ createBorder(CommonBorderPaddingBackground.BEFORE);
+ createBorder(CommonBorderPaddingBackground.AFTER);
+ }
+
private void finalizeColumns() throws FOPException {
for (int i = 0; i < columns.size(); i++) {
if (columns.get(i) == null) {
@@ -305,32 +316,6 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
for (int i = columns.size() + 1; i <= columnNumber; i++) {
columns.add(createImplicitColumn(i));
}
- ((VariableColRowGroupBuilder) rowGroupBuilder).ensureNumberOfColumns(columnNumber);
- if (tableHeader != null) {
- for (Iterator iter = tableHeader.getRowGroups().iterator(); iter.hasNext();) {
- VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(),
- columnNumber);
- }
- }
- if (tableFooter != null) {
- for (Iterator iter = tableFooter.getRowGroups().iterator(); iter.hasNext();) {
- VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(),
- columnNumber);
- }
- }
- FONodeIterator bodyIter = getChildNodes();
- if (bodyIter != null) {
- while (bodyIter.hasNext()) {
- FONode node = bodyIter.nextNode();
- if (node instanceof TableBody) { // AFAIK, may be a marker
- for (Iterator iter = ((TableBody) node).getRowGroups().iterator();
- iter.hasNext();) {
- VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(),
- columnNumber);
- }
- }
- }
- }
}
private TableColumn createImplicitColumn(int colNumber)
@@ -342,6 +327,9 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
implicitColumn.bind(pList);
implicitColumn.setColumnWidth(new TableColLength(1.0, implicitColumn));
implicitColumn.setColumnNumber(colNumber);
+ if (!isSeparateBorderModel()) {
+ implicitColumn.setCollapsedBorders(collapsingBorderModel); // TODO
+ }
return implicitColumn;
}
@@ -399,7 +387,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
* @param index index of the column to be retrieved, 0-based
* @return the corresponding column (may be an implicitly created column)
*/
- TableColumn getColumn(int index) {
+ public/*TODO*/ TableColumn getColumn(int index) {
return (TableColumn) columns.get(index);
}
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 7e4ee2fb0..ece1f0049 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableBody.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java
@@ -50,15 +50,15 @@ public class TableBody extends TableCellContainer {
protected boolean tableRowsFound = false;
protected boolean tableCellsFound = false;
- /**
- * used for initial values of column-number property
- */
private boolean firstRow = true;
private boolean rowsStarted = false;
private boolean lastCellEndsRow = true;
+ /** The last encountered table-row. */
+ private TableRow lastRow;
+
private List rowGroups = new LinkedList();
/**
@@ -101,14 +101,15 @@ public class TableBody extends TableCellContainer {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
getFOEventHandler().startBody(this);
}
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
if (!inMarker()) {
pendingSpans = null;
@@ -130,16 +131,25 @@ public class TableBody extends TableCellContainer {
}
}
+ /** {@inheritDoc} */
+ TableBody getTablePart() {
+ return this;
+ }
+
protected void finishLastRowGroup() throws ValidationException {
- RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
- if (tableRowsFound || !lastCellEndsRow) {
- rowGroupBuilder.signalRowEnd(this);
- }
- try {
- rowGroupBuilder.signalEndOfPart(this);
- } catch (ValidationException e) {
- e.setLocator(locator);
- throw e;
+ if (!inMarker()) {
+ RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
+ if (tableRowsFound) {
+ rowGroupBuilder.endRow(lastRow);
+ } else if (!lastCellEndsRow) {
+ rowGroupBuilder.endRow(this);
+ }
+ try {
+ rowGroupBuilder.endTablePart(this);
+ } catch (ValidationException e) {
+ e.setLocator(locator);
+ throw e;
+ }
}
}
@@ -184,13 +194,19 @@ public class TableBody extends TableCellContainer {
if (!inMarker()) {
switch (child.getNameId()) {
case FO_TABLE_ROW:
- if (rowsStarted) {
+ if (!rowsStarted) {
+ getTable().getRowGroupBuilder().startTablePart(this);
+ } else {
columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().signalRowEnd(this);
+ getTable().getRowGroupBuilder().endRow(lastRow);
}
rowsStarted = true;
+ lastRow = (TableRow) child;
break;
case FO_TABLE_CELL:
+ if (!rowsStarted) {
+ getTable().getRowGroupBuilder().startTablePart(this);
+ }
rowsStarted = true;
TableCell cell = (TableCell) child;
addTableCellChild(cell, firstRow);
@@ -198,7 +214,7 @@ public class TableBody extends TableCellContainer {
if (lastCellEndsRow) {
firstRow = false;
columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().signalRowEnd(this);
+ getTable().getRowGroupBuilder().endRow(this);
}
break;
default:
@@ -208,11 +224,20 @@ public class TableBody extends TableCellContainer {
super.addChildNode(child);
}
+ /** {inheritDoc} */
+ protected void setCollapsedBorders() {
+ Table table = (Table) parent;
+ createBorder(CommonBorderPaddingBackground.START, table);
+ createBorder(CommonBorderPaddingBackground.END, table);
+ createBorder(CommonBorderPaddingBackground.BEFORE);
+ createBorder(CommonBorderPaddingBackground.AFTER);
+ }
+
void addRowGroup(List rowGroup) {
rowGroups.add(rowGroup);
}
- List getRowGroups() {
+ public List getRowGroups() {
return rowGroups;
}
@@ -235,6 +260,10 @@ public class TableBody extends TableCellContainer {
return FO_TABLE_BODY;
}
+ protected boolean isTableFooter() {
+ return false;
+ }
+
/**
* @param obj table row in question
* @return true if the given table row is the first row of this body.
@@ -249,7 +278,7 @@ public class TableBody extends TableCellContainer {
firstRow = false;
if (!lastCellEndsRow) {
columnNumberManager.prepareForNextRow(pendingSpans);
- getTable().getRowGroupBuilder().signalRowEnd(this);
+ getTable().getRowGroupBuilder().endRow(this);
}
}
rowsStarted = true;
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java
index 34c6266a7..f85d0e97e 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCell.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java
@@ -90,7 +90,7 @@ public class TableCell extends TableFObj {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startCell(this);
}
@@ -100,7 +100,7 @@ public class TableCell extends TableFObj {
* FOEventHandler that we are at the end of the flow.
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
if (!blockItemFound) {
if (getUserAgent().validateStrictly()) {
missingChildElementError("marker* (%block;)+");
@@ -135,6 +135,21 @@ public class TableCell extends TableFObj {
}
/** {@inheritDoc} */
+ protected void setCollapsedBorders() {
+ createBorder(CommonBorderPaddingBackground.BEFORE);
+ createBorder(CommonBorderPaddingBackground.AFTER);
+ Table table = getTable();
+ if (table.hasExplicitColumns()) {
+ TableColumn col = table.getColumn(getColumnNumber() - 1);
+ createBorder(CommonBorderPaddingBackground.START, col);
+ createBorder(CommonBorderPaddingBackground.END, col);
+ } else {
+ createBorder(CommonBorderPaddingBackground.START);
+ createBorder(CommonBorderPaddingBackground.END);
+ }
+ }
+
+ /** {@inheritDoc} */
public boolean generatesReferenceAreas() {
return true;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
index ebb066c5c..7c91be351 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
@@ -93,6 +93,13 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb
}
}
+ /**
+ * Returns the enclosing table-header/footer/body of this container.
+ *
+ * @return <code>this</code> for TableBody, or the parent element for TableRow
+ */
+ abstract TableBody getTablePart();
+
/** {@inheritDoc} */
public ColumnNumberManager getColumnNumberManager() {
return columnNumberManager;
diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java
index aa2dfcb0a..aeb401893 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java
@@ -31,6 +31,7 @@ import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.TableColLength;
+import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
/**
* Class modelling the fo:table-column object.
@@ -114,14 +115,27 @@ public class TableColumn extends TableFObj {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
getFOEventHandler().startColumn(this);
}
- /**
- * {@inheritDoc}
- */
- protected void endOfNode() throws FOPException {
+ void setCollapsedBorders(CollapsingBorderModel collapsingBorderModel) {
+ this.collapsingBorderModel = collapsingBorderModel;
+ setCollapsedBorders();
+ }
+
+ /** {@inheritDoc} */
+ protected void setCollapsedBorders() {
+ Table table = (Table) parent;
+ createBorder(CommonBorderPaddingBackground.BEFORE, table);
+ createBorder(CommonBorderPaddingBackground.AFTER, table);
+ createBorder(CommonBorderPaddingBackground.START);
+ createBorder(CommonBorderPaddingBackground.END);
+ }
+
+ /** {@inheritDoc} */
+ public void endOfNode() throws FOPException {
getFOEventHandler().endColumn(this);
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
index 53995464b..984f242f2 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
@@ -30,6 +30,7 @@ import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.NumberProperty;
import org.apache.fop.fo.properties.Property;
+import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
/**
* Common base class for table-related FOs
@@ -41,6 +42,10 @@ public abstract class TableFObj extends FObj {
private Numeric borderEndPrecedence;
private Numeric borderStartPrecedence;
+ public/*TODO*/ BorderSpecification[] resolvedBorders = new BorderSpecification[4]; // TODO
+
+ CollapsingBorderModel collapsingBorderModel;
+
/**
* Main constructor
*
@@ -122,9 +127,7 @@ public abstract class TableFObj extends FObj {
super(propId);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public Property make(PropertyList propertyList)
throws PropertyException {
FObj fo = propertyList.getFObj();
@@ -189,4 +192,55 @@ public abstract class TableFObj extends FObj {
return p;
}
}
+
+ /** {@inheritDoc} */
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
+ Table table = getTable();
+ if (!inMarker() && !table.isSeparateBorderModel()) {
+ collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table
+ .getBorderCollapse());
+ resolvedBorders = new BorderSpecification[4];
+ setCollapsedBorders();
+ }
+ }
+
+ /*
+ * TODO made public so that RetrieveMarker can access it.
+ */
+ /** {@inheritDoc} */
+ public void endOfNode() throws FOPException {
+ super.endOfNode();
+ }
+
+ /**
+ * Prepares the borders of this element if the collapsing-border model is in use.
+ * Conflict resolution with parent elements is done where applicable.
+ */
+ protected abstract void setCollapsedBorders();
+
+ /**
+ * Creates a BorderSpecification from the border set on the given side. If no border
+ * is set, a BorderSpecification with border-style none is created.
+ *
+ * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END
+ */
+ protected void createBorder(int side) {
+ resolvedBorders[side] = new BorderSpecification(getCommonBorderPaddingBackground()
+ .getBorderInfo(side), getNameId());
+ }
+
+ /**
+ * Creates a BorderSpecification from the border set on the given side, performing
+ * conflict resolution with the same border on the given object.
+ *
+ * @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END
+ * @param competitor a parent table element whose side coincides with the given side
+ * on this element
+ */
+ protected void createBorder(int side, TableFObj competitor) {
+ createBorder(side);
+ resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side],
+ competitor.resolvedBorders[side]);
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableFooter.java b/src/java/org/apache/fop/fo/flow/table/TableFooter.java
index a7ee21406..e886d2ee1 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableFooter.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableFooter.java
@@ -39,14 +39,15 @@ public class TableFooter extends TableBody {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
//getFOEventHandler().startBody(this);
}
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
// getFOEventHandler().endFooter(this);
if (!(tableRowsFound || tableCellsFound)) {
missingChildElementError("marker* (table-row+|table-cell+)");
@@ -65,4 +66,9 @@ public class TableFooter extends TableBody {
public int getNameId() {
return FO_TABLE_FOOTER;
}
+
+ /** {@inheritDoc} */
+ protected boolean isTableFooter() {
+ return true;
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java
index bc9d88952..01ada2aa7 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java
@@ -39,14 +39,15 @@ public class TableHeader extends TableBody {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
+ super.startOfNode();
//getFOEventHandler().startHeader(this);
}
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
// getFOEventHandler().endHeader(this);
if (!(tableRowsFound || tableCellsFound)) {
missingChildElementError("marker* (table-row+|table-cell+)");
diff --git a/src/java/org/apache/fop/fo/flow/table/TableRow.java b/src/java/org/apache/fop/fo/flow/table/TableRow.java
index edc8d13df..a025f92fd 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableRow.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableRow.java
@@ -97,7 +97,7 @@ public class TableRow extends TableCellContainer {
/**
* {@inheritDoc}
*/
- protected void startOfNode() throws FOPException {
+ public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startRow(this);
}
@@ -105,7 +105,7 @@ public class TableRow extends TableCellContainer {
/**
* {@inheritDoc}
*/
- protected void endOfNode() throws FOPException {
+ public void endOfNode() throws FOPException {
if (firstChild == null) {
missingChildElementError("(table-cell+)");
}
@@ -128,6 +128,25 @@ public class TableRow extends TableCellContainer {
}
}
+ /** {@inheritDoc} */
+ TableBody getTablePart() {
+ return (TableBody) parent;
+ }
+
+ /** {@inheritDoc} */
+ boolean isTableRow() {
+ return true;
+ }
+
+ /** {inheritDoc} */
+ protected void setCollapsedBorders() {
+ TableBody body = (TableBody) parent;
+ createBorder(CommonBorderPaddingBackground.START, body);
+ createBorder(CommonBorderPaddingBackground.END, body);
+ createBorder(CommonBorderPaddingBackground.BEFORE);
+ createBorder(CommonBorderPaddingBackground.AFTER);
+ }
+
/** @return the "break-after" property. */
public int getBreakAfter() {
return breakAfter;
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 53b7bfca1..e35ad5c27 100644
--- a/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
+++ b/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
@@ -19,9 +19,12 @@
package org.apache.fop.fo.flow.table;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
-import org.apache.fop.layoutmgr.table.EmptyGridUnit;
+import org.apache.fop.fo.ValidationException;
+
/**
* A row group builder accommodating a variable number of columns. More flexible, but less
@@ -31,34 +34,69 @@ class VariableColRowGroupBuilder extends RowGroupBuilder {
VariableColRowGroupBuilder(Table t) {
super(t);
- numberOfColumns = 1;
}
/**
- * Fills the given row group with empty grid units if necessary, so that it matches
- * the given number of columns.
- *
- * @param rowGroup a List of List of GridUnit
- * @param numberOfColumns the number of columns that the row group must have
+ * Each event is recorded and will be played once the table is finished, and the final
+ * number of columns known.
*/
- static void fillWithEmptyGridUnits(List rowGroup, int numberOfColumns) {
- for (int i = 0; i < rowGroup.size(); i++) {
- List effRow = (List) rowGroup.get(i);
- for (int j = effRow.size(); j < numberOfColumns; j++) {
- effRow.add(new EmptyGridUnit(null, null, null, j));
+ private static interface Event {
+ /**
+ * Plays this event
+ *
+ * @param rowGroupBuilder the delegate builder which will actually create the row
+ * groups
+ * @throws ValidationException if a row-spanning cell overflows its parent body
+ */
+ void play(RowGroupBuilder rowGroupBuilder) throws ValidationException;
+ }
+
+ /** The queue of events sent to this builder. */
+ private List events = new LinkedList();
+
+ /** {@inheritDoc} */
+ void addTableCell(final TableCell cell) {
+ events.add(new Event() {
+ public void play(RowGroupBuilder rowGroupBuilder) {
+ rowGroupBuilder.addTableCell(cell);
}
- }
+ });
}
- /**
- * Updates the current row group to match the given number of columns, by adding empty
- * grid units if necessary.
- *
- * @param numberOfColumns new number of columns
- */
- void ensureNumberOfColumns(int numberOfColumns) {
- this.numberOfColumns = numberOfColumns;
- fillWithEmptyGridUnits(rows, numberOfColumns);
+ /** {@inheritDoc} */
+ void endRow(final TableCellContainer container) {
+ events.add(new Event() {
+ public void play(RowGroupBuilder rowGroupBuilder) {
+ rowGroupBuilder.endRow(container);
+ }
+ });
}
+ /** {@inheritDoc} */
+ void startTablePart(final TableBody part) {
+ events.add(new Event() {
+ public void play(RowGroupBuilder rowGroupBuilder) {
+ rowGroupBuilder.startTablePart(part);
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ void endTablePart(final TableBody tableBody) throws ValidationException {
+ // TODO catch the ValidationException sooner?
+ events.add(new Event() {
+ public void play(RowGroupBuilder rowGroupBuilder) throws ValidationException {
+ rowGroupBuilder.endTablePart(tableBody);
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ void endTable(final TableBody lastTablePart) throws ValidationException {
+ RowGroupBuilder delegate = new FixedColRowGroupBuilder(table);
+ for (Iterator eventIter = events.iterator(); eventIter.hasNext();) {
+ ((Event) eventIter.next()).play(delegate);
+ }
+ delegate.endTable(lastTablePart);
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
index d021ec922..114dadb94 100755
--- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
+++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
@@ -83,7 +83,7 @@ public class CommonBorderPaddingBackground {
private Color mColor; // Border color
private CondLengthProperty mWidth;
- BorderInfo(int style, CondLengthProperty width, Color color) {
+ public BorderInfo(int style, CondLengthProperty width, Color color) {
mStyle = style;
mWidth = width;
mColor = color;
@@ -227,7 +227,11 @@ public class CommonBorderPaddingBackground {
* @return the border info for a side
*/
public BorderInfo getBorderInfo(int side) {
- return this.borderInfo[side];
+ if (this.borderInfo[side] == null) {
+ return new BorderInfo(Constants.EN_NONE, null, null); // TODO
+ } else {
+ return this.borderInfo[side];
+ }
}
/**
diff --git a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
index 5c60ee6fd..5cfe5e382 100644
--- a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
+++ b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
@@ -20,8 +20,8 @@
package org.apache.fop.layoutmgr.table;
import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.flow.table.BorderSpecification;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
-import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
/**
* This class is a superclass for the two collapsing border models defined
@@ -37,10 +37,7 @@ public abstract class CollapsingBorderModel {
protected static final int START = CommonBorderPaddingBackground.START;
/** end side */
protected static final int END = CommonBorderPaddingBackground.END;
-
- /** Flag: current grid unit is either start or end of the table. */
- public static final int VERTICAL_START_END_OF_TABLE = 1;
-
+
/** Indicates that the cell is/starts in the first row being painted on a particular page */
//public static final int FIRST_ROW_IN_TABLE_PART = 1;
/** Indicates that the cell is/ends in the last row being painted on a particular page */
@@ -53,7 +50,7 @@ public abstract class CollapsingBorderModel {
//These statics are used singleton-style. No MT issues here.
private static CollapsingBorderModel collapse = null;
private static CollapsingBorderModel collapseWithPrecedence = null;
-
+
/**
* @param borderCollapse border collapse control
* @return the border model for the cell
@@ -74,12 +71,12 @@ public abstract class CollapsingBorderModel {
throw new IllegalArgumentException("Illegal border-collapse mode.");
}
}
-
+
/**
* @param side the side on the current cell
* @return the adjacent side on the neighbouring cell
*/
- public static int getOtherSide(int side) {
+ static int getOtherSide(int side) {
switch (side) {
case CommonBorderPaddingBackground.BEFORE:
return CommonBorderPaddingBackground.AFTER;
@@ -93,23 +90,32 @@ public abstract class CollapsingBorderModel {
throw new IllegalArgumentException("Illegal parameter: side");
}
}
-
+
/**
* @param side the side to investigate
* @return true if the adjacent cell is before or after
*/
protected boolean isVerticalRelation(int side) {
- return (side == CommonBorderPaddingBackground.BEFORE
+ return (side == CommonBorderPaddingBackground.BEFORE
|| side == CommonBorderPaddingBackground.AFTER);
}
-
+ private static int compareInt(int value1, int value2) {
+ if (value1 < value2) {
+ return -1;
+ } else if (value1 == value2) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
/**
* See rule 4 in 6.7.10 for the collapsing border model.
* @param style the border style to get the preference value for
* @return the preference value of the style
*/
- public int getPreferenceValue(int style) {
+ private static int getStylePreferenceValue(int style) {
switch (style) {
case Constants.EN_DOUBLE: return 0;
case Constants.EN_SOLID: return -1;
@@ -122,14 +128,62 @@ public abstract class CollapsingBorderModel {
default: throw new IllegalStateException("Illegal border style: " + style);
}
}
-
+
+ /**
+ * Compares the two given styles (see {@link Constants}).
+ *
+ * @param style1 a style constant
+ * @param style2 another style constant
+ * @return a value &lt; 0 if style1 has less priority than style2, 0 if both are
+ * equal, a value &gt; 0 if style1 has more priority than style2
+ */
+ static int compareStyles(int style1, int style2) {
+ int value1 = getStylePreferenceValue(style1);
+ int value2 = getStylePreferenceValue(style2);
+ return compareInt(value1, value2);
+ }
+
+ private static int getHolderPreferenceValue(int id) {
+ switch (id) {
+ case Constants.FO_TABLE_CELL: return 0;
+ case Constants.FO_TABLE_ROW: return -1;
+ case Constants.FO_TABLE_HEADER:
+ case Constants.FO_TABLE_FOOTER:
+ case Constants.FO_TABLE_BODY:
+ return -2;
+ case Constants.FO_TABLE_COLUMN: return -3;
+ // TODO colgroup
+ case Constants.FO_TABLE: return -4;
+ default: throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Compares the two given FO ids ({@link Constants}.FO*) in terms of border
+ * declaration.
+ *
+ * @param id1 a FO id ({@link Constants#FO_TABLE}, {@link Constants#FO_TABLE_BODY},
+ * etc.)
+ * @param id2 another FO id
+ * @return a value &lt; 0 if id1 has less priority than id2, 0 if both are equal, a
+ * value &gt; 0 if id1 has more priority than id2
+ */
+ static int compareFOs(int id1, int id2) {
+ int p1 = getHolderPreferenceValue(id1);
+ int p2 = getHolderPreferenceValue(id2);
+ return compareInt(p1, p2);
+ }
+
/**
- * Determines the winning BorderInfo.
- * @param current grid unit of the current element
- * @param neighbour grid unit of the neighbouring element
- * @return the winning BorderInfo
+ * Returns the border which wins the border conflict resolution. In case the two
+ * borders are equivalent (identical, or only the color is different), null is
+ * returned.
+ *
+ * @param border1 a border specification
+ * @param border2 another border specification
+ * @return the winning border, null if the two borders are equivalent
*/
- public abstract BorderInfo determineWinner(
- GridUnit current, GridUnit neighbour, int side, int flags);
-
+ public abstract BorderSpecification determineWinner(BorderSpecification border1,
+ BorderSpecification border2);
+
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
index ddbb20c47..5f979c986 100644
--- a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
+++ b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
@@ -20,11 +20,7 @@
package org.apache.fop.layoutmgr.table;
import org.apache.fop.fo.Constants;
-import org.apache.fop.fo.flow.table.Table;
-import org.apache.fop.fo.flow.table.TableBody;
-import org.apache.fop.fo.flow.table.TableCell;
-import org.apache.fop.fo.flow.table.TableColumn;
-import org.apache.fop.fo.flow.table.TableRow;
+import org.apache.fop.fo.flow.table.BorderSpecification;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
/**
@@ -34,268 +30,45 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
*/
public class CollapsingBorderModelEyeCatching extends CollapsingBorderModel {
- public BorderInfo determineWinner(GridUnit currentGridUnit,
- GridUnit otherGridUnit, int side, int flags) {
- final boolean vertical = isVerticalRelation(side);
- final int otherSide = getOtherSide(side);
-
- //Get cells
- TableCell currentCell = currentGridUnit.getCell();
- TableCell otherCell = null;
- if (otherGridUnit != null) {
- otherCell = otherGridUnit.getCell();
- }
-
- //Get rows
- TableRow currentRow = currentGridUnit.getRow();
- TableRow otherRow = null;
- if (vertical && otherCell != null) {
- otherRow = otherGridUnit.getRow();
- }
-
- //get bodies
- TableBody currentBody = currentGridUnit.getBody();
- TableBody otherBody = null;
- if (otherRow != null) {
- otherBody = otherGridUnit.getBody();
- }
-
- //get columns
- TableColumn currentColumn = currentGridUnit.getColumn();
- TableColumn otherColumn = null;
- if (otherGridUnit != null) {
- otherColumn = otherGridUnit.getColumn();
- }
-
- //TODO get column groups
-
- //Get table
- Table table = currentGridUnit.getTable();
-
- //----------------------------------------------------------------------
- //We're creating two arrays containing the applicable BorderInfos for
- //each cell in question.
- //0 = cell, 1 = row, 2 = row group (body), 3 = column,
- //4 = col group (spanned column, see 6.7.3), 5 = table
-
- BorderInfo[] current = new BorderInfo[6];
- BorderInfo[] other = new BorderInfo[6];
- //cell
- current[0] = currentGridUnit.getOriginalBorderInfoForCell(side);
- if (otherGridUnit != null) {
- other[0] = otherGridUnit.getOriginalBorderInfoForCell(otherSide);
- }
- if ((currentRow != null)
- && (side == BEFORE
- || side == AFTER
- || (currentGridUnit.getFlag(GridUnit.IN_FIRST_COLUMN) && side == START)
- || (currentGridUnit.getFlag(GridUnit.IN_LAST_COLUMN) && side == END))) {
- //row
- current[1] = currentRow.getCommonBorderPaddingBackground().getBorderInfo(side);
- }
- if (otherRow != null) {
- //row
- other[1] = otherRow.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
- }
- if (currentBody != null
- && ((side == BEFORE && currentGridUnit.getFlag(GridUnit.FIRST_IN_PART))
- || (side == AFTER && currentGridUnit.getFlag(GridUnit.LAST_IN_PART))
- || (currentGridUnit.getFlag(GridUnit.IN_FIRST_COLUMN) && side == START)
- || (currentGridUnit.getFlag(GridUnit.IN_LAST_COLUMN) && side == END))) {
- //row group (=body, table-header or table-footer)
- current[2] = currentBody.getCommonBorderPaddingBackground().getBorderInfo(side);
- }
- if (otherGridUnit != null
- && otherBody != null
- && ((otherSide == BEFORE && otherGridUnit.getFlag(GridUnit.FIRST_IN_PART))
- || (otherSide == AFTER && otherGridUnit.getFlag(GridUnit.LAST_IN_PART)))) {
- //row group (=body, table-header or table-footer)
- other[2] = otherBody.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
- }
- if ((side == BEFORE && otherGridUnit == null)
- || (side == AFTER && otherGridUnit == null)
- || (side == START)
- || (side == END)) {
- //column
- current[3] = currentColumn.getCommonBorderPaddingBackground().getBorderInfo(side);
- }
- if (otherColumn != null) {
- //column
- other[3] = otherColumn.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
- }
- //TODO current[4] and other[4] for column groups
- if (otherGridUnit == null
- && ((side == BEFORE && (flags & VERTICAL_START_END_OF_TABLE) > 0)
- || (side == AFTER && (flags & VERTICAL_START_END_OF_TABLE) > 0)
- || (side == START)
- || (side == END))) {
- //table
- current[5] = table.getCommonBorderPaddingBackground().getBorderInfo(side);
- }
- //other[6] is always null, since it's always the same table
-
- BorderInfo resolved = null;
-
- // *** Rule 1 ***
- resolved = doRule1(current, other);
- if (resolved != null) {
- return resolved;
- }
-
- // *** Rule 2 ***
- if (!doRule2(current, other)) {
- }
-
- // *** Rule 3 ***
- resolved = doRule3(current, other);
- if (resolved != null) {
- return resolved;
- }
-
- // *** Rule 4 ***
- resolved = doRule4(current, other);
- if (resolved != null) {
- return resolved;
- }
-
- // *** Rule 5 ***
- resolved = doRule5(current, other);
- if (resolved != null) {
- return resolved;
- }
-
- return null; //no winner, no border
- }
-
- private BorderInfo doRule1(BorderInfo[] current, BorderInfo[] other) {
- for (int i = 0; i < current.length; i++) {
- if ((current[i] != null) && (current[i].getStyle() == Constants.EN_HIDDEN)) {
- return current[i];
- }
- if ((other[i] != null) && (other[i].getStyle() == Constants.EN_HIDDEN)) {
- return other[i];
- }
- }
- return null;
- }
-
- private boolean doRule2(BorderInfo[] current, BorderInfo[] other) {
- boolean found = false;
- for (int i = 0; i < current.length; i++) {
- if ((current[i] != null) && (current[i].getStyle() != Constants.EN_NONE)) {
- found = true;
- break;
+ /** {@inheritDoc} */
+ public BorderSpecification determineWinner(BorderSpecification border1,
+ BorderSpecification border2) {
+ BorderInfo bi1 = border1.getBorderInfo();
+ BorderInfo bi2 = border2.getBorderInfo();
+ // Rule 1
+ if (bi1.getStyle() == Constants.EN_HIDDEN) {
+ return border1;
+ } else if (bi2.getStyle() == Constants.EN_HIDDEN) {
+ return border2;
+ }
+ // Rule 2
+ if (bi2.getStyle() == Constants.EN_NONE) {
+ return border1;
+ } else if (bi1.getStyle() == Constants.EN_NONE) {
+ return border2;
+ }
+ // Rule 3
+ int width1 = bi1.getRetainedWidth();
+ int width2 = bi2.getRetainedWidth();
+ if (width1 > width2) {
+ return border1;
+ } else if (width1 == width2) {
+ int cmp = compareStyles(bi1.getStyle(), bi2.getStyle());
+ if (cmp > 0) {
+ return border1;
+ } else if (cmp < 0) {
+ return border2;
}
- if ((other[i] != null) && (other[i].getStyle() != Constants.EN_NONE)) {
- found = true;
- break;
- }
- }
- return found;
- }
-
- private BorderInfo doRule3(BorderInfo[] current, BorderInfo[] other) {
- int width = 0;
- //Find max border width
- for (int i = 0; i < current.length; i++) {
- if ((current[i] != null) && (current[i].getRetainedWidth() > width)) {
- width = current[i].getRetainedWidth();
- }
- if ((other[i] != null) && (other[i].getRetainedWidth() > width)) {
- width = other[i].getRetainedWidth();
- }
- }
- BorderInfo widest = null;
- int count = 0;
- //See if there's only one with the widest border
- for (int i = 0; i < current.length; i++) {
- if ((current[i] != null) && (current[i].getRetainedWidth() == width)) {
- count++;
- if (widest == null) {
- widest = current[i];
- }
- } else {
- current[i] = null; //Discard the narrower ones
- }
- if ((other[i] != null) && (other[i].getRetainedWidth() == width)) {
- count++;
- if (widest == null) {
- widest = other[i];
- }
- } else {
- other[i] = null; //Discard the narrower ones
- }
- }
- if (count == 1) {
- return widest;
} else {
- return null;
+ return border2;
}
- }
-
- private BorderInfo doRule4(BorderInfo[] current, BorderInfo[] other) {
- int pref = getPreferenceValue(Constants.EN_INSET); //Lowest preference
- //Find highest preference value
- for (int i = 0; i < current.length; i++) {
- if (current[i] != null) {
- int currPref = getPreferenceValue(current[i].getStyle());
- if (currPref > pref) {
- pref = currPref;
- }
- }
- if (other[i] != null) {
- int currPref = getPreferenceValue(other[i].getStyle());
- if (currPref > pref) {
- pref = currPref;
- }
- }
- }
- BorderInfo preferred = null;
- int count = 0;
- //See if there's only one with the preferred border style
- for (int i = 0; i < current.length; i++) {
- if (current[i] != null) {
- int currPref = getPreferenceValue(current[i].getStyle());
- if (currPref == pref) {
- count++;
- if (preferred == null) {
- preferred = current[i];
- }
- break;
- }
- } else {
- current[i] = null; //Discard the ones that are not preferred
- }
- if (other[i] != null) {
- int currPref = getPreferenceValue(other[i].getStyle());
- if (currPref == pref) {
- count++;
- if (preferred == null) {
- preferred = other[i];
- }
- break;
- }
- } else {
- other[i] = null; //Discard the ones that are not preferred
- }
- }
- if (count == 1) {
- return preferred;
- } else {
- return null;
- }
- }
-
- private BorderInfo doRule5(BorderInfo[] current, BorderInfo[] other) {
- for (int i = 0; i < current.length; i++) {
- if (current[i] != null) {
- return current[i];
- }
- if (other[i] != null) {
- return other[i];
- }
+ // Rule 4
+ int cmp = compareFOs(border1.getHolder(), border2.getHolder());
+ if (cmp > 0) {
+ return border1;
+ } else if (cmp < 0) {
+ return border2;
}
return null;
}
-
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/EffRow.java b/src/java/org/apache/fop/layoutmgr/table/EffRow.java
index 1e4924a5a..fe57809e9 100644
--- a/src/java/org/apache/fop/layoutmgr/table/EffRow.java
+++ b/src/java/org/apache/fop/layoutmgr/table/EffRow.java
@@ -47,12 +47,14 @@ class EffRow {
* Creates a new effective row instance.
* @param index index of the row
* @param bodyType type of body (one of HEADER, FOOTER, BODY as found on TableRowIterator)
+ * @param gridUnits the grid units this row is made of
*/
- public EffRow(int index, int bodyType) {
+ public EffRow(int index, int bodyType, List gridUnits) {
this.index = index;
this.bodyType = bodyType;
+ this.gridUnits = gridUnits;
}
-
+
/** @return the index of the EffRow in the sequence of rows */
public int getIndex() {
return this.index;
diff --git a/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java b/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java
index 5c208b84b..50500c498 100644
--- a/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java
+++ b/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java
@@ -19,9 +19,12 @@
package org.apache.fop.layoutmgr.table;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.flow.table.BorderSpecification;
+import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
-import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableRow;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
/**
* GridUnit subclass for empty grid units.
@@ -30,25 +33,34 @@ public class EmptyGridUnit extends GridUnit {
private TableRow row;
private TableBody body;
-
+
/**
- * @param row Optional table-row instance
- * @param column table-column instance
- * @param body table-body the grid unit belongs to
- * @param startCol column index
+ * @param table the containing table
+ * @param startRow index of the row this grid unit belongs to, 0-based
+ * @param startCol column index, 0-based
*/
- public EmptyGridUnit(TableRow row, TableColumn column, TableBody body,
- int startCol) {
- super(null, null, column, startCol, 0);
- this.row = row;
- this.body = body;
+ public EmptyGridUnit(Table table, int startRow, int startCol) {
+ super(table, table.getColumn(startCol), startCol, 0, 0);
}
-
+
+ /** {@inheritDoc} */
+ protected void setBorder(int side) {
+ resolvedBorders[side] = new BorderSpecification(
+ new CommonBorderPaddingBackground.BorderInfo(Constants.EN_NONE, null, null),
+ Constants.FO_TABLE_CELL);
+ }
+
+ /** {@inheritDoc} */
+ public PrimaryGridUnit getPrimary() {
+ throw new UnsupportedOperationException();
+// return this; TODO
+ }
+
/** {@inheritDoc} */
public boolean isPrimary() {
return true;
}
-
+
/** {@inheritDoc} */
public TableBody getBody() {
return this.body;
@@ -58,4 +70,14 @@ public class EmptyGridUnit extends GridUnit {
public TableRow getRow() {
return this.row;
}
+
+ /** {@inheritDoc} */
+ public boolean isLastGridUnitColSpan() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isLastGridUnitRowSpan() {
+ return true;
+ }
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/GridUnit.java b/src/java/org/apache/fop/layoutmgr/table/GridUnit.java
index 79b2cca9e..7f713351f 100644
--- a/src/java/org/apache/fop/layoutmgr/table/GridUnit.java
+++ b/src/java/org/apache/fop/layoutmgr/table/GridUnit.java
@@ -22,10 +22,12 @@ package org.apache.fop.layoutmgr.table;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.flow.table.BorderSpecification;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.flow.table.TableFObj;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
@@ -39,81 +41,142 @@ public class GridUnit {
/** Indicates that the grid unit is in the first column. */
public static final int IN_FIRST_COLUMN = 0;
+
/** Indicates that the grid unit is in the last column. */
public static final int IN_LAST_COLUMN = 1;
+
/** Indicates that the grid unit is in the first row of the table. */
public static final int FIRST_IN_TABLE = 2;
- /** Indicates that the grid unit is in the first row of the table part (header, footer, body). */
+
+ /**
+ * Indicates that the grid unit is in the first row of the table part (header, footer,
+ * body).
+ */
public static final int FIRST_IN_PART = 3;
- /** Indicates that the grid unit is in the last row of the table part (header, footer, body). */
+
+ /**
+ * Indicates that the grid unit is in the last row of the table part (header, footer,
+ * body).
+ */
public static final int LAST_IN_PART = 4;
+
/** Indicates that the grid unit is in the last row of the table. */
public static final int LAST_IN_TABLE = 5;
+
/** Indicates that the primary grid unit has a pending keep-with-next. */
public static final int KEEP_WITH_NEXT_PENDING = 6;
+
/** Indicates that the primary grid unit has a pending keep-with-previous. */
public static final int KEEP_WITH_PREVIOUS_PENDING = 7;
/** Primary grid unit */
private PrimaryGridUnit primary;
+
/** Table cell which occupies this grid unit */
- private TableCell cell;
+ protected TableCell cell;
+
/** Table row which occupies this grid unit (may be null) */
private TableRow row;
+
/** Table column that this grid unit belongs to */
private TableColumn column;
/** start index of grid unit within row in column direction */
private int startCol;
+
/** index of grid unit within cell in column direction */
private int colSpanIndex;
+
/** index of grid unit within cell in row direction */
private int rowSpanIndex;
+
/** effective borders for a cell slot */
private CommonBorderPaddingBackground effectiveBorders;
+
/** flags for the grid unit */
private byte flags = 0;
+ protected BorderSpecification[] resolvedBorders;
+
+ private CollapsingBorderModel collapsingBorderModel;
/**
* Creates a new grid unit.
- *
- * @param cell table cell which occupies this grid unit
+ *
+ * @param table the containing table
* @param column table column this grid unit belongs to
* @param startCol index of the column this grid unit belongs to
* @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
*/
- public GridUnit(TableCell cell, TableColumn column, int startCol, int colSpanIndex) {
- this(null, cell, column, startCol, colSpanIndex);
+ protected GridUnit(Table table, TableColumn column, int startCol, int colSpanIndex,
+ int rowSpanIndex) {
+ this(column, startCol, colSpanIndex, rowSpanIndex);
+ setBorders(table);
}
/**
* Creates a new grid unit.
- *
- * @param primary the before-start grid unit of the cell containing this grid unit
+ *
+ * @param cell table cell which occupies this grid unit
* @param column table column this grid unit belongs to
* @param startCol index of the column this grid unit belongs to
* @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
*/
- public GridUnit(PrimaryGridUnit primary, TableColumn column, int startCol, int colSpanIndex) {
- this(primary, primary.getCell(), column, startCol, colSpanIndex);
+ protected GridUnit(TableCell cell, TableColumn column, int startCol, int colSpanIndex,
+ int rowSpanIndex) {
+ this(column, startCol, colSpanIndex, rowSpanIndex);
+ this.cell = cell;
+ setBorders(cell.getTable());
}
/**
* Creates a new grid unit.
- *
+ *
* @param primary the before-start grid unit of the cell containing this grid unit
- * @param cell table cell which occupies this grid unit
* @param column table column this grid unit belongs to
* @param startCol index of the column this grid unit belongs to
* @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(PrimaryGridUnit primary, TableCell cell, TableColumn column, int startCol, int colSpanIndex) {
+ public GridUnit(PrimaryGridUnit primary, TableColumn column, int startCol, int colSpanIndex,
+ int rowSpanIndex) {
+ this(primary.getCell(), column, startCol, colSpanIndex, rowSpanIndex);
this.primary = primary;
- this.cell = cell;
+ }
+
+ private GridUnit(TableColumn column, int startCol, int colSpanIndex, int rowSpanIndex) {
this.column = column;
this.startCol = startCol;
this.colSpanIndex = colSpanIndex;
+ this.rowSpanIndex = rowSpanIndex;
+ }
+
+ private void setBorders(Table table/*TODO*/) {
+ if (table.isSeparateBorderModel()) {
+ assignBorderForSeparateBorderModel();
+ } else {
+ resolvedBorders = new BorderSpecification[4];
+ collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table
+ .getBorderCollapse());
+ if (rowSpanIndex == 0) {
+ setBorder(CommonBorderPaddingBackground.BEFORE);
+ }
+ if (isLastGridUnitRowSpan()) {
+ setBorder(CommonBorderPaddingBackground.AFTER);
+ }
+ if (colSpanIndex == 0) {
+ setBorder(CommonBorderPaddingBackground.START);
+ }
+ if (isLastGridUnitColSpan()) {
+ setBorder(CommonBorderPaddingBackground.END);
+ }
+ }
+ }
+
+ protected void setBorder(int side) {
+ resolvedBorders[side] = cell.resolvedBorders[side];
}
public TableCell getCell() {
@@ -128,7 +191,7 @@ public class GridUnit {
if (row != null) {
return row;
} else if (getCell().getParent() instanceof TableRow) {
- return (TableRow)getCell().getParent();
+ return (TableRow) getCell().getParent();
} else {
return null;
}
@@ -136,6 +199,7 @@ public class GridUnit {
/**
* Sets the table-row FO, if applicable.
+ *
* @param row the table-row FO
*/
public void setRow(TableRow row) {
@@ -147,18 +211,7 @@ public class GridUnit {
while (node != null && !(node instanceof TableBody)) {
node = node.getParent();
}
- return (TableBody)node;
- }
-
- public Table getTable() {
- FONode node = getBody();
- while (node != null && !(node instanceof Table)) {
- node = node.getParent();
- }
- if (node == null && getColumn() != null) {
- node = getColumn().getParent();
- }
- return (Table)node;
+ return (TableBody) node;
}
/**
@@ -167,7 +220,7 @@ public class GridUnit {
* @return the before-start grid unit of the cell containing this grid unit.
*/
public PrimaryGridUnit getPrimary() {
- return (isPrimary() ? (PrimaryGridUnit)this : primary);
+ return primary;
}
/**
@@ -194,20 +247,12 @@ public class GridUnit {
/** @return true if the grid unit is the last in column spanning direction */
public boolean isLastGridUnitColSpan() {
- if (cell != null) {
- return (colSpanIndex == cell.getNumberColumnsSpanned() - 1);
- } else {
- return true;
- }
+ return (colSpanIndex == cell.getNumberColumnsSpanned() - 1);
}
/** @return true if the grid unit is the last in row spanning direction */
public boolean isLastGridUnitRowSpan() {
- if (cell != null) {
- return (rowSpanIndex == cell.getNumberRowsSpanned() - 1);
- } else {
- return true;
- }
+ return (rowSpanIndex == cell.getNumberRowsSpanned() - 1);
}
/**
@@ -225,9 +270,10 @@ public class GridUnit {
}
/**
- * Returns a BorderInfo instance for a side of the currently applicable cell before border
- * resolution (i.e. the value from the FO). A return value of null indicates an empty cell.
- * See CollapsingBorderModel(EyeCatching) where this method is used.
+ * Returns a BorderInfo instance for a side of the currently applicable cell before
+ * border resolution (i.e. the value from the FO). A return value of null indicates an
+ * empty cell. See CollapsingBorderModel(EyeCatching) where this method is used.
+ *
* @param side for which side to return the BorderInfo
* @return the requested BorderInfo instance or null if the grid unit is an empty cell
*/
@@ -243,9 +289,33 @@ public class GridUnit {
* @return the resolved normal borders for this grid unit
*/
public CommonBorderPaddingBackground getBorders() {
+ // TODO
+ if (effectiveBorders == null) {
+ effectiveBorders = new CommonBorderPaddingBackground();
+ setBorderInfo(CommonBorderPaddingBackground.BEFORE);
+ setBorderInfo(CommonBorderPaddingBackground.AFTER);
+ setBorderInfo(CommonBorderPaddingBackground.START);
+ setBorderInfo(CommonBorderPaddingBackground.END);
+ if (cell != null) {
+ effectiveBorders.setPadding(cell.getCommonBorderPaddingBackground());
+ }
+ if (log.isDebugEnabled()) {
+ log.debug(this + " resolved borders: " + "before="
+ + effectiveBorders.getBorderBeforeWidth(false) + ", " + "after="
+ + effectiveBorders.getBorderAfterWidth(false) + ", " + "start="
+ + effectiveBorders.getBorderStartWidth(false) + ", " + "end="
+ + effectiveBorders.getBorderEndWidth(false));
+ }
+ }
return effectiveBorders;
}
+ private void setBorderInfo(int side) {
+ if (resolvedBorders[side] != null) {
+ effectiveBorders.setBorderInfo(resolvedBorders[side].getBorderInfo(), side);
+ }
+ }
+
/**
* @return true if the grid unit has any borders.
*/
@@ -254,8 +324,8 @@ public class GridUnit {
}
/**
- * Assigns the borders from the given cell to this cell info. Used in
- * case of separate border model.
+ * Assigns the borders from the given cell to this cell info. Used in case of separate
+ * border model.
*/
public void assignBorderForSeparateBorderModel() {
if (cell != null) {
@@ -264,42 +334,39 @@ public class GridUnit {
}
/**
- * Resolve collapsing borders for the given cell. Used in case of the collapsing border model.
- * @param other neighbouring grid unit if any
- * @param side the side to resolve (one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
+ * Resolve collapsing borders for the given cell. Used in case of the collapsing
+ * border model.
+ *
+ * @param other neighbouring grid unit
+ * @param side the side to resolve (one of
+ * CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
*/
public void resolveBorder(GridUnit other, int side) {
- resolveBorder(other, side, 0);
+ BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(
+ resolvedBorders[side], other.resolvedBorders[CollapsingBorderModel
+ .getOtherSide(side)]);
+ if (resolvedBorder != null) {
+ this.resolvedBorders[side] = resolvedBorder;
+ other.resolvedBorders[CollapsingBorderModel.getOtherSide(side)] = resolvedBorder;
+ }
}
/**
- * Resolve collapsing borders for the given cell. Used in case of the collapsing border model.
- * @param other neighbouring grid unit if any
- * @param side the side to resolve (one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
- * @param resFlags flags for the border resolution
+ * Resolves the border on the given side of this grid unit, comparing it against the
+ * same border of the given parent element.
+ *
+ * @param side the side to resolve (one of
+ * CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
+ * @param parent the parent element holding a competing border
*/
- public void resolveBorder(GridUnit other, int side, int resFlags) {
- CollapsingBorderModel borderModel = CollapsingBorderModel.getBorderModelFor(
- getTable().getBorderCollapse());
- if (effectiveBorders == null) {
- effectiveBorders = new CommonBorderPaddingBackground();
- }
- effectiveBorders.setBorderInfo(borderModel.determineWinner(this, other,
- side, resFlags), side);
- if (cell != null) {
- effectiveBorders.setPadding(cell.getCommonBorderPaddingBackground());
- }
- if (log.isDebugEnabled()) {
- log.debug(this + " resolved borders: "
- + "before=" + effectiveBorders.getBorderBeforeWidth(false) + ", "
- + "after=" + effectiveBorders.getBorderAfterWidth(false) + ", "
- + "start=" + effectiveBorders.getBorderStartWidth(false) + ", "
- + "end=" + effectiveBorders.getBorderEndWidth(false));
- }
+ public void resolveBorder(int side, TableFObj parent) {
+ resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side],
+ parent.resolvedBorders[side]);
}
/**
* Returns a flag for this GridUnit.
+ *
* @param which the requested flag
* @return the value of the flag
*/
@@ -309,29 +376,25 @@ public class GridUnit {
/**
* Sets a flag on a GridUnit.
+ *
* @param which the flag to set
* @param value the new value for the flag
*/
public void setFlag(int which, boolean value) {
if (value) {
- flags |= (1 << which); //set flag
+ flags |= (1 << which); // set flag
} else {
- flags &= ~(1 << which); //clear flag
+ flags &= ~(1 << which); // clear flag
}
}
/**
- * @return the grid unit just below this grid unit if the cell is spanning.
+ * Sets the given flag on this grid unit.
+ *
+ * @param which the flag to set
*/
- public GridUnit createNextRowSpanningGridUnit() {
- if (isLastGridUnitRowSpan()) {
- return null;
- } else {
- //cloning the current GridUnit with adjustments
- GridUnit gu = new GridUnit(getPrimary(), getColumn(), startCol, colSpanIndex);
- gu.rowSpanIndex = rowSpanIndex + 1;
- return gu;
- }
+ public void setFlag(int which) {
+ setFlag(which, true);
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java b/src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java
index ece022556..34daf7d96 100644
--- a/src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java
+++ b/src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java
@@ -55,18 +55,22 @@ public class PrimaryGridUnit extends GridUnit {
* @param startRow index of the row this grid unit belongs to, zero-based
*/
public PrimaryGridUnit(TableCell cell, TableColumn column, int startCol, int startRow) {
- super(cell, column, startCol, 0);
+ super(cell, column, startCol, 0, 0);
this.startRow = startRow;
log.trace("PrimaryGridUnit created, row " + startRow + " col " + startCol);
- if (cell != null) {
- cellLM = new TableCellLayoutManager(cell, this);
- }
}
public TableCellLayoutManager getCellLM() {
+ assert cellLM != null;
return cellLM;
}
+ /** {@inheritDoc} */
+ public PrimaryGridUnit getPrimary() {
+ return this;
+ }
+
+ /** {@inheritDoc} */
public boolean isPrimary() {
return true;
}
@@ -225,4 +229,12 @@ public class PrimaryGridUnit extends GridUnit {
|| (getCell().getNumberRowsSpanned() > 1);
}
+ /**
+ * Creates a cellLM for the corresponding table-cell. A new one must be created
+ * for each new static-content (TODO).
+ */
+ public void createCellLM() {
+ cellLM = new TableCellLayoutManager(cell, this);
+ }
+
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
index 4dd42110f..c7776ff7b 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
@@ -97,10 +97,6 @@ class RowGroupLayoutManager {
public LinkedList getNextKnuthElements(LayoutContext context, int alignment, int bodyType) {
LinkedList returnList = new LinkedList();
- //Border resolution
- if (!tableLM.getTable().isSeparateBorderModel()) {
- resolveNormalBeforeAfterBordersForRowGroup();
- }
//Reset keep-with-next when remaining inside the table.
//The context flag is only used to propagate keep-with-next to the outside.
@@ -134,107 +130,6 @@ class RowGroupLayoutManager {
}
/**
- * Resolves normal borders for a row group.
- * @param iter Table row iterator to operate on
- */
- private void resolveNormalBeforeAfterBordersForRowGroup() {
- for (int rgi = 0; rgi < rowGroup.length; rgi++) {
- EffRow row = rowGroup[rgi];
- EffRow prevRow = thisIter.getPrecedingRow(row);
- EffRow nextRow = thisIter.getFollowingRow(row);
- if ((prevRow == null) && (thisIter == bodyIter) && (headerIter != null)) {
- prevRow = headerIter.getLastRow();
- }
- if ((nextRow == null) && (thisIter == headerIter)) {
- nextRow = bodyIter.getFirstRow();
- }
- if ((nextRow == null) && (thisIter == bodyIter) && (footerIter != null)) {
- nextRow = footerIter.getFirstRow();
- }
- if ((prevRow == null) && (thisIter == footerIter)) {
- //TODO This could be bad for memory consumption because it already causes the
- //whole body iterator to be prefetched!
- prevRow = bodyIter.getLastRow();
- }
- log.debug("prevRow-row-nextRow: " + prevRow + " - " + row + " - " + nextRow);
-
- //Determine the grid units necessary for getting all the borders right
- int guCount = row.getGridUnits().size();
- if (prevRow != null) {
- guCount = Math.max(guCount, prevRow.getGridUnits().size());
- }
- if (nextRow != null) {
- guCount = Math.max(guCount, nextRow.getGridUnits().size());
- }
- GridUnit gu = row.getGridUnit(0);
- //Create empty grid units to hold resolved borders of neighbouring cells
- //TODO maybe this needs to be done differently (and sooner)
- for (int i = 0; i < guCount - row.getGridUnits().size(); i++) {
- //TODO This block is untested!
- int pos = row.getGridUnits().size() + i;
- row.getGridUnits().add(new EmptyGridUnit(gu.getRow(),
- tableLM.getColumns().getColumn(pos + 1), gu.getBody(),
- pos));
- }
-
- //Now resolve normal borders
- if (tableLM.getTable().isSeparateBorderModel()) {
- //nop, borders are already assigned at this point
- } else {
- for (int i = 0; i < row.getGridUnits().size(); i++) {
- gu = row.getGridUnit(i);
- GridUnit other;
- int flags = 0;
- if (prevRow != null && i < prevRow.getGridUnits().size()) {
- other = prevRow.getGridUnit(i);
- } else {
- other = null;
- }
- if (other == null
- || other.isEmpty()
- || gu.isEmpty()
- || gu.getPrimary() != other.getPrimary()) {
- if ((thisIter == bodyIter)
- && gu.getFlag(GridUnit.FIRST_IN_TABLE)
- && (headerIter == null)) {
- flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
- }
- if ((thisIter == headerIter)
- && gu.getFlag(GridUnit.FIRST_IN_TABLE)) {
- flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
- }
- gu.resolveBorder(other,
- CommonBorderPaddingBackground.BEFORE, flags);
- }
-
- flags = 0;
- if (nextRow != null && i < nextRow.getGridUnits().size()) {
- other = nextRow.getGridUnit(i);
- } else {
- other = null;
- }
- if (other == null
- || other.isEmpty()
- || gu.isEmpty()
- || gu.getPrimary() != other.getPrimary()) {
- if ((thisIter == bodyIter)
- && gu.getFlag(GridUnit.LAST_IN_TABLE)
- && (footerIter == null)) {
- flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
- }
- if ((thisIter == footerIter)
- && gu.getFlag(GridUnit.LAST_IN_TABLE)) {
- flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
- }
- gu.resolveBorder(other,
- CommonBorderPaddingBackground.AFTER, flags);
- }
- }
- }
- }
- }
-
- /**
* Creates Knuth elements for a row group (see TableRowIterator.getNextRowGroup()).
* @param context Active LayoutContext
* @param alignment alignment indicator
@@ -271,6 +166,7 @@ class RowGroupLayoutManager {
PrimaryGridUnit primary = gu.getPrimary();
if (gu.isPrimary()) {
+ primary.createCellLM(); // TODO a new LM must be created for every new static-content
primary.getCellLM().setParent(tableLM);
//Determine the table-row if any
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
index dfac329a8..3acde70d3 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
@@ -20,11 +20,14 @@
package org.apache.fop.layoutmgr.table;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FONode.FONodeIterator;
import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
@@ -98,6 +101,8 @@ public class TableRowIterator {
/** Iterator over a part's child elements (either table-rows or table-cells). */
private ListIterator tablePartChildIterator = null;
+ private Iterator rowGroupsIter;
+
/**
* Creates a new TableRowIterator.
* @param table the table to iterate over
@@ -110,19 +115,23 @@ public class TableRowIterator {
this.tablePart = tablePart;
switch(tablePart) {
case HEADER: {
- List bodyList = new java.util.ArrayList();
- bodyList.add(table.getTableHeader());
- this.tablePartIterator = bodyList.listIterator();
+ rowGroupsIter = table.getTableHeader().getRowGroups().iterator();
break;
}
case FOOTER: {
- List bodyList = new java.util.ArrayList();
- bodyList.add(table.getTableFooter());
- this.tablePartIterator = bodyList.listIterator();
+ rowGroupsIter = table.getTableFooter().getRowGroups().iterator();
break;
}
default: {
- this.tablePartIterator = table.getChildNodes();
+ List rowGroupsList = new LinkedList();
+ // TODO this is ugly
+ for (FONodeIterator iter = table.getChildNodes(); iter.hasNext();) {
+ FONode node = iter.nextNode();
+ if (node instanceof TableBody) {
+ rowGroupsList.addAll(((TableBody) node).getRowGroups());
+ }
+ }
+ rowGroupsIter = rowGroupsList.iterator();
}
}
}
@@ -132,38 +141,19 @@ public class TableRowIterator {
* consecutive rows which contains all spanned grid units of its cells.
* @return the next row group, or null
*/
- public EffRow[] getNextRowGroup() {
- EffRow firstRowInGroup = getNextRow();
- if (firstRowInGroup == null) {
+ EffRow[] getNextRowGroup() {
+ if (!rowGroupsIter.hasNext()) {
return null;
}
- EffRow lastRowInGroup = firstRowInGroup;
- int lastIndex = lastRowInGroup.getIndex();
- boolean allFinished;
- do {
- allFinished = true;
- Iterator iter = lastRowInGroup.getGridUnits().iterator();
- while (iter.hasNext()) {
- GridUnit gu = (GridUnit)iter.next();
- if (!gu.isLastGridUnitRowSpan()) {
- allFinished = false;
- break;
- }
- }
- lastIndex = lastRowInGroup.getIndex();
- if (!allFinished) {
- lastRowInGroup = getNextRow();
- if (lastRowInGroup == null) {
- allFinished = true;
- }
- }
- } while (!allFinished);
- int rowCount = lastIndex - firstRowInGroup.getIndex() + 1;
- EffRow[] rowGroup = new EffRow[rowCount];
- for (int i = 0; i < rowCount; i++) {
- rowGroup[i] = getCachedRow(i + firstRowInGroup.getIndex());
+ List rowGroup = (List) rowGroupsIter.next();
+ EffRow[] effRowGroup = new EffRow[rowGroup.size()];
+ int i = 0;
+ for (Iterator rowIter = rowGroup.iterator(); rowIter.hasNext();) {
+ List gridUnits = (List) rowIter.next();
+ effRowGroup[i] = new EffRow(i, tablePart, gridUnits);
+ i++;
}
- return rowGroup;
+ return effRowGroup;
}
/**
@@ -197,7 +187,7 @@ public class TableRowIterator {
* @return the preceding row, or null if there is no such row (the given row is the
* first one in the table part)
*/
- public EffRow getPrecedingRow(EffRow row) {
+ EffRow getPrecedingRow(EffRow row) {
return getRow(row.getIndex() - 1);
}
@@ -207,7 +197,7 @@ public class TableRowIterator {
* @param row a row in the iterated table part
* @return the following row, or null if there is no more row
*/
- public EffRow getFollowingRow(EffRow row) {
+ EffRow getFollowingRow(EffRow row) {
return getRow(row.getIndex() + 1);
}
@@ -215,7 +205,7 @@ public class TableRowIterator {
* Returns the first effective row.
* @return the requested effective row.
*/
- public EffRow getFirstRow() {
+ EffRow getFirstRow() {
if (fetchedRows.size() == 0) {
prefetchNext();
}
@@ -228,7 +218,7 @@ public class TableRowIterator {
* if preloaded.</p>
* @return the requested effective row.
*/
- public EffRow getLastRow() {
+ EffRow getLastRow() {
while (prefetchNext()) {
//nop
}
@@ -377,7 +367,7 @@ public class TableRowIterator {
* @return the list of grid units
*/
private EffRow buildGridRow(List cells, TableRow rowFO) {
- EffRow row = new EffRow(this.fetchIndex, tablePart);
+ EffRow row = new EffRow(this.fetchIndex, tablePart, null);
List gridUnits = row.getGridUnits();
TableBody bodyFO = null;
@@ -393,7 +383,8 @@ public class TableRowIterator {
if (gu.getColSpanIndex() == 0) {
horzSpan = new GridUnit[gu.getCell().getNumberColumnsSpanned()];
}
- GridUnit newGU = gu.createNextRowSpanningGridUnit();
+// GridUnit newGU = gu.createNextRowSpanningGridUnit();
+ GridUnit newGU = null;
newGU.setRow(rowFO);
safelySetListItem(gridUnits, colnum - 1, newGU);
horzSpan[newGU.getColSpanIndex()] = newGU;
@@ -455,7 +446,7 @@ public class TableRowIterator {
horzSpan[0] = gu;
for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
colnum++;
- GridUnit guSpan = new GridUnit(gu, columns.getColumn(colnum), colnum - 1, j);
+ GridUnit guSpan = new GridUnit(gu, columns.getColumn(colnum), colnum - 1, j, 0);
//TODO: remove the check below???
other = (GridUnit)safelyGetListItem(gridUnits, colnum - 1);
if (other != null) {
@@ -486,29 +477,29 @@ public class TableRowIterator {
}
//Post-processing the list (looking for gaps and resolve start and end borders)
- fillEmptyGridUnits(gridUnits, rowFO, bodyFO);
+// fillEmptyGridUnits(gridUnits, rowFO, bodyFO);
resolveStartEndBorders(gridUnits);
return row;
}
- private void fillEmptyGridUnits(List gridUnits, TableRow row, TableBody body) {
- for (int pos = 1; pos <= gridUnits.size(); pos++) {
- GridUnit gu = (GridUnit)gridUnits.get(pos - 1);
-
- //Empty grid units
- if (gu == null) {
- //Add grid unit
- gu = new EmptyGridUnit(row, columns.getColumn(pos), body,
- pos - 1);
- gridUnits.set(pos - 1, gu);
- }
-
- //Set flags
- gu.setFlag(GridUnit.IN_FIRST_COLUMN, (pos == 1));
- gu.setFlag(GridUnit.IN_LAST_COLUMN, (pos == gridUnits.size()));
- }
- }
+// private void fillEmptyGridUnits(List gridUnits, TableRow row, TableBody body) {
+// for (int pos = 1; pos <= gridUnits.size(); pos++) {
+// GridUnit gu = (GridUnit)gridUnits.get(pos - 1);
+//
+// //Empty grid units
+// if (gu == null) {
+// //Add grid unit
+// gu = new EmptyGridUnit(row, columns.getColumn(pos), body,
+// pos - 1);
+// gridUnits.set(pos - 1, gu);
+// }
+//
+// //Set flags
+// gu.setFlag(GridUnit.IN_FIRST_COLUMN, (pos == 1));
+// gu.setFlag(GridUnit.IN_LAST_COLUMN, (pos == gridUnits.size()));
+// }
+// }
private void resolveStartEndBorders(List gridUnits) {
for (int pos = 1; pos <= gridUnits.size(); pos++) {