]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Fixes Bugzilla 39560: make sure the interaction between FOs and properties is only...
authorAndreas L. Delmelle <adelmelle@apache.org>
Tue, 6 Jun 2006 21:52:19 +0000 (21:52 +0000)
committerAndreas L. Delmelle <adelmelle@apache.org>
Tue, 6 Jun 2006 21:52:19 +0000 (21:52 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@412224 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/fo/flow/Table.java
src/java/org/apache/fop/fo/flow/TableBody.java
src/java/org/apache/fop/fo/flow/TableCell.java
src/java/org/apache/fop/fo/flow/TableFObj.java
src/java/org/apache/fop/fo/flow/TableRow.java
src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java
status.xml
test/layoutengine/disabled-testcases.xml

index dc14f642d33cc168f1deb2a2c0a02037a4217c56..6f2d7f198c4f08fe51e641435b8f62145f5f5cf3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -81,7 +81,7 @@ public class Table extends TableFObj {
     private boolean tableHeaderFound = false;   
     private boolean tableFooterFound = false;   
     private boolean tableBodyFound = false; 
-   
+
     /** 
      * Default table-column used when no columns are specified. It is used
      * to handle inheritance (especially visibility) and defaults properly. */
@@ -210,7 +210,8 @@ public class Table extends TableFObj {
     protected void endOfNode() throws FOPException {
         if (!tableBodyFound) {
            missingChildElementError(
-                   "(marker*,table-column*,table-header?,table-footer?,table-body+)");
+                   "(marker*,table-column*,table-header?,table-footer?"
+                       + ",table-body+)");
         }
         if (columns != null && !columns.isEmpty()) {
             for (int i = columns.size(); --i >= 0;) {
@@ -228,13 +229,15 @@ public class Table extends TableFObj {
     protected void addChildNode(FONode child) throws FOPException {
         if ("fo:table-column".equals(child.getName())) {
             addColumnNode((TableColumn) child);
-        } else if ("fo:table-footer".equals(child.getName())) {
-            tableFooter = (TableBody)child;
-        } else if ("fo:table-header".equals(child.getName())) {
-            tableHeader = (TableBody)child;
         } else {
-            // add bodies
-            super.addChildNode(child);
+            if ("fo:table-footer".equals(child.getName())) {
+                tableFooter = (TableBody) child;
+            } else if ("fo:table-header".equals(child.getName())) {
+                tableHeader = (TableBody) child;
+            } else {
+                // add bodies
+                super.addChildNode(child);
+            }
         }
     }
 
@@ -243,9 +246,9 @@ public class Table extends TableFObj {
      * used for determining initial values for column-number
      * 
      * @param col   the column to add
-     * @throws FOPException
+     * @throws FOPException 
      */
-    private void addColumnNode(TableColumn col) throws FOPException {
+    private void addColumnNode(TableColumn col) {
         int colNumber = col.getColumnNumber();
         int colRepeat = col.getNumberColumnsRepeated();
         if (columns == null) {
@@ -270,13 +273,9 @@ public class Table extends TableFObj {
             }
         }
         //flag column indices used by this column
-        for (int i = colNumber - 1; i < colNumber - 1 + colRepeat; i++) {
-            usedColumnIndices.set(i);
-        }
-        //set index for the next column to use
-        while (usedColumnIndices.get(columnIndex - 1)) {
-            columnIndex++;
-        }
+        int startIndex = colNumber - 1;
+        int endIndex = startIndex + colRepeat;
+        flagColumnIndices(startIndex, endIndex);
     }
 
     /** @return true of table-layout="auto" */
@@ -299,7 +298,7 @@ public class Table extends TableFObj {
      * @return the requested table-body element
      */
     public TableBody getBody(int index) {
-        return (TableBody)childNodes.get(index);
+        return (TableBody) childNodes.get(index);
     }
 
     /** @return the body for the table-header. */
@@ -439,7 +438,7 @@ public class Table extends TableFObj {
 
     /**
      * Sets the current column index of the given Table
-     * (used by TableColumn.bind() in case the column-number
+     * (used by ColumnNumberPropertyMaker.make() in case the column-number
      * was explicitly specified)
      * 
      * @param   newIndex    the new value for column index
@@ -448,4 +447,23 @@ public class Table extends TableFObj {
         columnIndex = newIndex;
     }
     
+    /**
+     * @see org.apache.fop.fo.flow.TableFObj#flagColumnIndices(int, int)
+     */
+    protected void flagColumnIndices(int start, int end) {
+        for (int i = start; i < end; i++) {
+            usedColumnIndices.set(i);
+        }
+        //set index for the next column to use
+        while (usedColumnIndices.get(columnIndex - 1)) {
+            columnIndex++;
+        }
+    }
+    
+    /**
+     * @see org.apache.fop.fo.flow.TableFObj#existsUsedColumnIndices()
+     */
+    protected boolean existsUsedColumnIndices() {
+        return (usedColumnIndices != null);
+    }
 }
index e970fb7d92e3cc615621ff2abb9d4d95e06f6fff..d0b706e3317c28303d1c440a3aca71412801893d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -22,6 +22,7 @@ package org.apache.fop.fo.flow;
 import java.util.BitSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.ListIterator;
 
 import org.xml.sax.Locator;
 
@@ -62,7 +63,7 @@ public class TableBody extends TableFObj {
     protected List pendingSpans;
     protected BitSet usedColumnIndices = new BitSet();
     private int columnIndex = 1;
-    private boolean firstRow = true;
+    protected boolean firstRow = true;
     
     /**
      * @param parent FONode that is the parent of the object
@@ -107,10 +108,15 @@ public class TableBody extends TableFObj {
                 getParent().removeChild(this);
             }
         }
-        /*
+        
         if (tableCellsFound) {
             convertCellsToRows();
-        }*/
+        }
+        
+        //reset column index (so that it would be
+        //correct if the table is cloned during
+        //marker retrieval)
+        resetColumnIndex();
         //release references
         savedPropertyList = null;
         pendingSpans = null;
@@ -138,9 +144,10 @@ public class TableBody extends TableFObj {
             } else if (localName.equals("table-cell")) {
                 tableCellsFound = true;
                 if (tableRowsFound) {
-                    invalidChildError(loc, nsURI, localName, "Either fo:table-rows" +
-                      " or fo:table-cells may be children of an " + getName() +
-                      " but not both");
+                    invalidChildError(loc, nsURI, localName, 
+                            "Either fo:table-rows or fo:table-cells "
+                            + "may be children of an " 
+                            + getName() + " but not both");
                 }  
             } else {
                 invalidChildError(loc, nsURI, localName);
@@ -150,84 +157,11 @@ public class TableBody extends TableFObj {
         }
     }
     
-    /**
-     * @see org.apache.fop.fo.FONode#addChildNode(FONode)
-     */
-    protected void addChildNode(FONode child) throws FOPException {
-        if (child.getNameId() == FO_TABLE_CELL) {
-            addCellNode( (TableCell) child);
-        } else {
-            super.addChildNode(child);
-        }
-    }
-
-    /**
-     * Adds a cell to the list of child nodes, and updates the columnIndex
-     * used for determining the initial value of column-number
-     * 
-     * @param cell  cell to add
-     * @throws FOPException
-     */
-    private void addCellNode(TableCell cell) throws FOPException {
-        //if firstRow flag is still true, the cell starts a row, 
-        //and there was a previous cell that didn't explicitly
-        //end the previous row => set firstRow flag to false
-        if (firstRow && cell.startsRow() && !lastCellEndedRow()) {
-            firstRow = false;
-        }
-        int rowSpan = cell.getNumberRowsSpanned();
-        int colSpan = cell.getNumberColumnsSpanned();
-        //if there were no explicit columns, pendingSpans
-        //will not be properly initialized for the first row
-        if (firstRow && getTable().columns == null) {
-            if (pendingSpans == null) {
-                pendingSpans = new java.util.ArrayList();
-            }
-            for (int i = colSpan; --i >= 0;) {
-                pendingSpans.add(null);
-            }
-        }
-        //if the current cell spans more than one row,
-        //update pending span list for the next row
-        if (rowSpan > 1) {
-            for (int i = colSpan; --i >= 0;) {
-                pendingSpans.set(columnIndex - 1 + i, 
-                        new PendingSpan(rowSpan));
-            }
-        }
-        //flag column indices used by this cell,
-        //take into account that possibly not all column-numbers
-        //are used by columns in the parent table (if any),
-        //so a cell spanning three columns, might actually
-        //take up more than three columnIndices...
-        int startIndex = columnIndex - 1;
-        int endIndex = startIndex + colSpan;
-        if (getTable().columns != null) {
-            List cols = getTable().columns;
-            int tmpIndex = endIndex;
-            for (int i = startIndex; i <= tmpIndex; ++i) {
-                if (i < cols.size() && cols.get(i) == null) {
-                    endIndex++;
-                }
-            }
-        }
-        for (int i = startIndex; i < endIndex; i++) {
-            usedColumnIndices.set(i);
-        }
-        setNextColumnIndex();
-        super.addChildNode(cell);
-        if (cell.endsRow()) {
-            if (firstRow) {
-                firstRow = false;
-            }
-            resetColumnIndex();
-        }
-    }
-
     /**
      * If table-cells are used as direct children of a table-body|header|footer
      * they are replaced in this method by proper table-rows.
-     * @throws FOPException if there's a problem binding the TableRows properties.
+     * @throws FOPException if there's a problem binding the TableRow's 
+     *         properties.
      */
     private void convertCellsToRows() throws FOPException {
         //getLogger().debug("Converting cells to rows...");
@@ -236,14 +170,15 @@ public class TableBody extends TableFObj {
         Iterator i = cells.iterator();
         TableRow row = null;
         while (i.hasNext()) {
-            TableCell cell = (TableCell)i.next();
+            TableCell cell = (TableCell) i.next();
             if (cell.startsRow() && (row != null)) {
                 childNodes.add(row);
                 row = null;
             }
             if (row == null) {
                 row = new TableRow(this);
-                PropertyList pList = new StaticPropertyList(row, savedPropertyList);
+                PropertyList pList = new StaticPropertyList(row, 
+                        savedPropertyList);
                 pList.setWritingMode();
                 row.bind(pList);
             }
@@ -282,8 +217,9 @@ public class TableBody extends TableFObj {
      * @return true if the given table row is the first row of this body.
      */
     public boolean isFirst(TableRow obj) {
-        return (childNodes.size() > 0) 
-            && (childNodes.get(0) == obj);
+        return (childNodes == null 
+                || (!childNodes.isEmpty()
+                    && childNodes.get(0) == obj));
     }
 
     /**
@@ -291,15 +227,20 @@ public class TableBody extends TableFObj {
      * @return true if the given table row is the first row of this body.
      */
     public boolean isLast(TableRow obj) {
-        return (childNodes.size() > 0) 
-            && (childNodes.get(childNodes.size() - 1) == obj);
+        return (childNodes == null
+                || (childNodes.size() > 0 
+                    && childNodes.get(childNodes.size() - 1) == obj));
     }
     
     /**
-     * Initializes pending spans list; used for correctly
+     * Initializes list of pending row-spans; used for correctly
      * assigning initial value for column-number for the
      * cells of following rows
-     *
+     * (note: not literally mentioned in the Rec, but it is assumed
+     *  that, if the first cell in a given row spans two rows, then
+     *  the first cell of the following row will have an initial
+     *  column-number of 2, since the first column is already 
+     *  occupied...)
      */
     protected void initPendingSpans() {
         if (getTable().columns != null) {
@@ -308,6 +249,10 @@ public class TableBody extends TableFObj {
             for (int i = tableCols.size(); --i >= 0;) {
                 pendingSpans.add(null);
             }
+        } else {
+            if (firstRow && pendingSpans == null) {
+                pendingSpans = new java.util.ArrayList();
+            }
         }
     }
         
@@ -322,8 +267,8 @@ public class TableBody extends TableFObj {
 
     /**
      * Sets the current column index to a specific value
-     * (used by TableCell.bind() in case the column-number
-     * was explicitly specified)
+     * (used by ColumnNumberPropertyMaker.make() in case the 
+     *  column-number was explicitly specified on the cell)
      * 
      * @param newIndex  the new column index
      */
@@ -384,13 +329,18 @@ public class TableBody extends TableFObj {
     /**
      * Checks whether the previous cell had 'ends-row="true"'
      * 
-     * @return false only if there was a previous cell, which
-     *         had ends-row="false" (implicit or explicit)
+     * @param currentCell   the cell for which the question is asked
+     * @return true if:
+     *          a) there is a previous cell, which
+     *             had ends-row="true"
+     *          b) there is no previous cell (implicit 
+     *             start of row)
      */
-    public boolean lastCellEndedRow() {
-        if (childNodes != null) {
-            FONode prevNode = (FONode) childNodes.get(childNodes.size() - 1);
-            if (prevNode.getNameId() == FO_TABLE_CELL) {
+    protected boolean lastCellEndedRow(TableCell currentCell) {
+        if (childNodes != null && childNodes.indexOf(currentCell) > 0) {
+            FONode prevNode = (FONode) childNodes.get(
+                    childNodes.indexOf(currentCell) - 1);
+            if (prevNode != null && prevNode.getNameId() == FO_TABLE_CELL) {
                 return ((TableCell) prevNode).endsRow();
             }
         }
@@ -399,13 +349,29 @@ public class TableBody extends TableFObj {
 
     /**
      * Checks whether a given column-number is already in use
-     * for the current row (used by TableCell.bind());
+     * for the current row;
      * 
      * @param   colNr   the column-number to check
      * @return true if column-number is already occupied
      */
     public boolean isColumnNumberUsed(int colNr) {
         return usedColumnIndices.get(colNr - 1);
-    }    
+    }
+    
+    /**
+     * @see org.apache.fop.fo.flow.TableFObj#flagColumnIndices(int, int)
+     */
+    protected void flagColumnIndices(int start, int end) {
+        for (int i = start; i < end; i++) {
+            usedColumnIndices.set(i);
+        }
+        setNextColumnIndex();
+    }
+    
+    /**
+     * @see org.apache.fop.fo.flow.TableFObj#existsUsedColumnIndices()
+     */
+    protected boolean existsUsedColumnIndices() {
+        return (usedColumnIndices != null);
+    }
 }
-
index 60826da163454fcf462d7dfd73e9794cfc1ec913..8f9282a5d0009e368cc93a3e77cae3cbd026466d 100644 (file)
@@ -18,6 +18,9 @@
 
 package org.apache.fop.fo.flow;
 
+import java.util.BitSet;
+import java.util.List;
+
 import org.xml.sax.Locator;
 
 import org.apache.fop.apps.FOPException;
@@ -94,7 +97,7 @@ public class TableCell extends TableFObj {
      * Set to true if all content completely laid out.
      */
     private boolean bDone = false;
-
+    
     /**
      * @param parent FONode that is the parent of this object
      */
@@ -111,7 +114,6 @@ public class TableCell extends TableFObj {
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonRelativePosition = pList.getRelativePositionProps();
         blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
-        columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric();
         displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum();
         relativeAlign = pList.get(PR_RELATIVE_ALIGN).getEnum();
         emptyCells = pList.get(PR_EMPTY_CELLS).getEnum();
@@ -123,6 +125,13 @@ public class TableCell extends TableFObj {
         numberRowsSpanned = pList.get(PR_NUMBER_ROWS_SPANNED).getNumeric();
         startsRow = pList.get(PR_STARTS_ROW).getEnum();
         width = pList.get(PR_WIDTH).getLength();
+        
+        //Check to make sure we're not in retrieve-marker context
+        //TODO: Can this be generalized/extended to other FOs/Properties?
+        if (((TableFObj) parent).existsUsedColumnIndices()) {
+            columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric();
+        }
+        
         super.bind(pList);
     }
 
@@ -144,8 +153,8 @@ public class TableCell extends TableFObj {
             if (getUserAgent().validateStrictly()) {
                 missingChildElementError("marker* (%block;)+");
             } else if (childNodes != null && childNodes.size() > 0) {
-                getLogger().warn("fo:table-cell content that is not enclosed by a "
-                        + "fo:block will be dropped/ignored.");
+                getLogger().warn("fo:table-cell content that is not "
+                        + "enclosed by a fo:block will be dropped/ignored.");
             }
         }
         if ((startsRow() || endsRow()) 
@@ -153,9 +162,112 @@ public class TableCell extends TableFObj {
             getLogger().warn("starts-row/ends-row for fo:table-cells "
                     + "non-applicable for children of an fo:table-row.");
         }
+        updateParentColumnIndex();
         getFOEventHandler().endCell(this);
     }
 
+    private void updateParentColumnIndex() {
+        
+        int rowSpan = getNumberRowsSpanned();
+        int colSpan = getNumberColumnsSpanned();
+        int columnIndex = ((TableFObj) parent).getCurrentColumnIndex();
+        
+        int i = -1;
+        while (++i < colSpan) {
+            //if table has explicit columns and the column-number isn't
+            //assigned to any column, increment further until the next
+            //column is encountered
+            if (getTable().getColumns() != null) {
+                while (columnIndex <= getTable().getColumns().size()
+                        && !getTable().isColumnNumberUsed(columnIndex)) {
+                    columnIndex++;
+                }
+            }
+            //if column-number is already in use by another cell
+            //in the current row => error!
+            if (((TableFObj) parent).isColumnNumberUsed(columnIndex + i)) {
+                log.error("fo:table-cell overlaps in column "
+                        + (columnIndex + i));
+            }
+        }
+
+        if (parent.getNameId() == FO_TABLE_ROW) {
+            /* parent is a fo:table-row */
+            TableRow row = (TableRow) parent;
+            TableBody body = (TableBody) parent.getParent();
+            
+            if (body.isFirst(row) && getTable().columns == null ) {
+                row.pendingSpans.add(null);
+                if (row.usedColumnIndices == null) {
+                    row.usedColumnIndices = new BitSet();
+                }
+            }
+            //if the current cell spans more than one row,
+            //update pending span list for the next row
+            if (rowSpan > 1) {
+                for (i = colSpan; --i >= 0;) {
+                    row.pendingSpans.set(columnIndex - 1 + i, 
+                            new PendingSpan(rowSpan));
+                }
+            }
+        } else {
+            /* parent is (should be) a fo:table-body/-header/-footer */
+            TableBody body = (TableBody) parent;
+            
+            /* if body.firstRow is still true, and :
+             * a) the cell starts a row,
+             * b) there was a previous cell 
+             * c) that previous cell didn't explicitly end the previous row
+             *  => set firstRow flag to false
+             */
+            if (startsRow() && body.firstRow) {
+                if (!body.lastCellEndedRow(this)) {
+                    body.firstRow = false;
+                }
+            }
+            
+            /* if there were no explicit columns, pendingSpans
+             * will not be properly initialized for the first row...
+             */
+            if (body.firstRow && getTable().columns == null) {
+                for (i = colSpan; --i >= 0;) {
+                    body.pendingSpans.add(null);
+                }
+            }
+            
+            /* if the current cell spans more than one row,
+             * update pending span list for the next row
+             */
+            if (rowSpan > 1) {
+                for (i = colSpan; --i >= 0;) {
+                    body.pendingSpans.set(columnIndex - 1 + i, 
+                            new PendingSpan(rowSpan));
+                }
+            }
+        }
+        //flag column indices used by this cell,
+        //take into account that possibly not all column-numbers
+        //are used by columns in the parent table (if any),
+        //so a cell spanning three columns, might actually
+        //take up more than three columnIndices...
+        int startIndex = columnIndex - 1;
+        int endIndex = startIndex + colSpan;
+        if (getTable().columns != null) {
+            List cols = getTable().columns;
+            int tmpIndex = endIndex;
+            for (i = startIndex; i <= tmpIndex; ++i) {
+                if (i < cols.size() && cols.get(i) == null) {
+                    endIndex++;
+                }
+            }
+        }
+        ((TableFObj) parent).flagColumnIndices(startIndex, endIndex);
+        if (endsRow() && parent.getNameId() != FO_TABLE_ROW) {
+            ((TableBody) parent).firstRow = false;
+            ((TableBody) parent).resetColumnIndex();
+        }
+    }
+    
     /**
      * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
      * XSL Content Model: marker* (%block;)+
@@ -187,102 +299,6 @@ public class TableCell extends TableFObj {
         startOffset = offset;
     }
 
-    /**
-     * Calculate cell border and padding, including offset of content
-     * rectangle from the theoretical grid position.
-     */
-// TODO This whole method is not used it refers to padding which requires layout
-// context to evaluate
-//    private void calcBorders(CommonBorderPaddingBackground bp) {
-//        if (this.borderCollapse == EN_SEPARATE) {
-//            /*
-//             * Easy case.
-//             * Cell border is the property specified directly on cell.
-//             * Offset content rect by half the border-separation value,
-//             * in addition to the border and padding values. Note:
-//             * border-separate should only be specified on the table object,
-//             * but it inherits.
-//             */
-//            int iSep = borderSeparation.getIPD().getLength().getValue();
-//            this.startAdjust = iSep / 2 + bp.getBorderStartWidth(false)
-//                               + bp.getPaddingStart(false);
-//
-//            this.widthAdjust = startAdjust + iSep - iSep / 2
-//                               + bp.getBorderEndWidth(false)
-//                               + bp.getPaddingEnd(false);
-//
-//            // Offset of content rectangle in the block-progression direction
-//            int bSep = borderSeparation.getBPD().getLength().getValue();
-//            this.beforeOffset = bSep / 2
-//                                + bp.getBorderBeforeWidth(false)
-//                                + bp.getPaddingBefore(false);
-//
-//        } else {
-//            // System.err.println("Collapse borders");
-//            /*
-//             * Hard case.
-//             * Cell border is combination of other cell borders, or table
-//             * border for edge cells. Also seems to border values specified
-//             * on row and column FO in the table (if I read CR correclty.)
-//             */
-//
-//            // Set up before and after borders, taking into account row
-//            // and table border properties.
-//            // ??? What about table-body, header,footer
-//
-//            /*
-//             * We can't calculate before and after because we aren't sure
-//             * whether this row will be the first or last in its area, due
-//             * to redoing break decisions (at least in the "new" architecture.)
-//             * So in the general case, we will calculate two possible values:
-//             * the first/last one and the "middle" one.
-//             * Example: border-before
-//             * 1. If the cell is in the first row in the first table body, it
-//             * will combine with the last row of the header, or with the
-//             * top (before) table border if there is no header.
-//             * 2. Otherwise there are two cases:
-//             * a. the row is first in its (non-first) Area.
-//             * The border can combine with either:
-//             * i.  the last row of table-header and its cells, or
-//             * ii. the table before border (no table-header or it is
-//             * omitted on non-first Areas).
-//             * b. the row isn't first in its Area.
-//             * The border combines with the border of the previous
-//             * row and the cells which end in that row.
-//             */
-//
-//            /*
-//             * if-first
-//             * Calculate the effective border of the cell before-border,
-//             * it's parent row before-border, the last header row after-border,
-//             * the after border of the cell(s) which end in the last header
-//             * row.
-//             */
-//            /*
-//             * if-not-first
-//             * Calculate the effective border of the cell before-border,
-//             * it's parent row before-border, the previous row after-border,
-//             * the after border of the cell(s) which end in the previous
-//             * row.
-//             */
-//
-//
-//            /* ivan demakov */
-//            int borderStart = bp.getBorderStartWidth(false);
-//            int borderEnd = bp.getBorderEndWidth(false);
-//            int borderBefore = bp.getBorderBeforeWidth(false);
-//            int borderAfter = bp.getBorderAfterWidth(false);
-//
-//            this.startAdjust = borderStart / 2 + bp.getPaddingStart(false);
-//
-//            this.widthAdjust = startAdjust + borderEnd / 2
-//                               + bp.getPaddingEnd(false);
-//            this.beforeOffset = borderBefore / 2 + bp.getPaddingBefore(false);
-//            // Half border height to fix overestimate of area size!
-//            this.borderHeight = (borderBefore + borderAfter) / 2;
-//        }
-//    }
-
     /**
      * @return the Common Border, Padding, and Background Properties.
      */
@@ -353,7 +369,7 @@ public class TableCell extends TableFObj {
     /**
      * @see org.apache.fop.fo.FObj#getNameId()
      */
-    public int getNameId() {
+    public final int getNameId() {
         return FO_TABLE_CELL;
     }
 }
index 729d5a5c296e72c7858154a79679301825460eed..fb2c72e1b38c5745b1e2eb29f166c02443d5c58c 100644 (file)
@@ -170,5 +170,23 @@ public abstract class TableFObj extends FObj {
      * @return the Common Border, Padding, and Background Properties.
      */
     public abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground();
-
+    
+    /**
+     * Flags column indices from <code>start</code> to <code>end</code>,
+     * and updates the current column index.
+     * Overridden for Table, TableBody, TableRow
+     * @param start start index
+     * @param end   end index
+     */
+    protected void flagColumnIndices(int start, int end) {
+        //nop
+    }
+    
+    /**
+     * Overridden for Table, TableBody, TableRow
+     * @return true if the usedColumnIndices BitSet exists, and is initialized
+     */
+    protected boolean existsUsedColumnIndices() {
+        return false;
+    }
 }
index 57da0f190b382a8c9c563557d41bf31655bc0568..0827cf7792f218bcf1be43b3040157418461cff4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -25,9 +25,7 @@ import org.xml.sax.Locator;
 
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.datatypes.Length;
-import org.apache.fop.datatypes.Numeric;
 import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.ValidationException;
 import org.apache.fop.fo.properties.CommonAccessibility;
@@ -59,8 +57,8 @@ public class TableRow extends TableFObj {
 
     private boolean setup = false;
     
-    private List pendingSpans;
-    private BitSet usedColumnIndices;
+    protected List pendingSpans;
+    protected BitSet usedColumnIndices;
     private int columnIndex = 1;
 
     /**
@@ -75,7 +73,8 @@ public class TableRow extends TableFObj {
      */
     public void bind(PropertyList pList) throws FOPException {
         commonAccessibility = pList.getAccessibilityProps();
-        blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
+        blockProgressionDimension 
+            = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
         commonAural = pList.getAuralProps();
         commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
         commonRelativePosition = pList.getRelativePositionProps();
@@ -91,7 +90,8 @@ public class TableRow extends TableFObj {
     }
 
     /**
-     * Adds a cell to this row (skips marker handling done by FObj.addChildNode().
+     * Adds a cell to this row (skips marker handling done by 
+     * FObj.addChildNode().
      * Used by TableBody during the row building process when only cells are
      * used as direct children of a table-body/header/footer.
      * @param cell cell to add.
@@ -115,6 +115,12 @@ public class TableRow extends TableFObj {
         
         checkId(id);
         getFOEventHandler().startRow(this);
+        if (((TableBody) parent).isFirst(this) 
+                && getTable().columns == null ) {
+            if (pendingSpans == null) {
+                pendingSpans = new java.util.ArrayList();
+            }
+        }
     }
 
     /**
@@ -131,6 +137,7 @@ public class TableRow extends TableFObj {
             ((TableBody) parent).pendingSpans = pendingSpans;
         }
         ((TableBody) parent).resetColumnIndex();
+        columnIndex = 1;
         //release references
         pendingSpans = null;
         usedColumnIndices = null;
@@ -141,64 +148,14 @@ public class TableRow extends TableFObj {
      * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
      * XSL Content Model: (table-cell+)
      */
-    protected void validateChildNode(Locator loc, String nsURI, String localName) 
+    protected void validateChildNode(Locator loc, String nsURI, 
+                                     String localName) 
         throws ValidationException {
         if (!(FO_URI.equals(nsURI) && localName.equals("table-cell"))) {
             invalidChildError(loc, nsURI, localName);
         }
     }
     
-    /**
-     * @see org.apache.fop.fo.FONode#addChildNode(FONode)
-     */
-    protected void addChildNode(FONode child) throws FOPException {
-        TableCell cell = (TableCell) child;
-        int rowSpan = cell.getNumberRowsSpanned();
-        int colSpan = cell.getNumberColumnsSpanned();
-        if (((TableBody) parent).isFirst(this) 
-                && getTable().columns == null ) {
-            if (pendingSpans == null) {
-                pendingSpans = new java.util.ArrayList();
-            }
-            pendingSpans.add(null);
-            if (usedColumnIndices == null) {
-                usedColumnIndices = new BitSet();
-            }
-        }
-        //if the current cell spans more than one row,
-        //update pending span list for the next row
-        if (rowSpan > 1) {
-            for (int i = colSpan; --i >= 0;) {
-                pendingSpans.set(columnIndex - 1 + i, 
-                        new PendingSpan(rowSpan));
-            }
-        }
-        //flag column indices used by this cell,
-        //take into account that possibly not all column-numbers
-        //are used by columns in the parent table (if any),
-        //so a cell spanning three columns, might actually
-        //take up more than three columnIndices...
-        int startIndex = columnIndex - 1;
-        int endIndex = startIndex + colSpan;
-        if (getTable().columns != null) {
-            List cols = getTable().columns;
-            int tmpIndex = endIndex;
-            for (int i = startIndex; i <= tmpIndex; ++i) {
-                if (i < cols.size() && cols.get(i) == null) {
-                    endIndex++;
-                }
-            }
-        }
-        for (int i = startIndex; i < endIndex; i++) {
-            usedColumnIndices.set(i);
-        }
-        //update columnIndex for the next cell
-        while (usedColumnIndices.get(columnIndex - 1)) {
-            columnIndex++;
-        }
-        super.addChildNode(cell);
-    }
-
     /**
      * @return the "id" property.
      */
@@ -232,7 +189,8 @@ public class TableRow extends TableFObj {
     }
 
     /**
-     * Convenience method to check if a keep-together constraint is specified.
+     * Convenience method to check if a keep-together 
+     * constraint is specified.
      * @return true if keep-together is active.
      */
     public boolean mustKeepTogether() {
@@ -241,7 +199,8 @@ public class TableRow extends TableFObj {
     }
     
     /**
-     * Convenience method to check if a keep-with-next constraint is specified.
+     * Convenience method to check if a keep-with-next 
+     * constraint is specified.
      * @return true if keep-with-next is active.
      */
     public boolean mustKeepWithNext() {
@@ -250,7 +209,8 @@ public class TableRow extends TableFObj {
     }
     
     /**
-     * Convenience method to check if a keep-with-previous constraint is specified.
+     * Convenience method to check if a keep-with-previous 
+     * constraint is specified.
      * @return true if keep-with-previous is active.
      */
     public boolean mustKeepWithPrevious() {
@@ -301,7 +261,7 @@ public class TableRow extends TableFObj {
     /**
      * Sets the current column index to a specific value
      * in case a column-number was explicitly specified
-     * (used by TableCell.bind())
+     * (used by ColumnNumberPropertyMaker.make())
      * 
      * @param newIndex  new value for column index
      */
@@ -319,4 +279,24 @@ public class TableRow extends TableFObj {
     public boolean isColumnNumberUsed(int colNr) {
         return usedColumnIndices.get(colNr - 1);
     }
+    
+    /**
+     * @see org.apache.fop.fo.flow.TableFObj#flagColumnIndices(int, int)
+     */
+    protected void flagColumnIndices(int start, int end) {
+        for (int i = start; i < end; i++) {
+            usedColumnIndices.set(i);
+        }
+        // update columnIndex for the next cell
+        while (usedColumnIndices.get(columnIndex - 1)) {
+            columnIndex++;
+        }
+    }
+    
+    /**
+     * @see org.apache.fop.fo.flow.TableFObj#existsUsedColumnIndices()
+     */
+    protected boolean existsUsedColumnIndices() {
+        return (usedColumnIndices != null);
+    }
 }
index f425b1a08f549553e5c5ec5f749dea439914a5a3..21af6657a9742ba889dc1590d06fc7a9a07e5e65 100644 (file)
 
 package org.apache.fop.fo.properties;
 
+import java.util.Iterator;
+
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.expr.PropertyException;
 import org.apache.fop.fo.flow.TableBody;
+import org.apache.fop.fo.flow.TableCell;
 import org.apache.fop.fo.flow.TableFObj;
 
 /**
@@ -32,40 +35,38 @@ import org.apache.fop.fo.flow.TableFObj;
  */
 public class ColumnNumberPropertyMaker extends NumberProperty.Maker {
 
+    /**
+     * Constructor
+     * @param propId    the id of the property for which the maker should be created
+     */
     public ColumnNumberPropertyMaker(int propId) {
         super(propId);
     }
 
     /**
-     * Set default column-number from parent's currentColumnIndex.
-     *
-     * @param   propertyList
-     * @return  the default value for column-number
-     * @throws  PropertyException
+     * @see PropertyMaker#make(PropertyList)
      */
     public Property make(PropertyList propertyList) throws PropertyException {
         FObj fo = propertyList.getFObj();
 
         if (fo.getNameId() == Constants.FO_TABLE_CELL
                 || fo.getNameId() == Constants.FO_TABLE_COLUMN) {
-            TableFObj parent = (TableFObj) propertyList.getParentFObj();
-            int columnIndex = parent.getCurrentColumnIndex();
             if (fo.getNameId() == Constants.FO_TABLE_CELL
-                    && parent.getNameId() == Constants.FO_TABLE_BODY) {
-                boolean startsRow = propertyList.get(Constants.PR_STARTS_ROW)
-                    .getEnum() == Constants.EN_TRUE;
-
-                //cell w/ starts-row="true", but previous cell
-                //didn't have ends-row="true", so index has still has
-                //to be reset (for other cases this already happened in
-                //body.addChildNode())
-                if (startsRow && !((TableBody) parent).lastCellEndedRow()) {
-                    //reset column index, and reassign...
-                    ((TableBody) parent).resetColumnIndex();
-                    columnIndex = parent.getCurrentColumnIndex();
+                    && fo.getParent().getNameId() != Constants.FO_TABLE_ROW
+                    && (propertyList.get(Constants.PR_STARTS_ROW).getEnum() 
+                            == Constants.EN_TRUE)) {
+                TableBody parent = (TableBody) fo.getParent();
+                TableCell prevCell = null;                
+                for (Iterator i = parent.getChildNodes(); 
+                        (i != null && i.hasNext());) {
+                    prevCell = (TableCell) i.next();
+                }
+                if (prevCell != null && !prevCell.endsRow()) {
+                    parent.resetColumnIndex();
                 }
             }
-            return new NumberProperty(columnIndex);
+            return new NumberProperty(((TableFObj) fo.getParent())
+                                        .getCurrentColumnIndex());
         } else {
             throw new PropertyException("column-number property is only allowed"
                     + " on fo:table-cell or fo:table-column, not on "
@@ -78,7 +79,8 @@ public class ColumnNumberPropertyMaker extends NumberProperty.Maker {
      * Return the parent's column index (initial value) in case 
      * of a negative or zero value
      * 
-     * @see org.apache.fop.fo.properties.PropertyMaker#get(int, PropertyList, boolean, boolean)
+     * @see org.apache.fop.fo.properties.PropertyMaker#get(
+     *                      int, PropertyList, boolean, boolean)
      */
     public Property get(int subpropId, PropertyList propertyList,
                         boolean tryInherit, boolean tryDefault) 
@@ -97,32 +99,7 @@ public class ColumnNumberPropertyMaker extends NumberProperty.Maker {
             return new NumberProperty(parent.getCurrentColumnIndex());
         }
         //TODO: check for non-integer value and round
-        
-        if (fo.getNameId() == Constants.FO_TABLE_CELL) {
-            //check if any of the column-numbers occupied by this cell
-            //are already in use in the current row...
-            int i = -1;
-            int colspan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED)
-                            .getNumeric().getValue();
-            while (++i < colspan) {
-                //if table has explicit columns and the column-number isn't
-                //assigned to any column, increment further until the next
-                //column is encountered
-                if (fo.getTable().getColumns() != null) {
-                    while (columnIndex <= fo.getTable().getColumns().size()
-                            && !fo.getTable().isColumnNumberUsed(columnIndex)) {
-                        columnIndex++;
-                    }
-                }
-                //if column-number is already in use by another cell
-                //in the current row => error!
-                if (parent.isColumnNumberUsed(columnIndex + i)) {
-                    throw new PropertyException("fo:table-cell overlaps in column "
-                            + (columnIndex + i));
-                }
-            }
-        }
-        
+                
         //if column-number was explicitly specified, force the parent's current
         //column index to the specified value, so that the updated index will
         //be the correct initial value for the next cell/column (see Rec 7.26.8)
index 86108b6254389e22a681b6c232e1a4a93fc5f23b..f14694fe1f0f4d11c484f798ee141957bdfa7223 100644 (file)
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Code" dev="AD" type="fix" fixes-bug="39560">
+        Bugfix: the interaction between the table FOs and properties package in
+        determining initial values for column-number should be a one-time process,
+        not repeated when the table is in a marker that is retrieved.
+      </action>
       <action context="Code" dev="JM" type="fix">
         Bugfix: All fonts names were converted unnecessarily to lower case in RTF output.
       </action>
         Bugfix: Text-decoration was not promoted if no text-decoration attribute was
         specified on a nested element.
       </action>
-      <action context="Code" dev="AD" type="add">
+      <action context="Code" dev="AD" type="add" fixes-bug="38282"
+              due-to="Gerhard Oettl (gerhard.oettl.at.oesoft.at)">
         Added support for the from-table-column() function.
-        (Thanks to gerhard.oettl.at.oesoft.at for the inspiration.)
       </action>
       <action context="Code" dev="JM" type="fix" fixes-bug="38397">
         Bugfix: Spanned cells could lead to an false error message about overlapping 
index 5725a4ebdb48543c0e76a4fe3bea19605773ca4a..f505f92a9029d39946a3a472d9dd083459c52cee 100644 (file)
     <description>TODO: Same as table-column_first-row-width.xml?</description>
     <reference>http://issues.apache.org/bugzilla/show_bug.cgi?id=35656</reference>
   </testcase>
-  <testcase>
-    <name>table in marker (Bug 39560)</name>
-    <file>table_in_marker_bug39560.xml</file>
-    <description>When a table is put in a marker and that is referenced using retrieve-marker, an NPE occurs during the cloning process.</description>
-    <reference>http://issues.apache.org/bugzilla/show_bug.cgi?id=39560</reference>
-  </testcase>
   <testcase>
     <name>table-cell empty area with marker.xml</name>
     <file>table-cell_empty_area_with_marker.xml</file>