From 3b9321e248bc6100b73afff706d919817999904f Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Mon, 21 Aug 2006 17:18:37 +0000 Subject: [PATCH] Rework of default column-creation and setting column-widths from the first row (fixes Bugzilla 35656) git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@433291 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/fo/FOPropertyMapping.java | 3 +- src/java/org/apache/fop/fo/flow/Table.java | 129 ++++++++++++------ .../org/apache/fop/fo/flow/TableBody.java | 45 +++++- .../org/apache/fop/fo/flow/TableCaption.java | 7 + .../org/apache/fop/fo/flow/TableCell.java | 32 +++-- .../org/apache/fop/fo/flow/TableColumn.java | 89 ++++++++---- .../org/apache/fop/fo/flow/TableFObj.java | 37 ++--- src/java/org/apache/fop/fo/flow/TableRow.java | 38 ++++++ .../table/CollapsingBorderModel.java | 2 +- .../fop/layoutmgr/table/ColumnSetup.java | 92 +++++++++++-- .../layoutmgr/table/TableLayoutManager.java | 31 ++--- status.xml | 4 + test/layoutengine/disabled-testcases.xml | 14 -- 13 files changed, 370 insertions(+), 153 deletions(-) diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index bf23e4d97..79c7eb0d5 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -2299,7 +2299,8 @@ public final class FOPropertyMapping implements Constants { // column-width m = new LengthProperty.Maker(PR_COLUMN_WIDTH); m.setInherited(false); - m.setDefault("proportional-column-width(1)", true); + m.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO")); + m.setDefault("auto"); m.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH); addPropertyMaker("column-width", m); diff --git a/src/java/org/apache/fop/fo/flow/Table.java b/src/java/org/apache/fop/fo/flow/Table.java index 9a4724ed4..5ea294064 100644 --- a/src/java/org/apache/fop/fo/flow/Table.java +++ b/src/java/org/apache/fop/fo/flow/Table.java @@ -25,6 +25,7 @@ import java.util.List; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.datatypes.Length; import org.apache.fop.datatypes.ValidationPercentBaseContext; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; @@ -44,7 +45,8 @@ import org.apache.fop.fo.properties.LengthRangeProperty; * Class modelling the fo:table object. */ public class Table extends TableFObj { - // The value of properties relevant for fo:table. + + /** properties */ private CommonAccessibility commonAccessibility; private CommonAural commonAural; private CommonBorderPaddingBackground commonBorderPaddingBackground; @@ -58,23 +60,24 @@ public class Table extends TableFObj { private String id; private LengthRangeProperty inlineProgressionDimension; private int intrusionDisplace; - //private Length height; private KeepProperty keepTogether; private KeepProperty keepWithNext; private KeepProperty keepWithPrevious; private int tableLayout; private int tableOmitFooterAtBreak; private int tableOmitHeaderAtBreak; - //private Length width; private int writingMode; - // End of property values private static final int MINCOLWIDTH = 10000; // 10pt /** collection of columns in this table */ protected List columns = null; + + /** helper variables for implicit column-numbering */ private int columnIndex = 1; private BitSet usedColumnIndices = new BitSet(); + + /** the table-header and -footer */ private TableBody tableHeader = null; private TableBody tableFooter = null; @@ -84,10 +87,12 @@ public class Table extends TableFObj { 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. */ - private TableColumn defaultColumn; + /** + * The table's property list. Used in case the table has + * no explicit columns, as a parent property list to + * internally generated TableColumns + */ + private PropertyList propList; /** * @param parent FONode that is the parent of this object @@ -113,23 +118,15 @@ public class Table extends TableFObj { id = pList.get(PR_ID).getString(); inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange(); intrusionDisplace = pList.get(PR_INTRUSION_DISPLACE).getEnum(); - //height = pList.get(PR_HEIGHT).getLength(); keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep(); keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep(); tableLayout = pList.get(PR_TABLE_LAYOUT).getEnum(); tableOmitFooterAtBreak = pList.get(PR_TABLE_OMIT_FOOTER_AT_BREAK).getEnum(); tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum(); - //width = pList.get(PR_WIDTH).getLength(); writingMode = pList.get(PR_WRITING_MODE).getEnum(); super.bind(pList); - - //Create default column in case no table-columns will be defined. - defaultColumn = new TableColumn(this, true); - PropertyList colPList = new StaticPropertyList(defaultColumn, pList); - colPList.setWritingMode(); - defaultColumn.bind(colPList); - + if (borderCollapse != EN_SEPARATE) { //TODO Remove once the collapsing border is at least marginally working. borderCollapse = EN_SEPARATE; @@ -140,13 +137,22 @@ public class Table extends TableFObj { if (tableLayout == EN_AUTO) { attributeWarning("table-layout=\"auto\" is currently not supported by FOP"); } - if (!isSeparateBorderModel() && getCommonBorderPaddingBackground().hasPadding( - ValidationPercentBaseContext.getPseudoContextForValidationPurposes())) { + if (!isSeparateBorderModel() + && getCommonBorderPaddingBackground().hasPadding( + ValidationPercentBaseContext + .getPseudoContextForValidationPurposes())) { //See "17.6.2 The collapsing border model" in CSS2 attributeWarning("In collapsing border model a table does not have padding" + " (see http://www.w3.org/TR/REC-CSS2/tables.html#collapsing-borders)" + ", but a non-zero value for padding was found. The padding will be ignored."); } + + /* Store reference to the property list, so + * new lists can be created in case the table has no + * explicit columns + * (see addDefaultColumn()) + */ + this.propList = pList; } /** @@ -164,19 +170,19 @@ public class Table extends TableFObj { protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { - if (localName.equals("marker")) { + if ("marker".equals(localName)) { if (tableColumnFound || tableHeaderFound || tableFooterFound || tableBodyFound) { nodesOutOfOrderError(loc, "fo:marker", "(table-column*,table-header?,table-footer?,table-body+)"); } - } else if (localName.equals("table-column")) { + } else if ("table-column".equals(localName)) { tableColumnFound = true; if (tableHeaderFound || tableFooterFound || tableBodyFound) { nodesOutOfOrderError(loc, "fo:table-column", "(table-header?,table-footer?,table-body+)"); } - } else if (localName.equals("table-header")) { + } else if ("table-header".equals(localName)) { if (tableHeaderFound) { tooManyNodesError(loc, "table-header"); } else { @@ -186,7 +192,7 @@ public class Table extends TableFObj { "(table-footer?,table-body+)"); } } - } else if (localName.equals("table-footer")) { + } else if ("table-footer".equals(localName)) { if (tableFooterFound) { tooManyNodesError(loc, "table-footer"); } else { @@ -196,7 +202,7 @@ public class Table extends TableFObj { "(table-body+)"); } } - } else if (localName.equals("table-body")) { + } else if ("table-body".equals(localName)) { tableBodyFound = true; } else { invalidChildError(loc, nsURI, localName); @@ -217,23 +223,28 @@ public class Table extends TableFObj { + ",table-body+)"); } if (!inMarker()) { - if (columns != null && !columns.isEmpty()) { - for (int i = columns.size(); --i >= 0;) { - TableColumn col = (TableColumn) columns.get(i); - if (col != null) { - col.releasePropertyList(); - } + /* clean up */ + for (int i = columns.size(); --i >= 0;) { + TableColumn col = (TableColumn) columns.get(i); + if (col != null) { + col.releasePropertyList(); } } + this.propList = null; } getFOEventHandler().endTable(this); + } /** * @see org.apache.fop.fo.FONode#addChildNode(FONode) */ protected void addChildNode(FONode child) throws FOPException { - if ("fo:table-column".equals(child.getName())) { + + int childId = child.getNameId(); + + switch (childId) { + case FO_TABLE_COLUMN: if (columns == null) { columns = new java.util.ArrayList(); } @@ -242,17 +253,48 @@ public class Table extends TableFObj { } else { columns.add((TableColumn) child); } - } else { - if ("fo:table-footer".equals(child.getName())) { + return; + case FO_MARKER: + super.addChildNode(child); + return; + default: + switch (childId) { + case FO_TABLE_FOOTER: tableFooter = (TableBody) child; - } else if ("fo:table-header".equals(child.getName())) { + break; + case FO_TABLE_HEADER: tableHeader = (TableBody) child; - } else { - // add bodies + break; + default: super.addChildNode(child); } } } + + /** + * Adds a default column to the columns list (called from + * TableBody.addChildNode() when the table has no explicit + * columns, and if processing the first row) + * + * @param colWidth the column's width (null if the default should be used) + * @param colNr the column-number from the cell + * @throws FOPException if there was an error creating the property list + */ + protected void addDefaultColumn(Length colWidth, int colNr) + throws FOPException { + TableColumn defaultColumn = new TableColumn(this, true); + PropertyList pList = new StaticPropertyList( + defaultColumn, this.propList); + pList.setWritingMode(); + defaultColumn.bind(pList); + if (colWidth != null) { + defaultColumn.setColumnWidth(colWidth); + } + if (colNr != 0) { + defaultColumn.setColumnNumber(colNr); + } + addColumnNode(defaultColumn); + } /** * Adds a column to the columns List, and updates the columnIndex @@ -262,17 +304,22 @@ public class Table extends TableFObj { * @throws FOPException */ private void addColumnNode(TableColumn col) { + int colNumber = col.getColumnNumber(); int colRepeat = col.getNumberColumnsRepeated(); + if (columns.size() < colNumber) { - //add nulls for non-occupied indices between - //the last column up to and including the current one + /* add nulls for non-occupied indices between + /* the last column up to and including the current one + */ while (columns.size() < colNumber) { columns.add(null); } } - //replace the null-value with the actual column + + /* replace the null-value with the actual column */ columns.set(colNumber - 1, col); + if (colRepeat > 1) { //in case column is repeated: //for the time being, add the same column @@ -290,12 +337,12 @@ public class Table extends TableFObj { /** @return true of table-layout="auto" */ public boolean isAutoLayout() { - return (tableLayout != EN_FIXED); + return (tableLayout == EN_AUTO); } /** @return the default table column */ public TableColumn getDefaultColumn() { - return this.defaultColumn; + return (TableColumn) this.columns.get(0); } /** @return the list of table-column elements. */ diff --git a/src/java/org/apache/fop/fo/flow/TableBody.java b/src/java/org/apache/fop/fo/flow/TableBody.java index 0a50b946d..8b0420e2f 100644 --- a/src/java/org/apache/fop/fo/flow/TableBody.java +++ b/src/java/org/apache/fop/fo/flow/TableBody.java @@ -29,6 +29,7 @@ import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; +import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; @@ -186,8 +187,48 @@ public class TableBody extends TableFObj { */ protected void addChildNode(FONode child) throws FOPException { if (!inMarker()) { - if (firstRow && child.getNameId() == FO_TABLE_ROW) { - firstRow = false; + if (firstRow) { + Table t = getTable(); + + if (t.columns == null) { + t.columns = new java.util.ArrayList(); + } + + switch (child.getNameId()) { + case FO_TABLE_ROW: + firstRow = false; + break; + case FO_TABLE_CELL: + TableCell cell = (TableCell) child; + int colNr = cell.getColumnNumber(); + int colSpan = cell.getNumberColumnsSpanned(); + Length colWidth = null; + + if (cell.getWidth().getEnum() != EN_AUTO + && colSpan == 1) { + colWidth = cell.getWidth(); + } + + for (int i = colNr; i < colNr + colSpan; ++i) { + if (t.columns.size() < i + || t.columns.get(i - 1) == null) { + t.addDefaultColumn(colWidth, + i == colNr + ? cell.getColumnNumber() + : 0); + } else { + TableColumn col = + (TableColumn) t.columns.get(i - 1); + if (!col.isDefaultColumn() + && colWidth != null) { + col.setColumnWidth(colWidth); + } + } + } + break; + default: + //nop + } } } super.addChildNode(child); diff --git a/src/java/org/apache/fop/fo/flow/TableCaption.java b/src/java/org/apache/fop/fo/flow/TableCaption.java index 6df6d2e9b..21ea0492f 100644 --- a/src/java/org/apache/fop/fo/flow/TableCaption.java +++ b/src/java/org/apache/fop/fo/flow/TableCaption.java @@ -96,6 +96,13 @@ public class TableCaption extends FObj { checkId(id); } + /** + * @return the Common Border, Padding, and Background Properties. + */ + public CommonBorderPaddingBackground getCommonBorderPaddingBackground() { + return commonBorderPaddingBackground; + } + /** * Make sure content model satisfied, if so then tell the * FOEventHandler that we are at the end of the flow. diff --git a/src/java/org/apache/fop/fo/flow/TableCell.java b/src/java/org/apache/fop/fo/flow/TableCell.java index 467a2a856..b349a8bde 100644 --- a/src/java/org/apache/fop/fo/flow/TableCell.java +++ b/src/java/org/apache/fop/fo/flow/TableCell.java @@ -19,10 +19,6 @@ package org.apache.fop.fo.flow; -import java.util.BitSet; -import java.util.List; - -import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; @@ -31,7 +27,6 @@ import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; -import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.properties.CommonAccessibility; import org.apache.fop.fo.properties.CommonAural; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; @@ -50,7 +45,7 @@ public class TableCell extends TableFObj { private CommonBorderPaddingBackground commonBorderPaddingBackground; private CommonRelativePosition commonRelativePosition; private LengthRangeProperty blockProgressionDimension; - private Numeric columnNumber; + private int columnNumber; private int displayAlign; private int relativeAlign; private int emptyCells; @@ -58,8 +53,8 @@ public class TableCell extends TableFObj { private Length height; private String id; private LengthRangeProperty inlineProgressionDimension; - private Numeric numberColumnsSpanned; - private Numeric numberRowsSpanned; + private int numberColumnsSpanned; + private int numberRowsSpanned; private int startsRow; private Length width; private KeepProperty keepTogether; @@ -123,9 +118,9 @@ public class TableCell extends TableFObj { height = pList.get(PR_HEIGHT).getLength(); id = pList.get(PR_ID).getString(); inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange(); - columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric(); - numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED).getNumeric(); - numberRowsSpanned = pList.get(PR_NUMBER_ROWS_SPANNED).getNumeric(); + columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue(); + numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED).getNumeric().getValue(); + numberRowsSpanned = pList.get(PR_NUMBER_ROWS_SPANNED).getNumeric().getValue(); startsRow = pList.get(PR_STARTS_ROW).getEnum(); width = pList.get(PR_WIDTH).getLength(); keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep(); @@ -207,9 +202,9 @@ public class TableCell extends TableFObj { * @return the "column-number" property. */ public int getColumnNumber() { - return columnNumber.getValue(); + return columnNumber; } - + /** @return true if "empty-cells" is "show" */ public boolean showEmptyCells() { return (this.emptyCells == EN_SHOW); @@ -226,14 +221,14 @@ public class TableCell extends TableFObj { * @return the "number-columns-spanned" property. */ public int getNumberColumnsSpanned() { - return Math.max(numberColumnsSpanned.getValue(), 1); + return Math.max(numberColumnsSpanned, 1); } /** * @return the "number-rows-spanned" property. */ public int getNumberRowsSpanned() { - return Math.max(numberRowsSpanned.getValue(), 1); + return Math.max(numberRowsSpanned, 1); } /** @@ -248,6 +243,13 @@ public class TableCell extends TableFObj { return displayAlign; } + /** + * @return the "width" property. + */ + public Length getWidth() { + return width; + } + /** @return true if the cell starts a row. */ public boolean startsRow() { return (startsRow == EN_TRUE); diff --git a/src/java/org/apache/fop/fo/flow/TableColumn.java b/src/java/org/apache/fop/fo/flow/TableColumn.java index c82eb474a..61c68fd03 100644 --- a/src/java/org/apache/fop/fo/flow/TableColumn.java +++ b/src/java/org/apache/fop/fo/flow/TableColumn.java @@ -24,14 +24,13 @@ 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.PropertyList; -import org.apache.fop.fo.StaticPropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.Property; +import org.apache.fop.fo.properties.TableColLength; /** * Class modelling the fo:table-column object. @@ -39,15 +38,15 @@ import org.apache.fop.fo.properties.Property; public class TableColumn extends TableFObj { // The value of properties relevant for fo:table-column. private CommonBorderPaddingBackground commonBorderPaddingBackground; - private Numeric columnNumber; + private int columnNumber; private Length columnWidth; - private Numeric numberColumnsRepeated; - private Numeric numberColumnsSpanned; + private int numberColumnsRepeated; + private int numberColumnsSpanned; private int visibility; // End of property values private boolean defaultColumn; - private StaticPropertyList pList = null; + private PropertyList pList = null; /** * @param parent FONode that is the parent of this object @@ -71,22 +70,44 @@ public class TableColumn extends TableFObj { */ public void bind(PropertyList pList) throws FOPException { commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps(); - columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric(); + columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue(); columnWidth = pList.get(PR_COLUMN_WIDTH).getLength(); - numberColumnsRepeated = pList.get(PR_NUMBER_COLUMNS_REPEATED).getNumeric(); - numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED).getNumeric(); + numberColumnsRepeated = pList.get(PR_NUMBER_COLUMNS_REPEATED) + .getNumeric().getValue(); + numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED) + .getNumeric().getValue(); visibility = pList.get(PR_VISIBILITY).getEnum(); super.bind(pList); - if (numberColumnsRepeated.getValue() <= 0) { + if (numberColumnsRepeated <= 0) { throw new PropertyException("number-columns-repeated must be 1 or bigger, " - + "but got " + numberColumnsRepeated.getValue()); + + "but got " + numberColumnsRepeated); } - if (numberColumnsSpanned.getValue() <= 0) { + if (numberColumnsSpanned <= 0) { throw new PropertyException("number-columns-spanned must be 1 or bigger, " - + "but got " + numberColumnsSpanned.getValue()); + + "but got " + numberColumnsSpanned); + } + + /* check for unspecified width and replace with default of + * proportional-column-width(1), in case of fixed table-layout + * warn only for explicit columns + */ + if (columnWidth.getEnum() == EN_AUTO) { + if (!this.defaultColumn && !getTable().isAutoLayout()) { + log.warn("table-layout=\"fixed\" and column-width unspecified " + + "=> falling back to proportional-column-width(1)"); + } + columnWidth = new TableColLength(1.0, this); + } + + /* in case of explicit columns, from-table-column() + * can be used on descendants of the table-cells, so + * we need a reference to the column's property list + * (cleared in Table.endOfNode()) + */ + if (!this.defaultColumn) { + this.pList = pList; } - this.pList = new StaticPropertyList(this, pList); } /** @@ -107,7 +128,8 @@ public class TableColumn extends TableFObj { * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String) * XSL Content Model: empty */ - protected void validateChildNode(Locator loc, String nsURI, String localName) + protected void validateChildNode(Locator loc, + String nsURI, String localName) throws ValidationException { invalidChildError(loc, nsURI, localName); } @@ -138,17 +160,25 @@ public class TableColumn extends TableFObj { * @return the "column-number" property. */ public int getColumnNumber() { - return columnNumber.getValue(); + return columnNumber; + } + + /** + * Used for setting the column-number for an implicit column + * @param columnNumber + */ + protected void setColumnNumber(int columnNumber) { + this.columnNumber = columnNumber; } /** @return value for number-columns-repeated. */ public int getNumberColumnsRepeated() { - return numberColumnsRepeated.getValue(); + return numberColumnsRepeated; } /** @return value for number-columns-spanned. */ public int getNumberColumnsSpanned() { - return numberColumnsSpanned.getValue(); + return numberColumnsSpanned; } /** @see org.apache.fop.fo.FONode#getLocalName() */ @@ -162,8 +192,10 @@ public class TableColumn extends TableFObj { } /** - * Indicates whether this table-column has been created as default column for this table in - * case no table-columns have been defined. Note that this only used to provide better + * Indicates whether this table-column has been created as + * default column for this table in case no table-columns + * have been defined. + * Note that this only used to provide better * user feedback (see ColumnSetup). * @return true if this table-column has been created as default column */ @@ -176,31 +208,34 @@ public class TableColumn extends TableFObj { StringBuffer sb = new StringBuffer("fo:table-column"); sb.append(" column-number=").append(getColumnNumber()); if (getNumberColumnsRepeated() > 1) { - sb.append(" number-columns-repeated=").append(getNumberColumnsRepeated()); + sb.append(" number-columns-repeated=") + .append(getNumberColumnsRepeated()); } if (getNumberColumnsSpanned() > 1) { - sb.append(" number-columns-spanned=").append(getNumberColumnsSpanned()); + sb.append(" number-columns-spanned=") + .append(getNumberColumnsSpanned()); } sb.append(" column-width=").append(getColumnWidth()); return sb.toString(); } /** - * Retrieve a property value through its Id; used by from-table-column() function + * Retrieve a property value through its Id; used by + * from-table-column() function * * @param propId the id for the property to retrieve * @return the requested Property * @throws PropertyException */ public Property getProperty(int propId) throws PropertyException { - return this.pList.getInherited(propId); + return this.pList.get(propId); } /** - * Clear the reference to the PropertyList (retained for from-table-column()) - * + * Clear the reference to the PropertyList (retained for + * from-table-column()) */ protected void releasePropertyList() { this.pList = null; - } + } } \ No newline at end of file diff --git a/src/java/org/apache/fop/fo/flow/TableFObj.java b/src/java/org/apache/fop/fo/flow/TableFObj.java index d2ea03d35..a5370a36d 100644 --- a/src/java/org/apache/fop/fo/flow/TableFObj.java +++ b/src/java/org/apache/fop/fo/flow/TableFObj.java @@ -367,24 +367,27 @@ public abstract class TableFObj extends FObj { Property p = super.get(0, propertyList, tryInherit, tryDefault); TableFObj fo = (TableFObj) propertyList.getFObj(); TableFObj parent = (TableFObj) propertyList.getParentFObj(); - int columnIndex = p.getNumeric().getValue(); - if (columnIndex <= 0) { - fo.getLogger().warn("Specified negative or zero value for " - + "column-number on " + fo.getName() + ": " - + columnIndex + " forced to " - + parent.getCurrentColumnIndex()); - return new NumberProperty(parent.getCurrentColumnIndex()); - } - //TODO: check for non-integer value and round - - /* 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) - */ - if (propertyList.getExplicit(Constants.PR_COLUMN_NUMBER) != null) { - parent.setCurrentColumnIndex(p.getNumeric().getValue()); + if (p != null) { + int columnIndex = p.getNumeric().getValue(); + + if (columnIndex <= 0) { + fo.getLogger().warn("Specified negative or zero value for " + + "column-number on " + fo.getName() + ": " + + columnIndex + " forced to " + + parent.getCurrentColumnIndex()); + return new NumberProperty(parent.getCurrentColumnIndex()); + } + //TODO: check for non-integer value and round + + /* 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) + */ + if (propertyList.getExplicit(Constants.PR_COLUMN_NUMBER) != null) { + parent.setCurrentColumnIndex(p.getNumeric().getValue()); + } } return p; } diff --git a/src/java/org/apache/fop/fo/flow/TableRow.java b/src/java/org/apache/fop/fo/flow/TableRow.java index 1f0cb14ae..09310afad 100644 --- a/src/java/org/apache/fop/fo/flow/TableRow.java +++ b/src/java/org/apache/fop/fo/flow/TableRow.java @@ -123,6 +123,44 @@ public class TableRow extends TableFObj { super.processNode(elementName, locator, attlist, pList); } + /** + * @see org.apache.fop.fo.FONode#addChildNode(FONode) + */ + protected void addChildNode(FONode child) throws FOPException { + if (!inMarker()) { + Table t = getTable(); + TableBody body = (TableBody) getParent(); + if (body.isFirst(this)) { + TableCell cell = (TableCell) child; + int colNr = cell.getColumnNumber(); + int colSpan = cell.getNumberColumnsSpanned(); + Length colWidth = null; + + if (cell.getWidth().getEnum() != EN_AUTO + && colSpan == 1) { + colWidth = cell.getWidth(); + } + + for (int i = colNr; i < colNr + colSpan; ++i) { + if (t.columns.size() < i + || t.columns.get(i - 1) == null) { + t.addDefaultColumn(colWidth, + i == colNr + ? cell.getColumnNumber() + : 0); + } else { + TableColumn col = (TableColumn) t.columns.get(i - 1); + if (!col.isDefaultColumn() + && colWidth != null) { + col.setColumnWidth(colWidth); + } + } + } + } + } + super.addChildNode(child); + } + /** * @see org.apache.fop.fo.FONode#startOfNode */ diff --git a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java index 0807bf7ae..5c60ee6fd 100644 --- a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java +++ b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java @@ -118,7 +118,7 @@ public abstract class CollapsingBorderModel { case Constants.EN_RIDGE: return -4; case Constants.EN_OUTSET: return -5; case Constants.EN_GROOVE: return -6; - case Constants.EN_INSET: return -6; + case Constants.EN_INSET: return -7; default: throw new IllegalStateException("Illegal border style: " + style); } } diff --git a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java index be72722af..b836b241e 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java +++ b/src/java/org/apache/fop/layoutmgr/table/ColumnSetup.java @@ -26,10 +26,12 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.datatypes.PercentBaseContext; +import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.flow.Table; import org.apache.fop.fo.flow.TableColumn; +import org.apache.fop.fo.properties.TableColLength; /** * Class holding a number of columns making up the column setup of a row. @@ -41,6 +43,8 @@ public class ColumnSetup { private Table table; private List columns = new java.util.ArrayList(); + private List colWidths = new java.util.ArrayList(); + private int maxColIndexReferenced = 0; /** @@ -49,13 +53,11 @@ public class ColumnSetup { */ public ColumnSetup(Table table) { this.table = table; - prepareExplicitColumns(); - if (getColumnCount() == 0) { - createColumnsFromFirstRow(); - } + prepareColumns(); + initializeColumnWidths(); } - private void prepareExplicitColumns() { + private void prepareColumns() { List rawCols = table.getColumns(); if (rawCols != null) { int colnum = 1; @@ -100,10 +102,11 @@ public class ColumnSetup { maxColIndexReferenced = index; if (!(size == 1 && getColumn(1).isDefaultColumn())) { log.warn(FONode.decorateWithContextInfo( - "There are fewer table-columns than are needed. Column " - + index + " was accessed although only " + "There are fewer table-columns than are needed. " + + "Column " + index + " was accessed, but only " + size + " columns have been defined. " - + "The last defined column will be reused.", table)); + + "The last defined column will be reused." + , table)); if (!table.isAutoLayout()) { log.warn("Please note that according XSL-FO 1.0 (7.26.9) says that " + "the 'column-width' property must be specified for every " @@ -111,9 +114,9 @@ public class ColumnSetup { } } } - return (TableColumn)columns.get(size - 1); + return (TableColumn) columns.get(size - 1); } else { - return (TableColumn)columns.get(index - 1); + return (TableColumn) columns.get(index - 1); } } @@ -136,6 +139,7 @@ public class ColumnSetup { return this.columns.iterator(); } + /* private void createColumnsFromFirstRow() { //TODO Create oldColumns from first row here //--> rule 2 in "fixed table layout", see CSS2, 17.5.2 @@ -146,7 +150,69 @@ public class ColumnSetup { this.columns.add(table.getDefaultColumn()); } } + */ + /** + * Initializes the column's widths + * + */ + private void initializeColumnWidths() { + + TableColumn col; + Length colWidth; + + for (int i = columns.size(); --i >= 0;) { + if (columns.get(i) != null) { + col = (TableColumn) columns.get(i); + colWidth = col.getColumnWidth(); + colWidths.add(0, colWidth); + } + } + colWidths.add(0, null); + } + + /** + * Works out the base unit for resolving proportional-column-width() + * [p-c-w(x) = x * base_unit_ipd] + * + * @param tlm the TableLayoutManager + * @return the computed base unit (in millipoint) + */ + protected double computeTableUnit(TableLayoutManager tlm) { + + int sumCols = 0; + float factors = 0; + double unit = 0; + + /* calculate the total width (specified absolute/percentages), + * and work out the total number of factors to use to distribute + * the remaining space (if any) + */ + for (Iterator i = colWidths.iterator(); i.hasNext();) { + Length colWidth = (Length) i.next(); + if (colWidth != null) { + sumCols += colWidth.getValue(tlm); + if (colWidth instanceof TableColLength) { + factors += + ((TableColLength) colWidth).getTableUnits(); + } + } + } + + /* distribute the remaining space over the accumulated + * factors (if any) + */ + if (factors > 0) { + if (sumCols < tlm.getContentAreaIPD()) { + unit = (tlm.getContentAreaIPD() - sumCols) / factors; + } else { + log.warn("No space remaining to distribute over columns."); + } + } + + return unit; + } + /** * @param col column index (1 is first column) * @param context the context for percentage based calculations @@ -154,9 +220,9 @@ public class ColumnSetup { */ public int getXOffset(int col, PercentBaseContext context) { int xoffset = 0; - for (int i = 1; i < col; i++) { - if (getColumn(i) != null) { - xoffset += getColumn(i).getColumnWidth().getValue(context); + for (int i = col; --i >= 0;) { + if (colWidths.get(i) != null) { + xoffset += ((Length) colWidths.get(i)).getValue(context); } } return xoffset; diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 7b353edd2..1df3f5b73 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -62,7 +62,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager private Block curBlockArea; - private double tableUnits; + private double tableUnit; private boolean autoLayout = true; private boolean discardBorderBefore; @@ -180,26 +180,11 @@ public class TableLayoutManager extends BlockStackingLayoutManager getTable())); } - // either works out table of column widths or if proportional-column-width function - // is used works out total factor, so that value of single unit can be computed. - int sumCols = 0; - float factors = 0; - for (Iterator i = columns.iterator(); i.hasNext();) { - TableColumn column = (TableColumn) i.next(); - if (column != null) { - Length width = column.getColumnWidth(); - sumCols += width.getValue(this); - if (width instanceof TableColLength) { - factors += ((TableColLength) width).getTableUnits(); - } - } - } - // sets TABLE_UNITS in case where one or more oldColumns is defined using - // proportional-column-width - if (sumCols < getContentAreaIPD()) { - if (tableUnits == 0.0) { - this.tableUnits = (getContentAreaIPD() - sumCols) / factors; - } + /* initialize unit to determine computed values + * for proportional-column-width() + */ + if (tableUnit == 0.0) { + this.tableUnit = columns.computeTableUnit(this); } if (!firstVisibleMarkServed) { @@ -480,6 +465,8 @@ public class TableLayoutManager extends BlockStackingLayoutManager switch (lengthBase) { case LengthBase.CONTAINING_BLOCK_WIDTH: return getContentAreaIPD(); + case LengthBase.TABLE_UNITS: + return (int) this.tableUnit; default: log.error("Unknown base type for LengthBase."); return 0; @@ -487,7 +474,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager } else { switch (lengthBase) { case LengthBase.TABLE_UNITS: - return (int)this.tableUnits; + return (int) this.tableUnit; default: return super.getBaseLength(lengthBase, fobj); } diff --git a/status.xml b/status.xml index 5110ec71d..d013359e6 100644 --- a/status.xml +++ b/status.xml @@ -28,6 +28,10 @@ + + Rework of default column-creation / column-width setting from + cells in the first row. + Added relaxed validation for empty list-item-*, as suggested by Gary Reed. diff --git a/test/layoutengine/disabled-testcases.xml b/test/layoutengine/disabled-testcases.xml index 85d129643..945ded11d 100644 --- a/test/layoutengine/disabled-testcases.xml +++ b/test/layoutengine/disabled-testcases.xml @@ -291,14 +291,6 @@ Border and padding conditionality are not supported on table-cells, yet. - - No table column setup based on the first row. - table-column_first-row-width.xml - According to the spec the table-columns can be set up - automatically based on values on the first row of a table. This is not - implemented, yet. - http://issues.apache.org/bugzilla/show_bug.cgi?id=35656 - No background-images on table-header table-header_background-image.xml @@ -311,12 +303,6 @@ Keep-with-previous doesn't work inside tables and lists, yet. - - table table-layout fixed 2 - table_table-layout_fixed_2.xml - TODO: Same as table-column_first-row-width.xml? - http://issues.apache.org/bugzilla/show_bug.cgi?id=35656 - table-cell empty area with marker.xml table-cell_empty_area_with_marker.xml -- 2.39.5