You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by vh...@apache.org on 2007/11/13 17:24:36 UTC

svn commit: r594571 [1/3] - in /xmlgraphics/fop/trunk: ./ src/java/org/apache/fop/fo/flow/ src/java/org/apache/fop/fo/flow/table/ src/java/org/apache/fop/fo/properties/ src/java/org/apache/fop/layoutmgr/table/ test/layoutengine/standard-testcases/

Author: vhennebert
Date: Tue Nov 13 08:24:32 2007
New Revision: 594571

URL: http://svn.apache.org/viewvc?rev=594571&view=rev
Log:
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)

Added:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderResolver.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java   (with props)
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java   (with props)
    xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/table_border-collapse_collapse_nrnc_no-col.xml   (with props)
    xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution.xml   (with props)
    xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution_no-col.xml   (with props)
    xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_2_no-col.xml   (with props)
Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/RetrieveMarker.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/Table.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableBody.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCell.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableColumn.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFObj.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFooter.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableHeader.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableRow.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EffRow.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/GridUnit.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
    xmlgraphics/fop/trunk/status.xml
    xmlgraphics/fop/trunk/test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_2.xml

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/RetrieveMarker.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/RetrieveMarker.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/RetrieveMarker.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/RetrieveMarker.java Tue Nov 13 08:24:32 2007
@@ -23,12 +23,13 @@
 
 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 @@
                         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 @@
                 }
                 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);

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderResolver.java?rev=594571&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderResolver.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderResolver.java Tue Nov 13 08:24:32 2007
@@ -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();
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderResolver.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java?rev=594571&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java Tue Nov 13 08:24:32 2007
@@ -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 + "}";
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java?rev=594571&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java Tue Nov 13 08:24:32 2007
@@ -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);
+        }
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java Tue Nov 13 08:24:32 2007
@@ -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 @@
  */
 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();
+    }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java Tue Nov 13 08:24:32 2007
@@ -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 @@
  */
 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 @@
      */
     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.
-     */
-    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++;
-        }
-    }
+     * @param part the part being started
+     */
+    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;
 }

Added: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java?rev=594571&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java (added)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java Tue Nov 13 08:24:32 2007
@@ -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() {
+    }
+}

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/Table.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/Table.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/Table.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/Table.java Tue Nov 13 08:24:32 2007
@@ -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 @@
     /**
      * {@inheritDoc}
      */
-    protected void startOfNode() throws FOPException {
+    public void startOfNode() throws FOPException {
         super.startOfNode();
         getFOEventHandler().startTable(this);
     }
@@ -211,7 +210,7 @@
     /**
      * {@inheritDoc}
      */
-    protected void endOfNode() throws FOPException {
+    public void endOfNode() throws FOPException {
 
         if (!tableBodyFound) {
            missingChildElementError(
@@ -219,6 +218,11 @@
                        + ",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 @@
         }
     }
 
+    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 @@
         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 @@
         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 @@
      * @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);
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableBody.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableBody.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableBody.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableBody.java Tue Nov 13 08:24:32 2007
@@ -50,15 +50,15 @@
     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 @@
     /**
      * {@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 @@
         }
     }
 
+    /** {@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 @@
         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 @@
                 if (lastCellEndsRow) {
                     firstRow = false;
                     columnNumberManager.prepareForNextRow(pendingSpans);
-                    getTable().getRowGroupBuilder().signalRowEnd(this);
+                    getTable().getRowGroupBuilder().endRow(this);
                 }
                 break;
             default:
@@ -208,11 +224,20 @@
         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 @@
         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 @@
             firstRow = false;
             if (!lastCellEndsRow) {
                 columnNumberManager.prepareForNextRow(pendingSpans);
-                getTable().getRowGroupBuilder().signalRowEnd(this);
+                getTable().getRowGroupBuilder().endRow(this);
             }
         }
         rowsStarted = true;

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCell.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCell.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCell.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCell.java Tue Nov 13 08:24:32 2007
@@ -90,7 +90,7 @@
     /**
      * {@inheritDoc}
      */
-    protected void startOfNode() throws FOPException {
+    public void startOfNode() throws FOPException {
         super.startOfNode();
         getFOEventHandler().startCell(this);
     }
@@ -100,7 +100,7 @@
      * 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;)+");
@@ -131,6 +131,21 @@
             invalidChildError(loc, nsURI, localName);
         } else {
             blockItemFound = true;
+        }
+    }
+
+    /** {@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);
         }
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableCellContainer.java Tue Nov 13 08:24:32 2007
@@ -93,6 +93,13 @@
         }
     }
 
+    /**
+     * 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;

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableColumn.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableColumn.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableColumn.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableColumn.java Tue Nov 13 08:24:32 2007
@@ -31,6 +31,7 @@
 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 @@
     /**
      * {@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);
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFObj.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFObj.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFObj.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFObj.java Tue Nov 13 08:24:32 2007
@@ -30,6 +30,7 @@
 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 @@
     private Numeric borderEndPrecedence;
     private Numeric borderStartPrecedence;
 
+    public/*TODO*/ BorderSpecification[] resolvedBorders = new BorderSpecification[4]; // TODO
+
+    CollapsingBorderModel collapsingBorderModel;
+    
     /**
      * Main constructor
      * 
@@ -122,9 +127,7 @@
             super(propId);
         }
 
-        /**
-         * {@inheritDoc}
-         */
+        /** {@inheritDoc} */
         public Property make(PropertyList propertyList)
                 throws PropertyException {
             FObj fo = propertyList.getFObj();
@@ -188,5 +191,56 @@
 
             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]);
     }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFooter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFooter.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFooter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableFooter.java Tue Nov 13 08:24:32 2007
@@ -39,14 +39,15 @@
     /**
      * {@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+)");
@@ -64,5 +65,10 @@
     /** {@inheritDoc} */
     public int getNameId() {
         return FO_TABLE_FOOTER;
+    }
+
+    /** {@inheritDoc} */
+    protected boolean isTableFooter() {
+        return true;
     }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableHeader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableHeader.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableHeader.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableHeader.java Tue Nov 13 08:24:32 2007
@@ -39,14 +39,15 @@
     /**
      * {@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+)");

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableRow.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableRow.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableRow.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/TableRow.java Tue Nov 13 08:24:32 2007
@@ -97,7 +97,7 @@
     /**
      * {@inheritDoc}
      */
-    protected void startOfNode() throws FOPException {
+    public void startOfNode() throws FOPException {
         super.startOfNode();
         getFOEventHandler().startRow(this);
     }
@@ -105,7 +105,7 @@
     /**
      * {@inheritDoc}
      */
-    protected void endOfNode() throws FOPException {
+    public void endOfNode() throws FOPException {
         if (firstChild == null) {
             missingChildElementError("(table-cell+)");
         }
@@ -126,6 +126,25 @@
         if (!(FO_URI.equals(nsURI) && localName.equals("table-cell"))) {
             invalidChildError(loc, nsURI, localName);
         }
+    }
+
+    /** {@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. */

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java Tue Nov 13 08:24:32 2007
@@ -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 @@
 
     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);
+    }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java Tue Nov 13 08:24:32 2007
@@ -83,7 +83,7 @@
         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 @@
      * @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];
+        }
     }
     
     /**

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java Tue Nov 13 08:24:32 2007
@@ -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 @@
     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 @@
     //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 @@
                 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 @@
                 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 @@
             default: throw new IllegalStateException("Illegal border style: " + style);
         }
     }
-    
+
     /**
-     * Determines the winning BorderInfo.
-     * @param current grid unit of the current element
-     * @param neighbour grid unit of the neighbouring element
-     * @return the winning BorderInfo
-     */
-    public abstract BorderInfo determineWinner(
-            GridUnit current, GridUnit neighbour, int side, int flags);
-    
+     * 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);
+    }
+
+    /**
+     * 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 BorderSpecification determineWinner(BorderSpecification border1,
+            BorderSpecification border2);
+
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java Tue Nov 13 08:24:32 2007
@@ -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 @@
  */
 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;
     }
-
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EffRow.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EffRow.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EffRow.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EffRow.java Tue Nov 13 08:24:32 2007
@@ -47,12 +47,14 @@
      * 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;

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java?rev=594571&r1=594570&r2=594571&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java Tue Nov 13 08:24:32 2007
@@ -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 @@
 
     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;
@@ -57,5 +69,15 @@
     /** {@inheritDoc} */
     public TableRow getRow() {
         return this.row;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isLastGridUnitColSpan() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isLastGridUnitRowSpan() {
+        return true;
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org