aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas L. Delmelle <adelmelle@apache.org>2006-06-06 21:52:19 +0000
committerAndreas L. Delmelle <adelmelle@apache.org>2006-06-06 21:52:19 +0000
commitc046ef49bcd7519b816fc1880f97a1fad8db43c9 (patch)
treee9ee6120ec24dcd17e08cc8630def14a82ef3d26
parent404809380b6d0f6bc554835fa2d38007e23a7ba0 (diff)
downloadxmlgraphics-fop-c046ef49bcd7519b816fc1880f97a1fad8db43c9.tar.gz
xmlgraphics-fop-c046ef49bcd7519b816fc1880f97a1fad8db43c9.zip
Fixes Bugzilla 39560: make sure the interaction between FOs and properties is only performed once
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@412224 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/fop/fo/flow/Table.java58
-rw-r--r--src/java/org/apache/fop/fo/flow/TableBody.java168
-rw-r--r--src/java/org/apache/fop/fo/flow/TableCell.java218
-rw-r--r--src/java/org/apache/fop/fo/flow/TableFObj.java20
-rw-r--r--src/java/org/apache/fop/fo/flow/TableRow.java106
-rw-r--r--src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java71
-rw-r--r--status.xml9
-rw-r--r--test/layoutengine/disabled-testcases.xml6
8 files changed, 315 insertions, 341 deletions
diff --git a/src/java/org/apache/fop/fo/flow/Table.java b/src/java/org/apache/fop/fo/flow/Table.java
index dc14f642d..6f2d7f198 100644
--- a/src/java/org/apache/fop/fo/flow/Table.java
+++ b/src/java/org/apache/fop/fo/flow/Table.java
@@ -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);
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/TableBody.java b/src/java/org/apache/fop/fo/flow/TableBody.java
index e970fb7d9..d0b706e33 100644
--- a/src/java/org/apache/fop/fo/flow/TableBody.java
+++ b/src/java/org/apache/fop/fo/flow/TableBody.java
@@ -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);
@@ -151,83 +158,10 @@ 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);
+ }
}
-
diff --git a/src/java/org/apache/fop/fo/flow/TableCell.java b/src/java/org/apache/fop/fo/flow/TableCell.java
index 60826da16..8f9282a5d 100644
--- a/src/java/org/apache/fop/fo/flow/TableCell.java
+++ b/src/java/org/apache/fop/fo/flow/TableCell.java
@@ -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;)+
@@ -188,102 +300,6 @@ public class TableCell extends TableFObj {
}
/**
- * 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.
*/
public CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
@@ -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;
}
}
diff --git a/src/java/org/apache/fop/fo/flow/TableFObj.java b/src/java/org/apache/fop/fo/flow/TableFObj.java
index 729d5a5c2..fb2c72e1b 100644
--- a/src/java/org/apache/fop/fo/flow/TableFObj.java
+++ b/src/java/org/apache/fop/fo/flow/TableFObj.java
@@ -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;
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/TableRow.java b/src/java/org/apache/fop/fo/flow/TableRow.java
index 57da0f190..0827cf779 100644
--- a/src/java/org/apache/fop/fo/flow/TableRow.java
+++ b/src/java/org/apache/fop/fo/flow/TableRow.java
@@ -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,7 +148,8 @@ 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);
@@ -149,57 +157,6 @@ public class TableRow extends TableFObj {
}
/**
- * @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.
*/
public String getId() {
@@ -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);
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java b/src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java
index f425b1a08..21af6657a 100644
--- a/src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java
+++ b/src/java/org/apache/fop/fo/properties/ColumnNumberPropertyMaker.java
@@ -18,11 +18,14 @@
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)
diff --git a/status.xml b/status.xml
index 86108b625..f14694fe1 100644
--- a/status.xml
+++ b/status.xml
@@ -27,6 +27,11 @@
<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>
@@ -196,9 +201,9 @@
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
diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml
index 5725a4ebd..f505f92a9 100644
--- a/test/layoutengine/disabled-testcases.xml
+++ b/test/layoutengine/disabled-testcases.xml
@@ -324,12 +324,6 @@
<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>
<description>A table-cell producing an empty area does currently not add any markers to a page. See TODO entry in AreaAdditionUtil.</description>