aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org
diff options
context:
space:
mode:
authorVincent Hennebert <vhennebert@apache.org>2007-12-13 16:10:32 +0000
committerVincent Hennebert <vhennebert@apache.org>2007-12-13 16:10:32 +0000
commit709bda3d6c3bc23050e6bf69d16b32ed6b35b541 (patch)
tree429aae5baa401dc11337b6e9e2975847ff76d3a4 /src/java/org
parent5ea761b17a5cbdcc2ac36f6c841d7a22d8bdd974 (diff)
downloadxmlgraphics-fop-709bda3d6c3bc23050e6bf69d16b32ed6b35b541.tar.gz
xmlgraphics-fop-709bda3d6c3bc23050e6bf69d16b32ed6b35b541.zip
Implemented the resolution of collapsing borders in the FO tree, for every situation (normal, cell at the top of a page, cell broken), taking conditionality, headers and footers into account.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@603945 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org')
-rw-r--r--src/java/org/apache/fop/fo/FOPropertyMapping.java2
-rw-r--r--src/java/org/apache/fop/fo/flow/table/BorderSpecification.java24
-rw-r--r--src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java413
-rw-r--r--src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java204
-rw-r--r--src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java11
-rw-r--r--src/java/org/apache/fop/fo/flow/table/GridUnit.java160
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableBody.java4
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableFObj.java44
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableHeader.java5
-rwxr-xr-xsrc/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java58
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java15
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java22
12 files changed, 822 insertions, 140 deletions
diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java
index e0acfca7e..5d1a6f31a 100644
--- a/src/java/org/apache/fop/fo/FOPropertyMapping.java
+++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java
@@ -1141,7 +1141,7 @@ public final class FOPropertyMapping implements Constants {
m.useGeneric(genericSpace);
corr = new SpacePropertyMaker(m);
corr.setCorresponding(PR_MARGIN_TOP, PR_MARGIN_TOP, PR_MARGIN_RIGHT);
- corr.setUseParent(true);
+ corr.setUseParent(false);
corr.setRelative(true);
addPropertyMaker("space-before", m);
diff --git a/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java b/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
index 214f9be07..ce6e1b802 100644
--- a/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
+++ b/src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
@@ -20,6 +20,7 @@
package org.apache.fop.fo.flow.table;
import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
/**
@@ -28,6 +29,8 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
*/
public/*TODO*/ class BorderSpecification {
+ private static BorderSpecification defaultBorder;
+
private BorderInfo borderInfo;
private int holder;
@@ -43,6 +46,14 @@ public/*TODO*/ class BorderSpecification {
this.holder = holder;
}
+ static synchronized BorderSpecification getDefaultBorder() {
+ if (defaultBorder == null) {
+ defaultBorder = new BorderSpecification(CommonBorderPaddingBackground
+ .getDefaultBorderInfo(), Constants.FO_TABLE_CELL);
+ }
+ return defaultBorder;
+ }
+
/**
* Returns this border's informations.
*
@@ -66,6 +77,17 @@ public/*TODO*/ class BorderSpecification {
/** {@inheritDoc} */
public String toString() {
- return "{" + borderInfo + ", " + holder + "}";
+ String holderName = "";
+ switch (holder) {
+ case Constants.FO_TABLE: holderName = "table"; break;
+ case Constants.FO_TABLE_COLUMN: holderName = "table-column"; break;
+ case Constants.FO_TABLE_HEADER: holderName = "table-header"; break;
+ case Constants.FO_TABLE_FOOTER: holderName = "table-footer"; break;
+ case Constants.FO_TABLE_BODY: holderName = "table-body"; break;
+ case Constants.FO_TABLE_ROW: holderName = "table-row"; break;
+ case Constants.FO_TABLE_CELL: holderName = "table-cell"; break;
+ default: assert false;
+ }
+ return "{" + borderInfo + ", " + holderName + "}";
}
}
diff --git a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
index c4f7f9a78..f92f7bb30 100644
--- a/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
+++ b/src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
@@ -19,6 +19,7 @@
package org.apache.fop.fo.flow.table;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -31,138 +32,366 @@ class CollapsingBorderResolver implements BorderResolver {
private Table table;
- private List previousRow;
-
/**
- * The flow of rows is interrupted by the table-footer. Save the header's last row (if
- * any) for resolution between it and the body's first row.
+ * The previously registered row, either in the header or the body(-ies), but not in
+ * the footer (handled separately).
*/
- private List previousRowSave;
-
- private TableBody currentTablePart;
+ private List/*<GridUnit>*/ previousRow;
private boolean firstInTable;
- private boolean firstInPart;
+ private List/*<GridUnit>*/ footerFirstRow;
- private List footerFirstRow;
+ /** The last currently registered footer row. */
+ private List/*<GridUnit>*/ footerLastRow;
- private List footerLastRow;
+ private Resolver delegate;
- private boolean inFooter;
+ private Resolver resolverInFooter;
- CollapsingBorderResolver(Table table) {
- this.table = table;
- firstInTable = true;
- }
+ private List/*<ConditionalBorder>*/ leadingBorders;
- /** {@inheritDoc} */
- public void endRow(List row, TableCellContainer container) {
- // Resolve before- and after-borders for the table-row
- if (container instanceof TableRow) {
- TableRow tableRow = (TableRow) container;
- for (Iterator iter = row.iterator(); iter.hasNext();) {
- GridUnit gu = (GridUnit) iter.next();
+ private List/*<ConditionalBorder>*/ trailingBorders;
+
+ /**
+ * Base class for delegate resolvers. Implementation of the State design pattern: the
+ * treatment differs slightly whether we are in the table's header, footer or body. To
+ * avoid complicated if statements, specialised delegate resolvers will be used
+ * instead.
+ */
+ private abstract class Resolver {
+
+ protected TableBody tablePart;
+
+ protected boolean firstInPart;
+
+ /**
+ * Integrates border-before specified on the table and its column.
+ *
+ * @param row the first row of the table (in the header, or in the body if the
+ * table has no header)
+ * @param withLeadingTrailing
+ * @param withNonLeadingTrailing
+ * @param withRest
+ */
+ void resolveBordersFirstRowInTable(List/*<GridUnit>*/ row, boolean withLeadingTrailing,
+ boolean withNonLeadingTrailing, boolean withRest) {
+ assert firstInTable;
+ for (int i = 0; i < row.size(); i++) {
+ TableColumn column = table.getColumn(i);
+ ((GridUnit) row.get(i)).integrateBorderSegment(
+ CommonBorderPaddingBackground.BEFORE, column, withLeadingTrailing,
+ withNonLeadingTrailing, withRest);
+ }
+ firstInTable = false;
+ }
+
+ /**
+ * Resolves border-after for the first row, border-before for the second one.
+ *
+ * @param rowBefore
+ * @param rowAfter
+ */
+ void resolveBordersBetweenRows(List/*<GridUnit>*/ rowBefore, List/*<GridUnit>*/ rowAfter) {
+ assert rowBefore != null && rowAfter != null;
+ for (int i = 0; i < rowAfter.size(); i++) {
+ GridUnit gu = (GridUnit) rowAfter.get(i);
if (gu.getRowSpanIndex() == 0) {
- gu.resolveBorder(CommonBorderPaddingBackground.BEFORE, tableRow);
- }
- if (gu.isLastGridUnitRowSpan()) {
- gu.resolveBorder(CommonBorderPaddingBackground.AFTER, tableRow);
+ GridUnit beforeGU = (GridUnit) rowBefore.get(i);
+ gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE);
}
}
}
- if (inFooter) {
- if (footerFirstRow == null) {
- footerFirstRow = row;
+
+ /** Integrates the border-after of the part. */
+ void resolveBordersLastRowInPart(List/*<GridUnit>*/ row, boolean withLeadingTrailing,
+ boolean withNonLeadingTrailing, boolean withRest) {
+ for (int i = 0; i < row.size(); i++) {
+ ((GridUnit) row.get(i)).integrateBorderSegment(CommonBorderPaddingBackground.AFTER,
+ tablePart, withLeadingTrailing, withNonLeadingTrailing, withRest);
}
- footerLastRow = row;
- } else if (firstInTable) {
- // Resolve border-before for the first row in the table
+ }
+
+ /**
+ * Integrates border-after specified on the table and its columns.
+ *
+ * @param row the last row of the footer, or of the last body if the table has no
+ * footer
+ * @param withLeadingTrailing
+ * @param withNonLeadingTrailing
+ * @param withRest
+ */
+ void resolveBordersLastRowInTable(List/*<GridUnit>*/ row, boolean withLeadingTrailing,
+ boolean withNonLeadingTrailing, boolean withRest) {
for (int i = 0; i < row.size(); i++) {
TableColumn column = table.getColumn(i);
- ((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE, column);
+ ((GridUnit) row.get(i)).integrateBorderSegment(CommonBorderPaddingBackground.AFTER,
+ column, withLeadingTrailing, withNonLeadingTrailing, withRest);
}
- firstInTable = false;
}
- if (firstInPart) {
- // Resolve border-before for the first row in the part
- for (int i = 0; i < row.size(); i++) {
- ((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE,
- currentTablePart);
+
+ /**
+ * Integrates either border-before specified on the table and its columns if the
+ * table has no header, or border-after specified on the cells of the header's
+ * last row. For the case the grid unit are at the top of a page.
+ *
+ * @param row
+ */
+ void integrateLeadingBorders(List/*<GridUnit>*/ row) {
+ for (int i = 0; i < table.getNumberOfColumns(); i++) {
+ GridUnit gu = (GridUnit) row.get(i);
+ ConditionalBorder border = (ConditionalBorder) leadingBorders.get(i);
+ gu.integrateCompetingBorder(CommonBorderPaddingBackground.BEFORE, border,
+ true, false, true);
}
- firstInPart = false;
}
- if (previousRow != null) {
- // Resolve after/before borders between rows
- for (int i = 0; i < row.size(); i++) {
+
+ /**
+ * Integrates either border-after specified on the table and its columns if the
+ * table has no footer, or border-before specified on the cells of the footer's
+ * first row. For the case the grid unit are at the bottom of a page.
+ *
+ * @param row
+ */
+ void integrateTrailingBorders(List/*<GridUnit>*/ row) {
+ for (int i = 0; i < table.getNumberOfColumns(); i++) {
GridUnit gu = (GridUnit) row.get(i);
- if (gu.getRowSpanIndex() == 0) {
- GridUnit beforeGU = (GridUnit) previousRow.get(i);
- gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE);
- }
+ ConditionalBorder border = (ConditionalBorder) trailingBorders.get(i);
+ gu.integrateCompetingBorder(CommonBorderPaddingBackground.AFTER, border,
+ true, false, true);
}
}
- // Resolve start/end borders in the row
- Iterator guIter = row.iterator();
- GridUnit gu = (GridUnit) guIter.next();
- gu.resolveBorder(CommonBorderPaddingBackground.START, container);
- while (guIter.hasNext()) {
- GridUnit guEnd = (GridUnit) guIter.next();
- if (gu.isLastGridUnitColSpan()) {
- gu.resolveBorder(guEnd, CommonBorderPaddingBackground.END);
+
+ void startPart(TableBody part) {
+ tablePart = part;
+ firstInPart = true;
+ }
+
+ /**
+ * Resolves the applicable borders for the given row.
+ * <ul>
+ * <li>Integrates the border-before/after of the containing table-row if any;</li>
+ * <li>Integrates the border-before of the containing part, if first row;</li>
+ * <li>Resolves border-start/end between grid units.</li>
+ * </ul>
+ *
+ * @param row the row being finished
+ * @param container the containing element
+ */
+ void endRow(List/*<GridUnit>*/ row, TableCellContainer container) {
+ // Resolve before- and after-borders for the table-row
+ if (container instanceof TableRow) {
+ TableRow tableRow = (TableRow) container;
+ for (Iterator iter = row.iterator(); iter.hasNext();) {
+ GridUnit gu = (GridUnit) iter.next();
+ if (gu.getRowSpanIndex() == 0) {
+ gu.integrateBorderSegment(CommonBorderPaddingBackground.BEFORE, tableRow,
+ true, true, true);
+ }
+ if (gu.isLastGridUnitRowSpan()) {
+ gu.integrateBorderSegment(CommonBorderPaddingBackground.AFTER, tableRow,
+ true, true, true);
+ }
+ }
+ }
+ if (firstInPart) {
+ // Integrate the border-before of the part
+ for (int i = 0; i < row.size(); i++) {
+ ((GridUnit) row.get(i)).integrateBorderSegment(
+ CommonBorderPaddingBackground.BEFORE, tablePart, true, true, true);
+ }
+ firstInPart = false;
+ }
+ // Resolve start/end borders in the row
+ Iterator guIter = row.iterator();
+ GridUnit gu = (GridUnit) guIter.next();
+ gu.integrateBorderSegment(CommonBorderPaddingBackground.START, container);
+ while (guIter.hasNext()) {
+ GridUnit guEnd = (GridUnit) guIter.next();
+ if (gu.isLastGridUnitColSpan()) {
+ gu.resolveBorder(guEnd, CommonBorderPaddingBackground.END);
+ }
+ gu = guEnd;
}
- gu = guEnd;
+ gu.integrateBorderSegment(CommonBorderPaddingBackground.END, container);
}
- gu.resolveBorder(CommonBorderPaddingBackground.END, container);
- previousRow = row;
+ void endPart() {
+ resolveBordersLastRowInPart(previousRow, true, true, true);
+ }
+
+ abstract void endTable();
}
- /** {@inheritDoc} */
- public void startPart(TableBody part) {
- firstInPart = true;
- currentTablePart = part;
- if (part.isTableFooter()) {
- inFooter = true;
- previousRowSave = previousRow;
- previousRow = null;
+ private class ResolverInHeader extends Resolver {
+
+ void endRow(List/*<GridUnit>*/ row, TableCellContainer container) {
+ super.endRow(row, container);
+ if (previousRow != null) {
+ resolveBordersBetweenRows(previousRow, row);
+ } else {
+ /*
+ * This is a bit hacky...
+ * The two only sensible values for border-before on the header's first row are:
+ * - at the beginning of the table (normal case)
+ * - if the header is repeated after each page break
+ * To represent those values we (ab)use the nonLeadingTrailing and the rest
+ * fields of ConditionalBorder. But strictly speaking this is not their
+ * purposes.
+ */
+ for (Iterator guIter = row.iterator(); guIter.hasNext();) {
+ ConditionalBorder borderBefore = ((GridUnit) guIter.next()).borderBefore;
+ borderBefore.leadingTrailing = null;
+ borderBefore.rest = borderBefore.nonLeadingTrailing;
+ }
+ resolveBordersFirstRowInTable(row, false, true, true);
+ }
+ previousRow = row;
}
- }
- /** {@inheritDoc} */
- public void endPart(TableBody part) {
- // Resolve border-after for the last row in the part
- for (int i = 0; i < previousRow.size(); i++) {
- ((GridUnit) previousRow.get(i))
- .resolveBorder(CommonBorderPaddingBackground.AFTER, part);
+ void endPart() {
+ super.endPart();
+ leadingBorders = new ArrayList(table.getNumberOfColumns());
+ /*
+ * Another hack...
+ * The border-after of a header is always the same. Leading and rest don't
+ * apply to cells in the header since they are never broken. To ease
+ * resolution we override the (normally unused) leadingTrailing and rest
+ * fields of ConditionalBorder with the only sensible nonLeadingTrailing
+ * field. That way grid units from the body will always resolve against the
+ * same, normal header border.
+ */
+ for (Iterator guIter = previousRow.iterator(); guIter.hasNext();) {
+ ConditionalBorder borderAfter = ((GridUnit) guIter.next()).borderAfter;
+ borderAfter.leadingTrailing = borderAfter.nonLeadingTrailing;
+ borderAfter.rest = borderAfter.nonLeadingTrailing;
+ leadingBorders.add(borderAfter);
+ }
}
- if (inFooter) {
- inFooter = false;
- previousRow = previousRowSave;
+
+ void endTable() {
+ throw new IllegalStateException();
}
}
- /** {@inheritDoc} */
- public void endTable() {
- if (footerFirstRow != null) {
+ private class ResolverInFooter extends Resolver {
+
+ void endRow(List/*<GridUnit>*/ row, TableCellContainer container) {
+ super.endRow(row, container);
+ if (footerFirstRow == null) {
+ footerFirstRow = row;
+ } else {
+ // There is a previous row
+ resolveBordersBetweenRows(footerLastRow, row);
+ }
+ footerLastRow = row;
+ }
+
+ void endPart() {
+ resolveBordersLastRowInPart(footerLastRow, true, true, true);
+ trailingBorders = new ArrayList(table.getNumberOfColumns());
+ // See same method in ResolverInHeader for an explanation of the hack
+ for (Iterator guIter = footerFirstRow.iterator(); guIter.hasNext();) {
+ ConditionalBorder borderBefore = ((GridUnit) guIter.next()).borderBefore;
+ borderBefore.leadingTrailing = borderBefore.nonLeadingTrailing;
+ borderBefore.rest = borderBefore.nonLeadingTrailing;
+ trailingBorders.add(borderBefore);
+ }
+ }
+
+ void endTable() {
// Resolve after/before border between the last row of table-body and the
// first row of table-footer
- for (int i = 0; i < footerFirstRow.size(); i++) {
- GridUnit gu = (GridUnit) footerFirstRow.get(i);
- GridUnit beforeGU = (GridUnit) previousRow.get(i);
- gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE);
+ resolveBordersBetweenRows(previousRow, footerFirstRow);
+ // See endRow method in ResolverInHeader for an explanation of the hack
+ for (Iterator guIter = footerLastRow.iterator(); guIter.hasNext();) {
+ ConditionalBorder borderAfter = ((GridUnit) guIter.next()).borderAfter;
+ borderAfter.leadingTrailing = null;
+ borderAfter.rest = borderAfter.nonLeadingTrailing;
}
+ resolveBordersLastRowInTable(footerLastRow, false, true, true);
}
- List lastRow;
- if (footerLastRow != null) {
- lastRow = footerLastRow;
- } else {
- lastRow = previousRow;
+ }
+
+ private class ResolverInBody extends Resolver {
+
+ void endRow(List/*<GridUnit>*/ row, TableCellContainer container) {
+ super.endRow(row, container);
+ if (firstInTable) {
+ resolveBordersFirstRowInTable(row, true, true, true);
+ } else {
+ // Either there is a header, and then previousRow is set to the header's last row,
+ // or this is not the first row in the body, and previousRow is not null
+ resolveBordersBetweenRows(previousRow, row);
+ integrateLeadingBorders(row);
+ }
+ integrateTrailingBorders(row);
+ previousRow = row;
}
- // Resolve border-after for the last row of the table
- for (int i = 0; i < lastRow.size(); i++) {
- TableColumn column = table.getColumn(i);
- ((GridUnit) lastRow.get(i)).resolveBorder(CommonBorderPaddingBackground.AFTER, column);
+
+ void endTable() {
+ if (resolverInFooter != null) {
+ resolverInFooter.endTable();
+ } else {
+ // Trailing and rest borders already resolved with integrateTrailingBorders
+ resolveBordersLastRowInTable(previousRow, false, true, false);
+ }
}
}
+
+ CollapsingBorderResolver(Table table) {
+ this.table = table;
+ firstInTable = true;
+ }
+
+ /** {@inheritDoc} */
+ public void endRow(List/*<GridUnit>*/ row, TableCellContainer container) {
+ delegate.endRow(row, container);
+ }
+
+ /** {@inheritDoc} */
+ public void startPart(TableBody part) {
+ if (part.isTableHeader()) {
+ delegate = new ResolverInHeader();
+ } else {
+ if (leadingBorders == null) {
+ // No header, leading borders determined by the table
+ leadingBorders = new ArrayList(table.getNumberOfColumns());
+ for (Iterator colIter = table.getColumns().iterator(); colIter.hasNext();) {
+ // See endRow method in ResolverInHeader for an explanation of the hack
+ ConditionalBorder border = ((TableColumn) colIter.next()).borderBefore;
+ border.leadingTrailing = border.rest;
+ leadingBorders.add(border);
+ }
+ }
+ if (part.isTableFooter()) {
+ resolverInFooter = new ResolverInFooter();
+ delegate = resolverInFooter;
+ } else {
+ if (trailingBorders == null) {
+ // No footer, trailing borders determined by the table
+ trailingBorders = new ArrayList(table.getNumberOfColumns());
+ for (Iterator colIter = table.getColumns().iterator(); colIter.hasNext();) {
+ // See endRow method in ResolverInHeader for an explanation of the hack
+ ConditionalBorder border = ((TableColumn) colIter.next()).borderAfter;
+ border.leadingTrailing = border.rest;
+ trailingBorders.add(border);
+ }
+ }
+ delegate = new ResolverInBody();
+ }
+ }
+ delegate.startPart(part);
+ }
+
+ /** {@inheritDoc} */
+ public void endPart(TableBody part) {
+ delegate.endPart();
+ }
+
+ /** {@inheritDoc} */
+ public void endTable() {
+ delegate.endTable();
+ delegate = null;
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java
new file mode 100644
index 000000000..e03e11a15
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/table/ConditionalBorder.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.fo.flow.table;
+
+import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
+
+/**
+ * A class that holds the three possible values for a border-before/after on a table-cell,
+ * in the collapsing model. These three values are (for border-before, similar for
+ * border-after):
+ * <ul>
+ * <li>non-leading: common case, when a cell follows the cell before on a same page;</li>
+ * <li>leading: when the table is broken and the cell appears at the top of a page, in
+ * which case its border must be resolved with the header (or the top of the table)
+ * instead of with the previous cell;</li>
+ * <li>rest: when a cell is broken over several pages; same as leading but with
+ * conditionality taken into account.</li>
+ * </ul>
+ */
+public class ConditionalBorder {
+
+ /** Special case: the cell is at the top or the bottom of the page. */
+ BorderSpecification leadingTrailing;
+
+ /** Normal case, no break. */
+ BorderSpecification nonLeadingTrailing;
+
+ /** Special case: break inside the cell. */
+ BorderSpecification rest;
+
+ /** The model used to resolve borders. */
+ private CollapsingBorderModel collapsingBorderModel;
+
+ private ConditionalBorder(BorderSpecification leadingTrailing,
+ BorderSpecification nonLeadingTrailing, BorderSpecification rest,
+ CollapsingBorderModel collapsingBorderModel) {
+ this.leadingTrailing = leadingTrailing;
+ this.nonLeadingTrailing = nonLeadingTrailing;
+ this.rest = rest;
+ this.collapsingBorderModel = collapsingBorderModel;
+ }
+
+ /**
+ * Creates a new conditional border.
+ *
+ * @param borderSpecification the border specification to take as a basis
+ * @param collapsingBorderModel the model that will be used to resolved borders
+ */
+ ConditionalBorder(BorderSpecification borderSpecification,
+ CollapsingBorderModel collapsingBorderModel) {
+ leadingTrailing = borderSpecification;
+ nonLeadingTrailing = leadingTrailing;
+ if (borderSpecification.getBorderInfo().getWidth().isDiscard()) {
+ rest = BorderSpecification.getDefaultBorder();
+ } else {
+ rest = leadingTrailing;
+ }
+ this.collapsingBorderModel = collapsingBorderModel;
+ }
+
+ /**
+ * Resolves and updates the relevant parts of this border as well as the given one.
+ *
+ * @param competitor
+ * @param withLeadingTrailing
+ * @param withNonLeadingTrailing
+ * @param withRest
+ */
+ void resolve(ConditionalBorder competitor, boolean withLeadingTrailing,
+ boolean withNonLeadingTrailing, boolean withRest) {
+ if (withLeadingTrailing) {
+ BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(
+ leadingTrailing, competitor.leadingTrailing);
+ if (resolvedBorder != null) {
+ leadingTrailing = resolvedBorder;
+ competitor.leadingTrailing = resolvedBorder;
+ }
+ }
+ if (withNonLeadingTrailing) {
+ BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(
+ nonLeadingTrailing, competitor.nonLeadingTrailing);
+ if (resolvedBorder != null) {
+ nonLeadingTrailing = resolvedBorder;
+ competitor.nonLeadingTrailing = resolvedBorder;
+ }
+ }
+ if (withRest) {
+ BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(rest,
+ competitor.rest);
+ if (resolvedBorder != null) {
+ rest = resolvedBorder;
+ competitor.rest = resolvedBorder;
+ }
+ }
+ }
+
+ /**
+ * Integrates the given segment in this border. Unlike for
+ * {@link #integrateSegment(ConditionalBorder, boolean, boolean, boolean)}, this
+ * method nicely handles the case where the CollapsingBorderModel returns null, by
+ * keeping the components to their old values.
+ *
+ * @param competitor
+ * @param withLeadingTrailing
+ * @param withNonLeadingTrailing
+ * @param withRest
+ */
+ void integrateCompetingSegment(ConditionalBorder competitor, boolean withLeadingTrailing,
+ boolean withNonLeadingTrailing, boolean withRest) {
+ if (withLeadingTrailing) {
+ BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(
+ leadingTrailing, competitor.leadingTrailing);
+ if (resolvedBorder != null) {
+ leadingTrailing = resolvedBorder;
+ }
+ }
+ if (withNonLeadingTrailing) {
+ BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(
+ nonLeadingTrailing, competitor.nonLeadingTrailing);
+ if (resolvedBorder != null) {
+ nonLeadingTrailing = resolvedBorder;
+ }
+ }
+ if (withRest) {
+ BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(rest,
+ competitor.rest);
+ if (resolvedBorder != null) {
+ rest = resolvedBorder;
+ }
+ }
+ }
+
+ /**
+ * Updates this border after taking into account the given segment. The
+ * CollapsingBorderModel is not expected to return null.
+ *
+ * @param segment
+ * @param withLeadingTrailing
+ * @param withNonLeadingTrailing
+ * @param withRest
+ */
+ void integrateSegment(ConditionalBorder segment, boolean withLeadingTrailing,
+ boolean withNonLeadingTrailing, boolean withRest) {
+ if (withLeadingTrailing) {
+ leadingTrailing = collapsingBorderModel.determineWinner(leadingTrailing,
+ segment.leadingTrailing);
+ assert leadingTrailing != null;
+ }
+ if (withNonLeadingTrailing) {
+ nonLeadingTrailing = collapsingBorderModel.determineWinner(nonLeadingTrailing,
+ segment.nonLeadingTrailing);
+ assert nonLeadingTrailing != null;
+ }
+ if (withRest) {
+ rest = collapsingBorderModel.determineWinner(rest, segment.rest);
+ assert rest != null;
+ }
+ }
+
+ /**
+ * Returns a shallow copy of this border.
+ *
+ * @return a copy of this border
+ */
+ ConditionalBorder copy() {
+ return new ConditionalBorder(leadingTrailing, nonLeadingTrailing, rest,
+ collapsingBorderModel);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "{non-leading: " + nonLeadingTrailing + ", leading: " + leadingTrailing + ", rest: "
+ + rest + "}";
+ }
+
+ /**
+ * Returns a default border specification.
+ *
+ * @param collapsingBorderModel the model that will be used to resolve borders
+ * @return a border with style 'none' for all of the three components
+ */
+ static ConditionalBorder getDefaultBorder(CollapsingBorderModel collapsingBorderModel) {
+ BorderSpecification defaultBorderSpec = BorderSpecification.getDefaultBorder();
+ return new ConditionalBorder(defaultBorderSpec, defaultBorderSpec, defaultBorderSpec,
+ collapsingBorderModel);
+ }
+}
diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
index be487931b..7a8b0be62 100644
--- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
@@ -19,8 +19,6 @@
package org.apache.fop.fo.flow.table;
-import org.apache.fop.fo.Constants;
-import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
/**
* GridUnit subclass for empty grid units.
@@ -40,10 +38,11 @@ public class EmptyGridUnit extends GridUnit {
}
/** {@inheritDoc} */
- protected void setBorder(int side) {
- resolvedBorders[side] = new BorderSpecification(
- CommonBorderPaddingBackground.getDefaultBorderInfo(),
- Constants.FO_TABLE_CELL);
+ protected void setBordersFromCell() {
+ borderBefore = ConditionalBorder.getDefaultBorder(collapsingBorderModel);
+ borderAfter = ConditionalBorder.getDefaultBorder(collapsingBorderModel);
+ borderStart = BorderSpecification.getDefaultBorder();
+ borderEnd = BorderSpecification.getDefaultBorder();
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java
index f7c7672e3..d6d622d57 100644
--- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java
@@ -90,9 +90,12 @@ public class GridUnit {
/** flags for the grid unit */
private byte flags = 0;
- protected BorderSpecification[] resolvedBorders;
+ ConditionalBorder borderBefore;
+ ConditionalBorder borderAfter;
+ BorderSpecification borderStart;
+ BorderSpecification borderEnd;
- private CollapsingBorderModel collapsingBorderModel;
+ protected CollapsingBorderModel collapsingBorderModel;
/**
* Creates a new grid unit.
@@ -156,26 +159,27 @@ public class GridUnit {
if (table.isSeparateBorderModel()) {
assignBorderForSeparateBorderModel();
} else {
- resolvedBorders = new BorderSpecification[4];
collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table
.getBorderCollapse());
- if (rowSpanIndex == 0) {
- setBorder(CommonBorderPaddingBackground.BEFORE);
- }
- if (isLastGridUnitRowSpan()) {
- setBorder(CommonBorderPaddingBackground.AFTER);
- }
- if (colSpanIndex == 0) {
- setBorder(CommonBorderPaddingBackground.START);
- }
- if (isLastGridUnitColSpan()) {
- setBorder(CommonBorderPaddingBackground.END);
- }
+ setBordersFromCell();
}
}
- protected void setBorder(int side) {
- resolvedBorders[side] = cell.resolvedBorders[side];
+ protected void setBordersFromCell() {
+ borderBefore = cell.borderBefore.copy();
+ if (rowSpanIndex > 0) {
+ borderBefore.nonLeadingTrailing = null;
+ }
+ borderAfter = cell.borderAfter.copy();
+ if (!isLastGridUnitRowSpan()) {
+ borderAfter.nonLeadingTrailing = null;
+ }
+ if (colSpanIndex == 0) {
+ borderStart = cell.borderStart;
+ }
+ if (isLastGridUnitColSpan()) {
+ borderEnd = cell.borderEnd;
+ }
}
public TableCell getCell() {
@@ -301,8 +305,30 @@ public class GridUnit {
}
private void setBorderInfo(int side) {
- if (resolvedBorders[side] != null) {
- effectiveBorders.setBorderInfo(resolvedBorders[side].getBorderInfo(), side);
+ switch (side) {
+ case CommonBorderPaddingBackground.BEFORE:
+ if (borderBefore.nonLeadingTrailing/*TODO*/ != null) {
+ effectiveBorders.setBorderInfo(borderBefore.nonLeadingTrailing.getBorderInfo(),
+ side);
+ }
+ break;
+ case CommonBorderPaddingBackground.AFTER:
+ if (borderAfter.nonLeadingTrailing/*TODO*/ != null) {
+ effectiveBorders.setBorderInfo(borderAfter.nonLeadingTrailing.getBorderInfo(),
+ side);
+ }
+ break;
+ case CommonBorderPaddingBackground.START:
+ if (borderStart != null) {
+ effectiveBorders.setBorderInfo(borderStart.getBorderInfo(), side);
+ }
+ break;
+ case CommonBorderPaddingBackground.END:
+ if (borderEnd != null) {
+ effectiveBorders.setBorderInfo(borderEnd.getBorderInfo(), side);
+ }
+ break;
+ default: assert false;
}
}
@@ -332,26 +358,96 @@ public class GridUnit {
* CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
*/
void resolveBorder(GridUnit other, int side) {
- BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(
- resolvedBorders[side], other.resolvedBorders[CollapsingBorderModel
- .getOtherSide(side)]);
- if (resolvedBorder != null) {
- this.resolvedBorders[side] = resolvedBorder;
- other.resolvedBorders[CollapsingBorderModel.getOtherSide(side)] = resolvedBorder;
+ switch (side) {
+ case CommonBorderPaddingBackground.BEFORE:
+ borderBefore.resolve(other.borderAfter, false, true, false);
+ break;
+ case CommonBorderPaddingBackground.AFTER:
+ borderAfter.resolve(other.borderBefore, false, true, false);
+ break;
+ case CommonBorderPaddingBackground.START:
+ BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(
+ borderStart, other.borderEnd);
+ if (resolvedBorder != null) {
+ this.borderStart = resolvedBorder;
+ other.borderEnd = resolvedBorder;
+ }
+ break;
+ case CommonBorderPaddingBackground.END:
+ resolvedBorder = collapsingBorderModel.determineWinner(
+ borderEnd, other.borderStart);
+ if (resolvedBorder != null) {
+ this.borderEnd = resolvedBorder;
+ other.borderStart = resolvedBorder;
+ }
+ break;
+ default: assert false;
}
}
/**
- * Resolves the border on the given side of this grid unit, comparing it against the
- * same border of the given parent element.
+ * For the given side, integrates in the conflict resolution the border segment of the
+ * given parent element.
*
- * @param side the side to resolve (one of
+ * @param side the side to consider (either CommonBorderPaddingBackground.BEFORE or
+ * AFTER)
+ * @param parent a table element whose corresponding border coincides on the given
+ * side
+ */
+ void integrateBorderSegment(int side, TableFObj parent, boolean withLeadingTrailing,
+ boolean withNonLeadingTrailing, boolean withRest) {
+ switch (side) {
+ case CommonBorderPaddingBackground.BEFORE:
+ borderBefore.integrateSegment(parent.borderBefore, withLeadingTrailing,
+ withNonLeadingTrailing, withRest);
+ break;
+ case CommonBorderPaddingBackground.AFTER:
+ borderAfter.integrateSegment(parent.borderAfter, withLeadingTrailing,
+ withNonLeadingTrailing, withRest);
+ break;
+ default: assert false;
+ }
+ }
+
+ /**
+ * For the given side, integrates in the conflict resolution the border segment of the
+ * given parent element.
+ *
+ * @param side the side to consider (one of
* CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
- * @param parent the parent element holding a competing border
+ * @param parent a table element whose corresponding border coincides on the given side
*/
- void resolveBorder(int side, TableFObj parent) {
- resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side],
- parent.resolvedBorders[side]);
+ void integrateBorderSegment(int side, TableFObj parent) {
+ switch (side) {
+ case CommonBorderPaddingBackground.BEFORE:
+ case CommonBorderPaddingBackground.AFTER:
+ integrateBorderSegment(side, parent, true, true, true);
+ break;
+ case CommonBorderPaddingBackground.START:
+ borderStart = collapsingBorderModel.determineWinner(borderStart,
+ parent.borderStart);
+ break;
+ case CommonBorderPaddingBackground.END:
+ borderEnd = collapsingBorderModel.determineWinner(borderEnd,
+ parent.borderEnd);
+ break;
+ default: assert false;
+ }
+ }
+
+ void integrateCompetingBorder(int side, ConditionalBorder competitor,
+ boolean withLeadingTrailing, boolean withNonLeadingTrailing, boolean withRest) {
+ switch (side) {
+ case CommonBorderPaddingBackground.BEFORE:
+ borderBefore.integrateCompetingSegment(competitor, withLeadingTrailing,
+ withNonLeadingTrailing, withRest);
+ break;
+ case CommonBorderPaddingBackground.AFTER:
+ borderAfter.integrateCompetingSegment(competitor, withLeadingTrailing,
+ withNonLeadingTrailing, withRest);
+ break;
+ default: assert false;
+ }
}
/**
diff --git a/src/java/org/apache/fop/fo/flow/table/TableBody.java b/src/java/org/apache/fop/fo/flow/table/TableBody.java
index 6b12271fc..c1453bdfa 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableBody.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableBody.java
@@ -261,6 +261,10 @@ public class TableBody extends TableCellContainer {
return FO_TABLE_BODY;
}
+ protected boolean isTableHeader() {
+ return false;
+ }
+
protected boolean isTableFooter() {
return false;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableFObj.java b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
index 236556a05..4b90ccac3 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableFObj.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableFObj.java
@@ -42,7 +42,10 @@ public abstract class TableFObj extends FObj {
private Numeric borderEndPrecedence;
private Numeric borderStartPrecedence;
- BorderSpecification[] resolvedBorders = new BorderSpecification[4]; // TODO
+ ConditionalBorder borderBefore;
+ ConditionalBorder borderAfter;
+ BorderSpecification borderStart;
+ BorderSpecification borderEnd;
CollapsingBorderModel collapsingBorderModel;
@@ -200,7 +203,6 @@ public abstract class TableFObj extends FObj {
if (!inMarker() && !table.isSeparateBorderModel()) {
collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table
.getBorderCollapse());
- resolvedBorders = new BorderSpecification[4];
setCollapsedBorders();
}
}
@@ -226,8 +228,23 @@ public abstract class TableFObj extends FObj {
* @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END
*/
protected void createBorder(int side) {
- resolvedBorders[side] = new BorderSpecification(getCommonBorderPaddingBackground()
- .getBorderInfo(side), getNameId());
+ BorderSpecification borderSpec = new BorderSpecification(
+ getCommonBorderPaddingBackground().getBorderInfo(side), getNameId());
+ switch (side) {
+ case CommonBorderPaddingBackground.BEFORE:
+ borderBefore = new ConditionalBorder(borderSpec, collapsingBorderModel);
+ break;
+ case CommonBorderPaddingBackground.AFTER:
+ borderAfter = new ConditionalBorder(borderSpec, collapsingBorderModel);
+ break;
+ case CommonBorderPaddingBackground.START:
+ borderStart = borderSpec;
+ break;
+ case CommonBorderPaddingBackground.END:
+ borderEnd = borderSpec;
+ break;
+ default: assert false;
+ }
}
/**
@@ -240,7 +257,22 @@ public abstract class TableFObj extends FObj {
*/
protected void createBorder(int side, TableFObj competitor) {
createBorder(side);
- resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side],
- competitor.resolvedBorders[side]);
+ switch (side) {
+ case CommonBorderPaddingBackground.BEFORE:
+ borderBefore.integrateSegment(competitor.borderBefore, true, true, true);
+ break;
+ case CommonBorderPaddingBackground.AFTER:
+ borderAfter.integrateSegment(competitor.borderAfter, true, true, true);
+ break;
+ case CommonBorderPaddingBackground.START:
+ borderStart = collapsingBorderModel.determineWinner(borderStart,
+ competitor.borderStart);
+ break;
+ case CommonBorderPaddingBackground.END:
+ borderEnd = collapsingBorderModel.determineWinner(borderEnd,
+ competitor.borderEnd);
+ break;
+ default: assert false;
+ }
}
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableHeader.java b/src/java/org/apache/fop/fo/flow/table/TableHeader.java
index 01ada2aa7..e248a0f7e 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableHeader.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableHeader.java
@@ -66,4 +66,9 @@ public class TableHeader extends TableBody {
public int getNameId() {
return FO_TABLE_HEADER;
}
+
+ /** {@inheritDoc} */
+ protected boolean isTableHeader() {
+ return true;
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
index 6ea08f19c..c5a4950f4 100755
--- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
+++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
@@ -131,14 +131,68 @@ public class CommonBorderPaddingBackground {
private static BorderInfo defaultBorderInfo;
/**
+ * A conditional length of value 0. Returned by the
+ * {@link CommonBorderPaddingBackground#getBorderInfo(int)} method when the
+ * corresponding border isn't specified, to avoid to callers painful checks for null.
+ */
+ private static class ConditionalNullLength extends CondLengthProperty {
+
+ /** {@inheritDoc} */
+ public Property getComponent(int cmpId) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public Property getConditionality() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public Length getLength() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public Property getLengthComponent() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public int getLengthValue() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ public int getLengthValue(PercentBaseContext context) {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isDiscard() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ public void setComponent(int cmpId, Property cmpnValue, boolean isDefault) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "CondLength[0mpt, discard]";
+ }
+ }
+
+ /**
* Returns a default BorderInfo of style none.
*
* @return a BorderInfo instance with style set to {@link Constants#EN_NONE}
*/
public static synchronized BorderInfo getDefaultBorderInfo() {
if (defaultBorderInfo == null) {
- /* It is enough to set color and width to null, as they should never be consulted */
- defaultBorderInfo = new BorderInfo(Constants.EN_NONE, null, null);
+ /* It is enough to set color to null, as it should never be consulted */
+ defaultBorderInfo = new BorderInfo(Constants.EN_NONE,
+ new ConditionalNullLength(), null);
}
return defaultBorderInfo;
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
index a0bff3b5e..c3df74800 100644
--- a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
+++ b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
@@ -181,9 +181,24 @@ public abstract class CollapsingBorderModel {
*
* @param border1 a border specification
* @param border2 another border specification
+ * @param discard true if the .conditionality component of the border width must be
+ * taken into account
* @return the winning border, null if the two borders are equivalent
*/
public abstract BorderSpecification determineWinner(BorderSpecification border1,
+ BorderSpecification border2, boolean discard);
+
+ /**
+ * Returns the border which wins the border conflict resolution. Same as
+ * {@link #determineWinner(BorderSpecification, BorderSpecification, boolean)
+ * determineWinner(border1, border2, false)}.
+ *
+ * @param border1 a border specification
+ * @param border2 another border specification
+ * @return the winning border, null if the two borders are equivalent
+ * @see determineWinner
+ */
+ public abstract BorderSpecification determineWinner(BorderSpecification border1,
BorderSpecification border2);
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
index 5f979c986..c1a9380a3 100644
--- a/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
+++ b/src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
@@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr.table;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.flow.table.BorderSpecification;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
/**
@@ -32,6 +33,27 @@ public class CollapsingBorderModelEyeCatching extends CollapsingBorderModel {
/** {@inheritDoc} */
public BorderSpecification determineWinner(BorderSpecification border1,
+ BorderSpecification border2, boolean discard) {
+ BorderInfo bi1 = border1.getBorderInfo();
+ BorderInfo bi2 = border2.getBorderInfo();
+ if (discard) {
+ if (bi1.getWidth().isDiscard()) {
+ if (bi2.getWidth().isDiscard()) {
+ return new BorderSpecification(
+ CommonBorderPaddingBackground.getDefaultBorderInfo(), 0/*TODO*/);
+ } else {
+ return border2;
+ }
+ } else if (bi2.getWidth().isDiscard()) {
+ return border1;
+ }
+ }
+ // Otherwise, fall back to the default resolution algorithm
+ return determineWinner(border1, border2);
+ }
+
+ /** {@inheritDoc} */
+ public BorderSpecification determineWinner(BorderSpecification border1,
BorderSpecification border2) {
BorderInfo bi1 = border1.getBorderInfo();
BorderInfo bi2 = border2.getBorderInfo();