]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Proper generation of grid units for spanned cells (both directions).
authorJeremias Maerki <jeremias@apache.org>
Thu, 7 Apr 2005 07:09:24 +0000 (07:09 +0000)
committerJeremias Maerki <jeremias@apache.org>
Thu, 7 Apr 2005 07:09:24 +0000 (07:09 +0000)
start|end border resolution.
Border painting adjusted to new grid units

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

src/java/org/apache/fop/layoutmgr/table/Cell.java
src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/table/GridUnit.java
src/java/org/apache/fop/layoutmgr/table/OldGridUnit.java
src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java
src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java

index 8b0e020eccc27a70762a08802da3ae217fab8e84..7419ba1e6a04e292dfd59660c41bdd45b539d61a 100644 (file)
@@ -131,20 +131,10 @@ public class Cell extends BlockStackingLayoutManager implements BlockLevelLayout
 
     private int getIPIndents() {
         int iIndents = 0;
-        startBorderWidth = 0;
-        endBorderWidth = 0;
-        for (int i = 0; i < rows.size(); i++) {
-            List gridUnits = (List)rows.get(i);
-            startBorderWidth = Math.max(startBorderWidth, 
-                    ((OldGridUnit)gridUnits.get(0)).
-                        effBorders.getBorderStartWidth(false));
-            endBorderWidth = Math.max(endBorderWidth, 
-                    ((OldGridUnit)gridUnits.get(gridUnits.size() - 1)).
-                        effBorders.getBorderEndWidth(false));
-        }
-        //iIndents += fobj.getCommonBorderPaddingBackground().getBorderStartWidth(false);
+        int[] startEndBorderWidths = gridUnit.getStartEndBorderWidths();
+        startBorderWidth += startEndBorderWidths[0];
+        endBorderWidth += startEndBorderWidths[1];
         iIndents += startBorderWidth;
-        //iIndents += fobj.getCommonBorderPaddingBackground().getBorderEndWidth(false);
         iIndents += endBorderWidth;
         if (!fobj.isSeparateBorderModel()) {
             iIndents /= 2;
@@ -432,24 +422,19 @@ public class Cell extends BlockStackingLayoutManager implements BlockLevelLayout
             TraitSetter.addBackground(curBlockArea, fobj.getCommonBorderPaddingBackground());
             //TODO Set these booleans right
             boolean[] outer = new boolean[] {false, false, false, false};
-            if (rows.size() == 1 && ((List)rows.get(0)).size() == 1) {
+            if (!gridUnit.hasSpanning()) {
                 //Can set the borders directly if there's no span
-                CommonBorderPaddingBackground effBorders =
-                    ((OldGridUnit)((List)rows.get(0)).get(0)).effBorders;
-                //TODO Next line is a temporary hack!
-                TraitSetter.addCollapsingBorders(curBlockArea, 
-                        fobj.getCommonBorderPaddingBackground(), outer);
                 TraitSetter.addCollapsingBorders(curBlockArea, 
-                        effBorders, outer);
+                        gridUnit.getBorders(), outer);
             } else {
                 int dy = yoffset;
-                for (int y = 0; y < rows.size(); y++) {
-                    List gridUnits = (List)rows.get(y);
+                for (int y = 0; y < gridUnit.getRows().size(); y++) {
+                    GridUnit[] gridUnits = (GridUnit[])gridUnit.getRows().get(y);
                     int dx = xoffset;
                     int lastRowHeight = 0;
-                    for (int x = 0; x < gridUnits.size(); x++) {
-                        OldGridUnit gu = (OldGridUnit)gridUnits.get(x);
-                        if (!gu.effBorders.hasBorder()) {
+                    for (int x = 0; x < gridUnits.length; x++) {
+                        GridUnit gu = gridUnits[x];
+                        if (!gu.getBorders().hasBorder()) {
                             continue;
                         }
                         
@@ -457,18 +442,20 @@ public class Cell extends BlockStackingLayoutManager implements BlockLevelLayout
                         Block block = new Block();
                         block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
                         block.setPositioning(Block.ABSOLUTE);
-                        block.setBPD(gu.row.getRowHeight());
-                        lastRowHeight = gu.row.getRowHeight();
-                        int ipd = gu.column.getWidth().getValue();
-                        int borderStartWidth = gu.effBorders.getBorderStartWidth(false) / 2; 
+                        //block.setBPD(gu.row.getRowHeight());
+                        block.setBPD(rowHeight); //TODO This needs to be fixed for row spanning
+                        //lastRowHeight = gu.row.getRowHeight();
+                        lastRowHeight = rowHeight;
+                        int ipd = gu.getColumn().getColumnWidth().getValue();
+                        int borderStartWidth = gu.getBorders().getBorderStartWidth(false) / 2; 
                         ipd -= borderStartWidth;
-                        ipd -= gu.effBorders.getBorderEndWidth(false) / 2;
+                        ipd -= gu.getBorders().getBorderEndWidth(false) / 2;
                         block.setIPD(ipd);
                         block.setXOffset(dx + borderStartWidth);
                         block.setYOffset(dy);
-                        TraitSetter.addCollapsingBorders(block, gu.effBorders, outer);
+                        TraitSetter.addCollapsingBorders(block, gu.getBorders(), outer);
                         parentLM.addChildArea(block);
-                        dx += gu.column.getWidth().getValue();
+                        dx += gu.getColumn().getColumnWidth().getValue();
                     }
                     dy += lastRowHeight;
                 }
@@ -560,7 +547,7 @@ public class Cell extends BlockStackingLayoutManager implements BlockLevelLayout
             int halfCollapsingBorderHeight = 0;
             if (!fobj.isSeparateBorderModel()) {
                 halfCollapsingBorderHeight += 
-                    fobj.getCommonBorderPaddingBackground().getBorderBeforeWidth(false) / 2;
+                    gridUnit.getBorders().getBorderBeforeWidth(false) / 2;
             }
             curBlockArea.setXOffset(xoffset + inRowIPDOffset + halfBorderSep + indent);
             curBlockArea.setYOffset(yoffset - halfCollapsingBorderHeight);
index 44ab65510415e09450b86fb93acab18d311f3b57..4d923fecd3d65fbe821cb44fdb79bb27ec48ccfa 100644 (file)
@@ -111,11 +111,11 @@ public abstract class CollapsingBorderModel {
     
     /**
      * Determines the winning BorderInfo.
-     * @param current cell info of the current element
-     * @param neighbour cell info of the neighbouring element
+     * @param current grid unit of the current element
+     * @param neighbour grid unit of the neighbouring element
      * @return the winning BorderInfo
      */
     public abstract BorderInfo determineWinner(
-            OldGridUnit current, OldGridUnit neighbour, int side, int flags);
+            GridUnit current, GridUnit neighbour, int side, int flags);
     
 }
index ea54d153c5e8c1f9598f7f071be26b401a2fecf9..1fccbc4a43c23997f7b5aad8089925a357eedc95 100644 (file)
 package org.apache.fop.layoutmgr.table;
 
 import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.flow.Table;
+import org.apache.fop.fo.flow.TableBody;
+import org.apache.fop.fo.flow.TableCell;
+import org.apache.fop.fo.flow.TableColumn;
+import org.apache.fop.fo.flow.TableRow;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
 
@@ -34,43 +39,43 @@ public class CollapsingBorderModelEyeCatching extends CollapsingBorderModel {
     private static final int START = CommonBorderPaddingBackground.START;
     private static final int END = CommonBorderPaddingBackground.END;
     
-    public BorderInfo determineWinner(OldGridUnit currentGridUnit, 
-            OldGridUnit otherGridUnit, int side, int flags) {
+    public BorderInfo determineWinner(GridUnit currentGridUnit, 
+            GridUnit otherGridUnit, int side, int flags) {
         final boolean vertical = isVerticalRelation(side);
         final int otherSide = getOtherSide(side);
         
         //Get cells
-        Cell currentCell = currentGridUnit.layoutManager;
-        Cell otherCell = null;
+        TableCell currentCell = currentGridUnit.getCell();
+        TableCell otherCell = null;
         if (otherGridUnit != null) {
-            otherCell = otherGridUnit.layoutManager;
+            otherCell = otherGridUnit.getCell();
         }
         
         //Get rows
-        Row currentRow = currentGridUnit.row;
-        Row otherRow = null;
+        TableRow currentRow = currentGridUnit.getRow();
+        TableRow otherRow = null;
         if (vertical && otherCell != null) {
-            otherRow = otherGridUnit.row;
+            otherRow = otherGridUnit.getRow();
         }
         
         //get bodies
-        Body currentBody = (Body)currentRow.getParent();
-        Body otherBody = null;
+        TableBody currentBody = currentGridUnit.getBody();
+        TableBody otherBody = null;
         if (otherRow != null) {
-            otherBody = (Body)otherRow.getParent();
+            otherBody = otherGridUnit.getBody();
         }
 
         //get columns
-        Column currentColumn = (Column)currentGridUnit.column;
-        Column otherColumn = null;
+        TableColumn currentColumn = currentGridUnit.getColumn();
+        TableColumn otherColumn = null;
         if (otherGridUnit != null) {
-            otherColumn = (Column)otherGridUnit.column;
+            otherColumn = otherGridUnit.getColumn();
         }
         
         //TODO get column groups
         
         //Get table
-        TableLayoutManager table = (TableLayoutManager)currentBody.getParent();
+        Table table = currentGridUnit.getTable();
         
         //----------------------------------------------------------------------
         //We're creating two arrays containing the applicable BorderInfos for
@@ -85,44 +90,45 @@ public class CollapsingBorderModelEyeCatching extends CollapsingBorderModel {
         if (otherGridUnit != null) {
             other[0] = otherGridUnit.getOriginalBorderInfoForCell(otherSide);
         }
-        if (side == BEFORE 
-                || side == AFTER
-                || (currentColumn.isFirst() && side == START)
-                || (currentColumn.isLast() && side == END)) {
+        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.getFObj().getCommonBorderPaddingBackground().getBorderInfo(side);
+            current[1] = currentRow.getCommonBorderPaddingBackground().getBorderInfo(side);
         }
         if (otherRow != null) {
             //row
-            other[1] = otherRow.getFObj().getCommonBorderPaddingBackground().getBorderInfo(otherSide);
+            other[1] = otherRow.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
         }
-        if ((side == BEFORE && currentRow.isFirstInBody())
-                || (side == AFTER && currentRow.isLastInBody())
-                || (currentColumn.isFirst() && side == START)
-                || (currentColumn.isLast() && side == END)) {
+        if ((side == BEFORE && currentGridUnit.getFlag(GridUnit.FIRST_IN_BODY))
+                || (side == AFTER && currentGridUnit.getFlag(GridUnit.LAST_IN_BODY))
+                || (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.getFObj().getCommonBorderPaddingBackground().getBorderInfo(side);
+            current[2] = currentBody.getCommonBorderPaddingBackground().getBorderInfo(side);
         }
-        if ((otherSide == BEFORE && otherRow.isFirstInBody())
-                || (otherSide == AFTER && otherRow.isLastInBody())) {
+        if ((otherSide == BEFORE && otherGridUnit.getFlag(GridUnit.FIRST_IN_BODY))
+                || (otherSide == AFTER && otherGridUnit.getFlag(GridUnit.LAST_IN_BODY))) {
             //row group (=body, table-header or table-footer)
-            other[2] = otherBody.getFObj().getCommonBorderPaddingBackground().getBorderInfo(otherSide);
+            other[2] = otherBody.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
         }
         if ((side == BEFORE && otherGridUnit == null)
                 || (side == AFTER && otherGridUnit == null)
                 || (side == START)
                 || (side == END)) {
             //column
-            current[3] = currentColumn.getFObj().getCommonBorderPaddingBackground().getBorderInfo(side);
+            current[3] = currentColumn.getCommonBorderPaddingBackground().getBorderInfo(side);
         }
         if (otherColumn != null) {
             //column
-            other[3] = otherColumn.getFObj().getCommonBorderPaddingBackground().getBorderInfo(otherSide);
+            other[3] = otherColumn.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
         }
         //TODO current[4] and other[4] for column groups
         if (otherGridUnit == null) {
             //table
-            current[5] = table.getTable().getCommonBorderPaddingBackground().getBorderInfo(side);
+            current[5] = table.getCommonBorderPaddingBackground().getBorderInfo(side);
         }
         //other[6] is always null, since it's always the same table
         
diff --git a/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java b/src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java
new file mode 100644 (file)
index 0000000..8197dd5
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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.layoutmgr.table;
+
+import org.apache.fop.fo.flow.TableBody;
+import org.apache.fop.fo.flow.TableCell;
+import org.apache.fop.fo.flow.TableColumn;
+import org.apache.fop.fo.flow.TableRow;
+
+/**
+ * GridUnit subclass for empty grid units.
+ */
+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 
+     * @param colSpanIndex
+     */
+    public EmptyGridUnit(TableRow row, TableColumn column, TableBody body, 
+            int startCol) {
+        super(null, column, startCol, 0);
+        this.row = row;
+        this.body = body;
+    }
+    
+    /** @see org.apache.fop.layoutmgr.table.GridUnit#isPrimary() */
+    public boolean isPrimary() {
+        return true;
+    }
+    
+    /** @see org.apache.fop.layoutmgr.table.GridUnit#getBody() */
+    public TableBody getBody() {
+        return this.body;
+    }
+
+    /** @see org.apache.fop.layoutmgr.table.GridUnit#getRow() */
+    public TableRow getRow() {
+        return this.row;
+    }
+}
index 7f7b738cb10fc4f3533440c330c6c00b2ad33bac..262d83f256810abbef1ceff446c080ec75102b27 100644 (file)
@@ -24,12 +24,27 @@ import org.apache.fop.fo.flow.TableBody;
 import org.apache.fop.fo.flow.TableCell;
 import org.apache.fop.fo.flow.TableColumn;
 import org.apache.fop.fo.flow.TableRow;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
 
 /**
  * This class represents one grid unit inside a table.
  */
 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 (context: table). */
+    public static final int FIRST_IN_TABLE = 2;
+    /** Indicates that the grid unit is in the first row (context: body). */
+    public static final int FIRST_IN_BODY = 3;
+    /** Indicates that the grid unit is in the last row (context: body). */
+    public static final int LAST_IN_BODY = 4;
+    /** Indicates that the grid unit is in the last row (context: table). */
+    public static final int LAST_IN_TABLE = 5;
+    
     /** Table cell which occupies this grid unit */
     private TableCell cell;
     /** Table column that this grid unit belongs to */
@@ -41,6 +56,10 @@ public class GridUnit {
     private int colSpanIndex;
     /** index of grid unit within cell in row direction */
     private int rowSpanIndex;
+    /** effective borders for a cell slot */
+    private CommonBorderPaddingBackground effBorders;
+    /** flags for the grid unit */
+    private byte flags = 0;
     
     
     public GridUnit(TableCell cell, TableColumn column, int startCol, int colSpanIndex) {
@@ -68,15 +87,15 @@ public class GridUnit {
     
     public TableBody getBody() {
         FONode node = getCell();
-        while (!(node instanceof TableBody)) {
+        while (node != null && !(node instanceof TableBody)) {
             node = node.getParent();
         }
         return (TableBody)node;
     }
     
     public Table getTable() {
-        FONode node = getCell();
-        while (!(node instanceof Table)) {
+        FONode node = getBody();
+        while (node != null && !(node instanceof Table)) {
             node = node.getParent();
         }
         return (Table)node;
@@ -94,6 +113,92 @@ public class GridUnit {
         return this.startCol;
     }
     
+    /** @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 true if the grid unit is the last in column spanning direction */
+    public boolean isLastGridUnitRowSpan() {
+        if (cell != null) {
+            return (rowSpanIndex == cell.getNumberRowsSpanned() - 1);
+        } else {
+            return true;
+        }
+    }
+    
+    public BorderInfo getOriginalBorderInfoForCell(int side) {
+        if (cell != null) {
+            return cell.getCommonBorderPaddingBackground().getBorderInfo(side);
+        } else {
+            return null;
+        }
+    }
+    
+    public CommonBorderPaddingBackground getBorders() {
+        return this.effBorders;
+    }
+    
+    public void setBorders(CommonBorderPaddingBackground borders) {
+        this.effBorders = borders;
+    }
+    
+    /**
+     * Assigns the borders from the given cell to this cell info. Used in
+     * case of separate border model.
+     */
+    public void assignBorderForSeparateBorderModel() {
+        if (cell != null) {
+            this.effBorders = cell.getCommonBorderPaddingBackground();
+        }
+    }
+    
+    /**
+     * 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)
+     */
+    public void resolveBorder(GridUnit other, int side) {
+        CollapsingBorderModel borderModel = CollapsingBorderModel.getBorderModelFor(
+                getTable().getBorderCollapse());
+        if (this.effBorders == null) {
+            this.effBorders = new CommonBorderPaddingBackground();
+        }
+        this.effBorders.setBorderInfo(
+                borderModel.determineWinner(this, other, 
+                        side, 0), side);
+    }
+    
+    public boolean getFlag(int which) {
+        return (flags & (1 << which)) != 0;
+    }
+    
+    public void setFlag(int which, boolean value) {
+        if (value) {
+            flags |= (1 << which); //set flag
+        } else {
+            flags &= ~(1 << which); //clear flag
+        }
+    }
+    
+    /**
+     * @return the grid unit just below this grid unit if the cell is spanning.
+     */
+    public GridUnit createNextRowSpanningGridUnit() {
+        if (isLastGridUnitRowSpan()) {
+            return null;
+        } else {
+            //cloning the current GridUnit with adjustments
+            GridUnit gu = new GridUnit(getCell(), getColumn(), startCol, colSpanIndex);
+            gu.rowSpanIndex = rowSpanIndex + 1;
+            return gu;
+        }
+    }
+
     /** @see java.lang.Object#toString() */
     public String toString() {
         StringBuffer sb = new StringBuffer();
@@ -110,7 +215,8 @@ public class GridUnit {
             sb.append(" rowSpan=").append(rowSpanIndex);
         }
         sb.append(" startCol=").append(startCol);
+        sb.append(" flags=").append(Integer.toBinaryString(flags));
         return sb.toString();
     }
-    
+
 }
index 4a7021ae7132171174ccf1ef44f142898d0f3227..8f0f5a2d6969ec7e19e9bfaf86494281d8c6f31d 100644 (file)
@@ -123,9 +123,10 @@ public class OldGridUnit {
         
         CollapsingBorderModel borderModel = CollapsingBorderModel.getBorderModelFor(
                 table.getBorderCollapse());
+        /*
         target.setBorderInfo(
                 borderModel.determineWinner(current, other, 
-                        side, 0), side);
+                        side, 0), side);*/
     }
     
 }
\ No newline at end of file
index eb9dd38af622612fe7af7a2ec2b0b21d348c55eb..c9c481289e539798ac64970222a0677b4d5c2311 100644 (file)
@@ -19,6 +19,7 @@
 package org.apache.fop.layoutmgr.table;
 
 import java.util.LinkedList;
+import java.util.List;
 
 import org.apache.fop.fo.flow.TableCell;
 import org.apache.fop.fo.flow.TableColumn;
@@ -28,11 +29,14 @@ import org.apache.fop.fo.flow.TableColumn;
  */
 public class PrimaryGridUnit extends GridUnit {
 
+    /** Cell layout manager. */
     private Cell cellLM;
+    /** List of Knuth elements representing the contents of the cell. */
     private LinkedList elements;
-    /** index of row where this cell starts */
+    /** Index of row where this cell starts */
     private int startRow;
-
+    /** Links to the spanned grid units. (List of GridUnit arrays, one array represents a row) */ 
+    private List rows;
     
     public PrimaryGridUnit(TableCell cell, TableColumn column, int startCol, int startRow) {
         super(cell, column, startCol, 0);
@@ -58,15 +62,51 @@ public class PrimaryGridUnit extends GridUnit {
         return this.elements;
     }
     
+    public List getRows() {
+        return this.rows;
+    }
+    
+    public void addRow(GridUnit[] row) {
+        if (rows == null) {
+            rows = new java.util.ArrayList();
+        }
+        rows.add(row);
+    }
+    
     public int getStartRow() {
         return this.startRow;
     }
 
+    public int[] getStartEndBorderWidths() {
+        int[] widths = new int[2];
+        if (rows == null) {
+            widths[0] = getBorders().getBorderStartWidth(false);
+            widths[1] = getBorders().getBorderEndWidth(false);
+        } else {
+            for (int i = 0; i < rows.size(); i++) {
+                GridUnit[] gridUnits = (GridUnit[])rows.get(i);
+                widths[0] = Math.max(widths[0], 
+                        (gridUnits[0]).
+                            getBorders().getBorderStartWidth(false));
+                widths[1] = Math.max(widths[1], 
+                        (gridUnits[gridUnits.length - 1]).
+                            getBorders().getBorderEndWidth(false));
+            }
+        }
+        return widths;
+    }
+    
     /** @see java.lang.Object#toString() */
     public String toString() {
         StringBuffer sb = new StringBuffer(super.toString());
         sb.append(" startRow=").append(startRow);
         return sb.toString();
     }
+
+    /** @return true if this cell spans over more than one grid unit. */
+    public boolean hasSpanning() {
+        return (getCell().getNumberColumnsSpanned() > 1) 
+            || (getCell().getNumberRowsSpanned() > 1);
+    }
     
 }
index ed428583aefce16be64b68e577184141faa86a48..b01e1100ff89bc09307f8658f735f5456ed067c4 100644 (file)
@@ -18,7 +18,6 @@
 
 package org.apache.fop.layoutmgr.table;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.ListIterator;
 
@@ -43,12 +42,16 @@ public class TableRowIterator {
     private Table table;
     private ColumnSetup columns;
     
+    /** Holds the current row (TableCell instances) */
     private List currentRow = new java.util.ArrayList();
+    /** Holds the grid units of cell from the last row while will span over the current row 
+     * (GridUnit instance) */
+    private List lastRowsSpanningCells = new java.util.ArrayList();
     private int currentRowIndex = -1;
     //TODO rows should later be a Jakarta Commons LinkedList so concurrent modifications while 
     //using a ListIterator are possible
     private List rows = new java.util.ArrayList();
-    private int indexOfFirstRowInList;
+    //private int indexOfFirstRowInList;
     private int currentIndex = -1;
     
     //prefetch state
@@ -133,22 +136,61 @@ public class TableRowIterator {
         return true;
     }
 
+    private void safelySetListItem(List list, int position, Object obj) {
+        while (position >= list.size()) {
+            list.add(null);
+        }
+        list.set(position, obj);
+    }
+    
+    private Object safelyGetListItem(List list, int position) {
+        if (position >= list.size()) {
+            return null;
+        } else {
+            return list.get(position);
+        }
+    }
+    
     private EffRow buildGridRow(List cells) {
         EffRow row = new EffRow(this.currentRowIndex);
         List gridUnits = row.getGridUnits();
         
-        //Transfer available cells to their slots
+        TableRow rowFO = null;
+        TableBody bodyFO = null;
+        
+        //Create all row-spanned grid units based on information from the last row
         int colnum = 1;
+        ListIterator spanIter = lastRowsSpanningCells.listIterator();
+        while (spanIter.hasNext()) {
+            GridUnit gu = (GridUnit)spanIter.next();
+            if (gu != null) {
+                GridUnit newGU = gu.createNextRowSpanningGridUnit();
+                safelySetListItem(gridUnits, colnum - 1, newGU);
+                if (newGU.isLastGridUnitRowSpan()) {
+                    spanIter.set(null);
+                } else {
+                    spanIter.set(newGU);
+                }
+            }
+            colnum++;
+        }
+        
+        //Transfer available cells to their slots
+        colnum = 1;
         ListIterator iter = cells.listIterator();
         while (iter.hasNext()) {
             TableCell cell = (TableCell)iter.next();
+            
             if (cell.hasColumnNumber()) {
                 colnum = cell.getColumnNumber();
+            } else {
+                //Skip columns with spanning grid units
+                while (safelyGetListItem(gridUnits, colnum - 1) != null) {
+                    colnum++;
+                }
             }
-            while (colnum > gridUnits.size()) {
-                gridUnits.add(null);
-            }
-            if (gridUnits.get(colnum - 1) != null) {
+
+            if (safelyGetListItem(gridUnits, colnum - 1) != null) {
                 log.error("Overlapping cell at position " + colnum);
                 //TODO throw layout exception
             }
@@ -156,62 +198,81 @@ public class TableRowIterator {
 
             //Add grid unit for primary grid unit
             PrimaryGridUnit gu = new PrimaryGridUnit(cell, col, colnum - 1, this.currentRowIndex);
-            gridUnits.set(colnum - 1, gu);
+            safelySetListItem(gridUnits, colnum - 1, gu);
+            boolean hasRowSpanningLeft = !gu.isLastGridUnitRowSpan();
+            if (hasRowSpanningLeft) {
+                safelySetListItem(lastRowsSpanningCells, colnum - 1, gu);
+            }
             
-            //Add cell infos on spanned slots if any
-            for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
-                colnum++;
-                GridUnit guSpan = new GridUnit(cell, columns.getColumn(colnum), colnum - 1, j);
-                if (colnum > gridUnits.size()) {
-                    gridUnits.add(guSpan);
-                } else {
-                    if (gridUnits.get(colnum - 1) != null) {
+            if (gu.hasSpanning()) {
+                //Add grid units on spanned slots if any
+                GridUnit[] horzSpan = new GridUnit[cell.getNumberColumnsSpanned()];
+                horzSpan[0] = gu;
+                for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
+                    colnum++;
+                    GridUnit guSpan = new GridUnit(cell, columns.getColumn(colnum), colnum - 1, j);
+                    if (safelyGetListItem(gridUnits, colnum - 1) != null) {
                         log.error("Overlapping cell at position " + colnum);
                         //TODO throw layout exception
                     }
-                    gridUnits.set(colnum - 1, guSpan);
+                    safelySetListItem(gridUnits, colnum - 1, guSpan);
+                    if (hasRowSpanningLeft) {
+                        safelySetListItem(lastRowsSpanningCells, colnum - 1, gu);
+                    }
+                    horzSpan[j] = guSpan;
                 }
+                gu.addRow(horzSpan);
             }
+            
+            //Gather info for empty grid units (used later)
+            if (rowFO == null) {
+                rowFO = gu.getRow();
+            }
+            if (bodyFO == null) {
+                bodyFO = gu.getBody();
+            }
+            
             colnum++;
         }
         
         //Post-processing the list (looking for gaps and resolve start and end borders)
-        postProcessGridUnits(gridUnits);
+        fillEmptyGridUnits(gridUnits, rowFO, bodyFO);
+        resolveStartEndBorders(gridUnits);
         
         return row;
     }
     
-    private void fillEmptyGridUnits(List gridUnits) {
+    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 PrimaryGridUnit(null, columns.getColumn(pos)
-                        pos - 1, this.currentRowIndex);
+                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 postProcessGridUnits(List gridUnits) {
-        fillEmptyGridUnits(gridUnits);
-            
-        /*
-        //Border resolution now that the empty grid units are filled
+    private void resolveStartEndBorders(List gridUnits) {
         for (int pos = 1; pos <= gridUnits.size(); pos++) {
             GridUnit starting = (GridUnit)gridUnits.get(pos - 1);
          
             //Border resolution
             if (table.isSeparateBorderModel()) {
-                starting.assignBorder(starting.layoutManager);
+                starting.assignBorderForSeparateBorderModel();
             } else {
                 //Neighbouring grid unit at start edge 
-                OldGridUnit start = null;
+                GridUnit start = null;
                 int find = pos - 1;
                 while (find >= 1) {
-                    OldGridUnit candidate = (OldGridUnit)gridUnits.get(find - 1);
+                    GridUnit candidate = (GridUnit)gridUnits.get(find - 1);
                     if (candidate.isLastGridUnitColSpan()) {
                         start = candidate;
                         break;
@@ -220,39 +281,38 @@ public class TableRowIterator {
                 }
                 
                 //Ending grid unit for current cell
-                OldGridUnit ending = null;
-                if (starting.layoutManager != null) {
-                    pos += starting.layoutManager.getFObj().getNumberColumnsSpanned() - 1;
+                GridUnit ending = null;
+                if (starting.getCell() != null) {
+                    pos += starting.getCell().getNumberColumnsSpanned() - 1;
                 }
-                ending = (OldGridUnit)gridUnits.get(pos - 1);
+                ending = (GridUnit)gridUnits.get(pos - 1);
                 
                 //Neighbouring grid unit at end edge 
-                OldGridUnit end = null;
+                GridUnit end = null;
                 find = pos + 1;
                 while (find <= gridUnits.size()) {
-                    OldGridUnit candidate = (OldGridUnit)gridUnits.get(find - 1);
-                    if (candidate.isPrimaryGridUnit()) {
+                    GridUnit candidate = (GridUnit)gridUnits.get(find - 1);
+                    if (candidate.isPrimary()) {
                         end = candidate;
                         break;
                     }
                     find++;
                 }
-                CommonBorderPaddingBackground borders = new CommonBorderPaddingBackground();
-                OldGridUnit.resolveBorder(table, borders, starting, 
-                        (start != null ? start : null), 
+                //CommonBorderPaddingBackground borders = new CommonBorderPaddingBackground();
+                starting.resolveBorder(start, 
                         CommonBorderPaddingBackground.START);
-                starting.effBorders = borders;
+                //starting.setBorders(borders);
+                /*
                 if (starting != ending) {
                     borders = new CommonBorderPaddingBackground();
-                }
-                OldGridUnit.resolveBorder(table, borders, ending, 
-                        (end != null ? end : null), 
+                }*/
+                ending.resolveBorder(end, 
                         CommonBorderPaddingBackground.END);
-                ending.effBorders = borders;
+                //ending.setBorders(borders);
                 //Only start and end borders here, before and after during layout
                 //TODO resolve before and after borders during layout
             }
-        }*/
+        }
     }
     
     public class EffRow {