Sfoglia il codice sorgente

Moved the creation of grid units to the FO tree building stage. Brought a few improvements along with the move:

- bugfix: border-resolution for border-end on row-spanning cells was wrong
- bugfix: in case of missing cells the border-end of the table was applied to an inner cell, instead of the cell in the last column (but missing cells aren't painted yet :-\)
- bugfix: in collapsing-border model, border-before and -after specified on table-column were applied to every cell of the column, instead of only the first and the last ones
- border resolution is now made progressively when possible, and no longer triggers the fetching of all the rows of the table
Added testcases for the border conflict resolution (between the various elements of a table and not only the cells)


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@594571 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_95beta
Vincent Hennebert 16 anni fa
parent
commit
5675e7ef51
32 ha cambiato i file con 2925 aggiunte e 722 eliminazioni
  1. 12
    1
      src/java/org/apache/fop/fo/flow/RetrieveMarker.java
  2. 56
    0
      src/java/org/apache/fop/fo/flow/table/BorderResolver.java
  3. 71
    0
      src/java/org/apache/fop/fo/flow/table/BorderSpecification.java
  4. 169
    0
      src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java
  5. 148
    0
      src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java
  6. 26
    72
      src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java
  7. 44
    0
      src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java
  8. 18
    30
      src/java/org/apache/fop/fo/flow/table/Table.java
  9. 48
    19
      src/java/org/apache/fop/fo/flow/table/TableBody.java
  10. 17
    2
      src/java/org/apache/fop/fo/flow/table/TableCell.java
  11. 7
    0
      src/java/org/apache/fop/fo/flow/table/TableCellContainer.java
  12. 19
    5
      src/java/org/apache/fop/fo/flow/table/TableColumn.java
  13. 57
    3
      src/java/org/apache/fop/fo/flow/table/TableFObj.java
  14. 8
    2
      src/java/org/apache/fop/fo/flow/table/TableFooter.java
  15. 3
    2
      src/java/org/apache/fop/fo/flow/table/TableHeader.java
  16. 21
    2
      src/java/org/apache/fop/fo/flow/table/TableRow.java
  17. 60
    22
      src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java
  18. 6
    2
      src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
  19. 74
    20
      src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java
  20. 36
    263
      src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java
  21. 4
    2
      src/java/org/apache/fop/layoutmgr/table/EffRow.java
  22. 35
    13
      src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java
  23. 145
    82
      src/java/org/apache/fop/layoutmgr/table/GridUnit.java
  24. 16
    4
      src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java
  25. 1
    105
      src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
  26. 52
    61
      src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
  27. 15
    0
      status.xml
  28. 448
    0
      test/layoutengine/standard-testcases/table_border-collapse_collapse_nrnc_no-col.xml
  29. 337
    0
      test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution.xml
  30. 333
    0
      test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution_no-col.xml
  31. 0
    10
      test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_2.xml
  32. 639
    0
      test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_2_no-col.xml

+ 12
- 1
src/java/org/apache/fop/fo/flow/RetrieveMarker.java Vedi File

@@ -23,12 +23,13 @@ import java.util.Iterator;

import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.FObjMixed;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableFObj;
import org.xml.sax.Locator;

/**
@@ -126,6 +127,12 @@ public class RetrieveMarker extends FObjMixed {
getLocator(),
pList,
newPropertyList);
if (newChild instanceof TableFObj) {
// TODO calling startOfNode (and endOfNode, below) on other fobjs may
// have undesirable side-effects. This is really ugly and will need to
// be addressed sooner or later
((TableFObj) newChild).startOfNode();
}
addChildTo(newChild, (FObj) newParent);
if (newChild.getNameId() == FO_TABLE) {
Table t = (Table) child;
@@ -138,6 +145,10 @@ public class RetrieveMarker extends FObjMixed {
}
cloneSubtree(child.getChildNodes(), newChild,
marker, newPropertyList);
if (newChild instanceof TableFObj) {
// TODO this is ugly
((TableFObj) newChild).endOfNode();
}
} else if (child instanceof FOText) {
FOText ft = (FOText) newChild;
ft.bind(parentPropertyList);

+ 56
- 0
src/java/org/apache/fop/fo/flow/table/BorderResolver.java Vedi File

@@ -0,0 +1,56 @@
/*
* 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 java.util.List;

/**
* A class dedicated to the resolution of borders in tables. It receives a series of
* events as the table is parsed and performs border resolution accordingly.
*/
interface BorderResolver {

/**
* Receives notification of the end of a row.
*
* @param row the row that has just been finished
* @param container the FO element holding the given row
*/
void endRow(List/*<GridUnit>*/ row, TableCellContainer container);

/**
* Receives notification of the start of a table-header/footer/body.
*
* @param part the part that has started
*/
void startPart(TableBody part);

/**
* Receives notification of the end of a table-header/footer/body.
*
* @param part the part that has ended
*/
void endPart(TableBody part);

/**
* Receives notification of the end of the table.
*/
void endTable();
}

+ 71
- 0
src/java/org/apache/fop/fo/flow/table/BorderSpecification.java Vedi File

@@ -0,0 +1,71 @@
/*
* 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.fo.Constants;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;

/**
* A border's informations, along with the FO element which declared it. Used for border
* resolution in the collapsing-border model.
*/
public/*TODO*/ class BorderSpecification {

private BorderInfo borderInfo;

private int holder;

/**
* Creates a new border specification.
*
* @param borderInfo the border's informations
* @param holder the FO element declaring this border
*/
public/*TODO*/ BorderSpecification(BorderInfo borderInfo, int holder) {
this.borderInfo = borderInfo;
this.holder = holder;
}

/**
* Returns this border's informations.
*
* @return this border's informations
*/
public/*TODO*/ BorderInfo getBorderInfo() {
return borderInfo;
}

/**
* Returns the FO element declaring this border.
*
* @return one of {@link Constants#FO_TABLE}, {@link Constants#FO_TABLE_COLUMN},
* {@link Constants#FO_TABLE_HEADER}, {@link Constants#FO_TABLE_FOOTER},
* {@link Constants#FO_TABLE_BODY}, {@link Constants#FO_TABLE_ROW},
* {@link Constants#FO_TABLE_CELL}
*/
public/*TODO*/ int getHolder() {
return holder;
}

/** {@inheritDoc} */
public String toString() {
return "{" + borderInfo + ", " + holder + "}";
}
}

+ 169
- 0
src/java/org/apache/fop/fo/flow/table/CollapsingBorderResolver.java Vedi File

@@ -0,0 +1,169 @@
/*
* 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 java.util.Iterator;
import java.util.List;

import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.layoutmgr.table.GridUnit;

/**
* A class that implements the border-collapsing model.
*/
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.
*/
private List previousRowSave;

private TableBody currentTablePart;

private boolean firstInTable;

private boolean firstInPart;

private List footerFirstRow;

private List footerLastRow;

private boolean inFooter;

CollapsingBorderResolver(Table table) {
this.table = table;
firstInTable = true;
}

/** {@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();
if (gu.getRowSpanIndex() == 0) {
gu.resolveBorder(CommonBorderPaddingBackground.BEFORE, tableRow);
}
if (gu.isLastGridUnitRowSpan()) {
gu.resolveBorder(CommonBorderPaddingBackground.AFTER, tableRow);
}
}
}
if (inFooter) {
if (footerFirstRow == null) {
footerFirstRow = row;
}
footerLastRow = row;
} else if (firstInTable) {
// Resolve border-before for the first row in the table
for (int i = 0; i < row.size(); i++) {
TableColumn column = table.getColumn(i);
((GridUnit) row.get(i)).resolveBorder(CommonBorderPaddingBackground.BEFORE, column);
}
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);
}
firstInPart = false;
}
if (previousRow != null) {
// Resolve after/before borders between rows
for (int i = 0; i < row.size(); i++) {
GridUnit gu = (GridUnit) row.get(i);
if (gu.getRowSpanIndex() == 0) {
GridUnit beforeGU = (GridUnit) previousRow.get(i);
gu.resolveBorder(beforeGU, CommonBorderPaddingBackground.BEFORE);
}
}
}
// 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);
}
gu = guEnd;
}
gu.resolveBorder(CommonBorderPaddingBackground.END, container);

previousRow = row;
}

/** {@inheritDoc} */
public void startPart(TableBody part) {
firstInPart = true;
currentTablePart = part;
if (part.isTableFooter()) {
inFooter = true;
previousRowSave = previousRow;
previousRow = null;
}
}

/** {@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);
}
if (inFooter) {
inFooter = false;
previousRow = previousRowSave;
}
}

/** {@inheritDoc} */
public void endTable() {
if (footerFirstRow != null) {
// 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);
}
}
List lastRow;
if (footerLastRow != null) {
lastRow = footerLastRow;
} else {
lastRow = previousRow;
}
// 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);
}
}
}

+ 148
- 0
src/java/org/apache/fop/fo/flow/table/FixedColRowGroupBuilder.java Vedi File

@@ -19,6 +19,15 @@

package org.apache.fop.fo.flow.table;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import org.apache.fop.fo.ValidationException;
import org.apache.fop.layoutmgr.table.EmptyGridUnit;
import org.apache.fop.layoutmgr.table.GridUnit;
import org.apache.fop.layoutmgr.table.PrimaryGridUnit;


/**
* A row group builder optimised for a fixed number of columns, known before the parsing
@@ -26,10 +35,149 @@ package org.apache.fop.fo.flow.table;
*/
class FixedColRowGroupBuilder extends RowGroupBuilder {

/** Number of columns in the corresponding table. */
private int numberOfColumns;

/** 0-based, index in the row group. */
private int currentRowIndex;

/** The rows belonging to this row group. List of List of {@link GridUnit}s. */
private List/*<List<GridUnit>>*/ rows;

private boolean firstInTable = true;

private boolean firstInPart = true;

/** The last encountered row. This is the last row of the table if it has no footer. */
private List lastRow;

private BorderResolver borderResolver;

private boolean inFooter;

private List lastFooterRow;

FixedColRowGroupBuilder(Table t) {
super(t);
numberOfColumns = t.getNumberOfColumns();
if (t.isSeparateBorderModel()) {
borderResolver = new SeparateBorderResolver();
} else {
borderResolver = new CollapsingBorderResolver(t);
}
initialize();
}

/**
* Prepares this builder for creating a new row group.
*/
private void initialize() {
rows = new ArrayList();
currentRowIndex = 0;
}

/** {@inheritDoc} */
void addTableCell(TableCell cell) {
for (int i = rows.size(); i < currentRowIndex + cell.getNumberRowsSpanned(); i++) {
List effRow = new ArrayList(numberOfColumns);
for (int j = 0; j < numberOfColumns; j++) {
effRow.add(null);
}
rows.add(effRow);
}
int columnIndex = cell.getColumnNumber() - 1;
PrimaryGridUnit pgu = new PrimaryGridUnit(cell, table.getColumn(columnIndex), columnIndex,
currentRowIndex);
List row = (List) rows.get(currentRowIndex);
row.set(columnIndex, pgu);
// TODO
GridUnit[] cellRow = new GridUnit[cell.getNumberColumnsSpanned()];
cellRow[0] = pgu;
for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
GridUnit gu = new GridUnit(pgu, table.getColumn(columnIndex + j),
columnIndex + j, j, 0);
row.set(columnIndex + j, gu);
cellRow[j] = gu;
}
pgu.addRow(cellRow);
for (int i = 1; i < cell.getNumberRowsSpanned(); i++) {
row = (List) rows.get(currentRowIndex + i);
cellRow = new GridUnit[cell.getNumberColumnsSpanned()];
for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) {
GridUnit gu = new GridUnit(pgu, table.getColumn(columnIndex + j),
columnIndex + j, j, i);
row.set(columnIndex + j, gu);
cellRow[j] = gu;
}
pgu.addRow(cellRow);
}
}

private static void setFlagForCols(int flag, List row) {
for (ListIterator iter = row.listIterator(); iter.hasNext();) {
((GridUnit) iter.next()).setFlag(flag);
}
}

/** {@inheritDoc} */
void endRow(TableCellContainer container) {
List currentRow = (List) rows.get(currentRowIndex);
lastRow = currentRow;
// Fill gaps with empty grid units
for (int i = 0; i < numberOfColumns; i++) {
if (currentRow.get(i) == null) {
currentRow.set(i, new EmptyGridUnit(table, currentRowIndex, i));
}
}
borderResolver.endRow(currentRow, container);
((GridUnit) currentRow.get(0)).setFlag(GridUnit.IN_FIRST_COLUMN);
((GridUnit) currentRow.get(numberOfColumns - 1)).setFlag(GridUnit.IN_LAST_COLUMN);
if (inFooter) {
lastFooterRow = currentRow;
} else if (firstInTable) {
setFlagForCols(GridUnit.FIRST_IN_TABLE, currentRow);
firstInTable = false;
}
if (firstInPart) {
setFlagForCols(GridUnit.FIRST_IN_PART, currentRow);
firstInPart = false;
}
if (currentRowIndex == rows.size() - 1) {
// Means that the current row has no cell spanning over following rows
container.getTablePart().addRowGroup(rows);
initialize();
} else {
currentRowIndex++;
}
}

/** {@inheritDoc} */
void startTablePart(TableBody part) {
firstInPart = true;
inFooter = part.isTableFooter();
borderResolver.startPart(part);
}

/** {@inheritDoc} */
void endTablePart(TableBody tableBody) throws ValidationException {
if (rows.size() > 0) {
throw new ValidationException(
"A table-cell is spanning more rows than available in its parent element.");
}
setFlagForCols(GridUnit.LAST_IN_PART, lastRow);
borderResolver.endPart(tableBody);
inFooter = false;
}

/** {@inheritDoc} */
void endTable(TableBody lastTablePart) {
List lastTableRow;
if (lastFooterRow != null) {
lastTableRow = lastFooterRow;
} else {
lastTableRow = lastRow;
}
setFlagForCols(GridUnit.LAST_IN_TABLE, lastTableRow);
borderResolver.endTable();
}
}

+ 26
- 72
src/java/org/apache/fop/fo/flow/table/RowGroupBuilder.java Vedi File

@@ -19,12 +19,8 @@

package org.apache.fop.fo.flow.table;

import java.util.ArrayList;
import java.util.List;

import org.apache.fop.fo.ValidationException;
import org.apache.fop.layoutmgr.table.GridUnit;
import org.apache.fop.layoutmgr.table.PrimaryGridUnit;

/**
* A class that creates groups of rows belonging to a same set of spans. The first row of
@@ -34,16 +30,7 @@ import org.apache.fop.layoutmgr.table.PrimaryGridUnit;
*/
abstract class RowGroupBuilder {

/** Number of columns in the corresponding table. */
protected int numberOfColumns;

/** 0-based, index in the row group. */
private int currentRowIndex;

private Table table;

/** The rows belonging to this row group. List of List of {@link GridUnit}s. */
protected List rows;
protected Table table;

/**
* Creates and initialises a new builder for the given table.
@@ -52,81 +39,48 @@ abstract class RowGroupBuilder {
*/
protected RowGroupBuilder(Table t) {
table = t;
initialize();
}


/**
* Prepares this builder for creating a new row group.
* Adds a table-cell to the current row-group, creating {@link GridUnit}s accordingly.
*
* @param cell the cell to add
*/
private void initialize() {
rows = new ArrayList();
currentRowIndex = 0;
}
abstract void addTableCell(TableCell cell);

/**
* Adds a table-cell to the row-group, creating {@link GridUnit}s accordingly.
* Receives notification of the end of the current row. If the current row finishes
* the row group, the {@link TableBody#addRowGroup(List)} method of the parent table
* part (i.e., the given container itself or its parent if this is a table-row) will
* be called
*
* @param cell
* @param container the parent element of the current row
*/
void addTableCell(TableCell cell) {
for (int i = rows.size(); i < currentRowIndex + cell.getNumberRowsSpanned(); i++) {
List effRow = new ArrayList(numberOfColumns);
for (int j = 0; j < numberOfColumns; j++) {
effRow.add(null);
}
rows.add(effRow);
}
int columnIndex = cell.getColumnNumber() - 1;
PrimaryGridUnit pgu = new PrimaryGridUnit(cell, table.getColumn(columnIndex), columnIndex,
currentRowIndex);
List row = (List) rows.get(currentRowIndex);
row.set(columnIndex, pgu);
for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
row.set(j + columnIndex,
new GridUnit(pgu, table.getColumn(columnIndex + j), columnIndex + j, j));
}
for (int i = 1; i < cell.getNumberRowsSpanned(); i++) {
row = (List) rows.get(currentRowIndex + i);
for (int j = 0; j < cell.getNumberColumnsSpanned(); j++) {
row.set(j + columnIndex,
new GridUnit(pgu, table.getColumn(columnIndex + j), columnIndex + j, j));
}
}
}
abstract void endRow(TableCellContainer container);

/**
* Signals that a table row has just ended, potentially finishing the current row
* group.
* Receives notification of the start of a table-header/footer/body.
*
* @param body the table-body containing the row. Its
* {@link TableBody#addRowGroup(List)} method will be called if the current row group
* is finished.
* @param part the part being started
*/
void signalRowEnd(TableBody body) {
if (currentRowIndex == rows.size() - 1) {
// Means that the current row has no cell spanning over following rows
body.addRowGroup(rows);
initialize();
} else {
currentRowIndex++;
}
}
abstract void startTablePart(TableBody part);

/**
* Signals that the end of a table-header/footer/body has been reached. The current
* Receives notification of the end of a table-header/footer/body. The current
* row-group is checked for emptiness. This row group builder is reset for handling
* further possible table parts.
*
* @param tableBody the table part being finished
* @throws ValidationException if a cell is spanning further than the given table part
* @param tableBody the table part being ended
* @throws ValidationException if a row-spanning cell overflows the given table part
*/
void signalEndOfPart(TableBody tableBody) throws ValidationException {
if (rows.size() > 0) {
throw new ValidationException(
"A table-cell is spanning more rows than available in its parent element.");
}
initialize();
}
abstract void endTablePart(TableBody tableBody) throws ValidationException;

/**
* Receives notification of the end of the table.
*
* @param lastTablePart the last part of the table
* @throws ValidationException if a row-spanning cell overflows one of the table's parts
*/
abstract void endTable(TableBody lastTablePart) throws ValidationException;
}

+ 44
- 0
src/java/org/apache/fop/fo/flow/table/SeparateBorderResolver.java Vedi File

@@ -0,0 +1,44 @@
/*
* 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 java.util.List;

/**
* A resolver for the separate-border model. Basically this class does nothing.
*/
class SeparateBorderResolver implements BorderResolver {

/** {@inheritDoc} */
public void endRow(List row, TableCellContainer container) {
}

/** {@inheritDoc} */
public void startPart(TableBody part) {
}

/** {@inheritDoc} */
public void endPart(TableBody part) {
}

/** {@inheritDoc} */
public void endTable() {
}
}

+ 18
- 30
src/java/org/apache/fop/fo/flow/table/Table.java Vedi File

@@ -20,7 +20,6 @@
package org.apache.fop.fo.flow.table;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.fop.apps.FOPException;
@@ -154,7 +153,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
/**
* {@inheritDoc}
*/
protected void startOfNode() throws FOPException {
public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startTable(this);
}
@@ -211,7 +210,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
/**
* {@inheritDoc}
*/
protected void endOfNode() throws FOPException {
public void endOfNode() throws FOPException {

if (!tableBodyFound) {
missingChildElementError(
@@ -219,6 +218,11 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
+ ",table-body+)");
}
if (!inMarker()) {
if (tableFooter != null) {
rowGroupBuilder.endTable(tableFooter);
} else {
rowGroupBuilder.endTable((TableBody) getChildNodes().lastNode());
}
/* clean up */
for (int i = columns.size(); --i >= 0;) {
TableColumn col = (TableColumn) columns.get(i);
@@ -278,6 +282,13 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
}
}

protected void setCollapsedBorders() {
createBorder(CommonBorderPaddingBackground.START);
createBorder(CommonBorderPaddingBackground.END);
createBorder(CommonBorderPaddingBackground.BEFORE);
createBorder(CommonBorderPaddingBackground.AFTER);
}

private void finalizeColumns() throws FOPException {
for (int i = 0; i < columns.size(); i++) {
if (columns.get(i) == null) {
@@ -305,32 +316,6 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
for (int i = columns.size() + 1; i <= columnNumber; i++) {
columns.add(createImplicitColumn(i));
}
((VariableColRowGroupBuilder) rowGroupBuilder).ensureNumberOfColumns(columnNumber);
if (tableHeader != null) {
for (Iterator iter = tableHeader.getRowGroups().iterator(); iter.hasNext();) {
VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(),
columnNumber);
}
}
if (tableFooter != null) {
for (Iterator iter = tableFooter.getRowGroups().iterator(); iter.hasNext();) {
VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(),
columnNumber);
}
}
FONodeIterator bodyIter = getChildNodes();
if (bodyIter != null) {
while (bodyIter.hasNext()) {
FONode node = bodyIter.nextNode();
if (node instanceof TableBody) { // AFAIK, may be a marker
for (Iterator iter = ((TableBody) node).getRowGroups().iterator();
iter.hasNext();) {
VariableColRowGroupBuilder.fillWithEmptyGridUnits((List) iter.next(),
columnNumber);
}
}
}
}
}

private TableColumn createImplicitColumn(int colNumber)
@@ -342,6 +327,9 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
implicitColumn.bind(pList);
implicitColumn.setColumnWidth(new TableColLength(1.0, implicitColumn));
implicitColumn.setColumnNumber(colNumber);
if (!isSeparateBorderModel()) {
implicitColumn.setCollapsedBorders(collapsingBorderModel); // TODO
}
return implicitColumn;
}

@@ -399,7 +387,7 @@ public class Table extends TableFObj implements ColumnNumberManagerHolder {
* @param index index of the column to be retrieved, 0-based
* @return the corresponding column (may be an implicitly created column)
*/
TableColumn getColumn(int index) {
public/*TODO*/ TableColumn getColumn(int index) {
return (TableColumn) columns.get(index);
}


+ 48
- 19
src/java/org/apache/fop/fo/flow/table/TableBody.java Vedi File

@@ -50,15 +50,15 @@ public class TableBody extends TableCellContainer {
protected boolean tableRowsFound = false;
protected boolean tableCellsFound = false;

/**
* used for initial values of column-number property
*/
private boolean firstRow = true;

private boolean rowsStarted = false;

private boolean lastCellEndsRow = true;

/** The last encountered table-row. */
private TableRow lastRow;

private List rowGroups = new LinkedList();

/**
@@ -101,14 +101,15 @@ public class TableBody extends TableCellContainer {
/**
* {@inheritDoc}
*/
protected void startOfNode() throws FOPException {
public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startBody(this);
}

/**
* {@inheritDoc}
*/
protected void endOfNode() throws FOPException {
public void endOfNode() throws FOPException {

if (!inMarker()) {
pendingSpans = null;
@@ -130,16 +131,25 @@ public class TableBody extends TableCellContainer {
}
}

/** {@inheritDoc} */
TableBody getTablePart() {
return this;
}

protected void finishLastRowGroup() throws ValidationException {
RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
if (tableRowsFound || !lastCellEndsRow) {
rowGroupBuilder.signalRowEnd(this);
}
try {
rowGroupBuilder.signalEndOfPart(this);
} catch (ValidationException e) {
e.setLocator(locator);
throw e;
if (!inMarker()) {
RowGroupBuilder rowGroupBuilder = getTable().getRowGroupBuilder();
if (tableRowsFound) {
rowGroupBuilder.endRow(lastRow);
} else if (!lastCellEndsRow) {
rowGroupBuilder.endRow(this);
}
try {
rowGroupBuilder.endTablePart(this);
} catch (ValidationException e) {
e.setLocator(locator);
throw e;
}
}
}

@@ -184,13 +194,19 @@ public class TableBody extends TableCellContainer {
if (!inMarker()) {
switch (child.getNameId()) {
case FO_TABLE_ROW:
if (rowsStarted) {
if (!rowsStarted) {
getTable().getRowGroupBuilder().startTablePart(this);
} else {
columnNumberManager.prepareForNextRow(pendingSpans);
getTable().getRowGroupBuilder().signalRowEnd(this);
getTable().getRowGroupBuilder().endRow(lastRow);
}
rowsStarted = true;
lastRow = (TableRow) child;
break;
case FO_TABLE_CELL:
if (!rowsStarted) {
getTable().getRowGroupBuilder().startTablePart(this);
}
rowsStarted = true;
TableCell cell = (TableCell) child;
addTableCellChild(cell, firstRow);
@@ -198,7 +214,7 @@ public class TableBody extends TableCellContainer {
if (lastCellEndsRow) {
firstRow = false;
columnNumberManager.prepareForNextRow(pendingSpans);
getTable().getRowGroupBuilder().signalRowEnd(this);
getTable().getRowGroupBuilder().endRow(this);
}
break;
default:
@@ -208,11 +224,20 @@ public class TableBody extends TableCellContainer {
super.addChildNode(child);
}

/** {inheritDoc} */
protected void setCollapsedBorders() {
Table table = (Table) parent;
createBorder(CommonBorderPaddingBackground.START, table);
createBorder(CommonBorderPaddingBackground.END, table);
createBorder(CommonBorderPaddingBackground.BEFORE);
createBorder(CommonBorderPaddingBackground.AFTER);
}

void addRowGroup(List rowGroup) {
rowGroups.add(rowGroup);
}

List getRowGroups() {
public List getRowGroups() {
return rowGroups;
}

@@ -235,6 +260,10 @@ public class TableBody extends TableCellContainer {
return FO_TABLE_BODY;
}

protected boolean isTableFooter() {
return false;
}

/**
* @param obj table row in question
* @return true if the given table row is the first row of this body.
@@ -249,7 +278,7 @@ public class TableBody extends TableCellContainer {
firstRow = false;
if (!lastCellEndsRow) {
columnNumberManager.prepareForNextRow(pendingSpans);
getTable().getRowGroupBuilder().signalRowEnd(this);
getTable().getRowGroupBuilder().endRow(this);
}
}
rowsStarted = true;

+ 17
- 2
src/java/org/apache/fop/fo/flow/table/TableCell.java Vedi File

@@ -90,7 +90,7 @@ public class TableCell extends TableFObj {
/**
* {@inheritDoc}
*/
protected void startOfNode() throws FOPException {
public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startCell(this);
}
@@ -100,7 +100,7 @@ public class TableCell extends TableFObj {
* FOEventHandler that we are at the end of the flow.
* {@inheritDoc}
*/
protected void endOfNode() throws FOPException {
public void endOfNode() throws FOPException {
if (!blockItemFound) {
if (getUserAgent().validateStrictly()) {
missingChildElementError("marker* (%block;)+");
@@ -134,6 +134,21 @@ public class TableCell extends TableFObj {
}
}

/** {@inheritDoc} */
protected void setCollapsedBorders() {
createBorder(CommonBorderPaddingBackground.BEFORE);
createBorder(CommonBorderPaddingBackground.AFTER);
Table table = getTable();
if (table.hasExplicitColumns()) {
TableColumn col = table.getColumn(getColumnNumber() - 1);
createBorder(CommonBorderPaddingBackground.START, col);
createBorder(CommonBorderPaddingBackground.END, col);
} else {
createBorder(CommonBorderPaddingBackground.START);
createBorder(CommonBorderPaddingBackground.END);
}
}

/** {@inheritDoc} */
public boolean generatesReferenceAreas() {
return true;

+ 7
- 0
src/java/org/apache/fop/fo/flow/table/TableCellContainer.java Vedi File

@@ -93,6 +93,13 @@ public abstract class TableCellContainer extends TableFObj implements ColumnNumb
}
}

/**
* Returns the enclosing table-header/footer/body of this container.
*
* @return <code>this</code> for TableBody, or the parent element for TableRow
*/
abstract TableBody getTablePart();

/** {@inheritDoc} */
public ColumnNumberManager getColumnNumberManager() {
return columnNumberManager;

+ 19
- 5
src/java/org/apache/fop/fo/flow/table/TableColumn.java Vedi File

@@ -31,6 +31,7 @@ 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;
import org.apache.fop.layoutmgr.table.CollapsingBorderModel;

/**
* Class modelling the fo:table-column object.
@@ -114,14 +115,27 @@ public class TableColumn extends TableFObj {
/**
* {@inheritDoc}
*/
protected void startOfNode() throws FOPException {
public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startColumn(this);
}

/**
* {@inheritDoc}
*/
protected void endOfNode() throws FOPException {
void setCollapsedBorders(CollapsingBorderModel collapsingBorderModel) {
this.collapsingBorderModel = collapsingBorderModel;
setCollapsedBorders();
}

/** {@inheritDoc} */
protected void setCollapsedBorders() {
Table table = (Table) parent;
createBorder(CommonBorderPaddingBackground.BEFORE, table);
createBorder(CommonBorderPaddingBackground.AFTER, table);
createBorder(CommonBorderPaddingBackground.START);
createBorder(CommonBorderPaddingBackground.END);
}

/** {@inheritDoc} */
public void endOfNode() throws FOPException {
getFOEventHandler().endColumn(this);
}


+ 57
- 3
src/java/org/apache/fop/fo/flow/table/TableFObj.java Vedi File

@@ -30,6 +30,7 @@ import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.NumberProperty;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.layoutmgr.table.CollapsingBorderModel;

/**
* Common base class for table-related FOs
@@ -41,6 +42,10 @@ public abstract class TableFObj extends FObj {
private Numeric borderEndPrecedence;
private Numeric borderStartPrecedence;

public/*TODO*/ BorderSpecification[] resolvedBorders = new BorderSpecification[4]; // TODO

CollapsingBorderModel collapsingBorderModel;
/**
* Main constructor
*
@@ -122,9 +127,7 @@ public abstract class TableFObj extends FObj {
super(propId);
}

/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
public Property make(PropertyList propertyList)
throws PropertyException {
FObj fo = propertyList.getFObj();
@@ -189,4 +192,55 @@ public abstract class TableFObj extends FObj {
return p;
}
}

/** {@inheritDoc} */
public void startOfNode() throws FOPException {
super.startOfNode();
Table table = getTable();
if (!inMarker() && !table.isSeparateBorderModel()) {
collapsingBorderModel = CollapsingBorderModel.getBorderModelFor(table
.getBorderCollapse());
resolvedBorders = new BorderSpecification[4];
setCollapsedBorders();
}
}

/*
* TODO made public so that RetrieveMarker can access it.
*/
/** {@inheritDoc} */
public void endOfNode() throws FOPException {
super.endOfNode();
}

/**
* Prepares the borders of this element if the collapsing-border model is in use.
* Conflict resolution with parent elements is done where applicable.
*/
protected abstract void setCollapsedBorders();

/**
* Creates a BorderSpecification from the border set on the given side. If no border
* is set, a BorderSpecification with border-style none is created.
*
* @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END
*/
protected void createBorder(int side) {
resolvedBorders[side] = new BorderSpecification(getCommonBorderPaddingBackground()
.getBorderInfo(side), getNameId());
}

/**
* Creates a BorderSpecification from the border set on the given side, performing
* conflict resolution with the same border on the given object.
*
* @param side one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END
* @param competitor a parent table element whose side coincides with the given side
* on this element
*/
protected void createBorder(int side, TableFObj competitor) {
createBorder(side);
resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side],
competitor.resolvedBorders[side]);
}
}

+ 8
- 2
src/java/org/apache/fop/fo/flow/table/TableFooter.java Vedi File

@@ -39,14 +39,15 @@ public class TableFooter extends TableBody {
/**
* {@inheritDoc}
*/
protected void startOfNode() throws FOPException {
public void startOfNode() throws FOPException {
super.startOfNode();
//getFOEventHandler().startBody(this);
}

/**
* {@inheritDoc}
*/
protected void endOfNode() throws FOPException {
public void endOfNode() throws FOPException {
// getFOEventHandler().endFooter(this);
if (!(tableRowsFound || tableCellsFound)) {
missingChildElementError("marker* (table-row+|table-cell+)");
@@ -65,4 +66,9 @@ public class TableFooter extends TableBody {
public int getNameId() {
return FO_TABLE_FOOTER;
}

/** {@inheritDoc} */
protected boolean isTableFooter() {
return true;
}
}

+ 3
- 2
src/java/org/apache/fop/fo/flow/table/TableHeader.java Vedi File

@@ -39,14 +39,15 @@ public class TableHeader extends TableBody {
/**
* {@inheritDoc}
*/
protected void startOfNode() throws FOPException {
public void startOfNode() throws FOPException {
super.startOfNode();
//getFOEventHandler().startHeader(this);
}

/**
* {@inheritDoc}
*/
protected void endOfNode() throws FOPException {
public void endOfNode() throws FOPException {
// getFOEventHandler().endHeader(this);
if (!(tableRowsFound || tableCellsFound)) {
missingChildElementError("marker* (table-row+|table-cell+)");

+ 21
- 2
src/java/org/apache/fop/fo/flow/table/TableRow.java Vedi File

@@ -97,7 +97,7 @@ public class TableRow extends TableCellContainer {
/**
* {@inheritDoc}
*/
protected void startOfNode() throws FOPException {
public void startOfNode() throws FOPException {
super.startOfNode();
getFOEventHandler().startRow(this);
}
@@ -105,7 +105,7 @@ public class TableRow extends TableCellContainer {
/**
* {@inheritDoc}
*/
protected void endOfNode() throws FOPException {
public void endOfNode() throws FOPException {
if (firstChild == null) {
missingChildElementError("(table-cell+)");
}
@@ -128,6 +128,25 @@ public class TableRow extends TableCellContainer {
}
}

/** {@inheritDoc} */
TableBody getTablePart() {
return (TableBody) parent;
}

/** {@inheritDoc} */
boolean isTableRow() {
return true;
}

/** {inheritDoc} */
protected void setCollapsedBorders() {
TableBody body = (TableBody) parent;
createBorder(CommonBorderPaddingBackground.START, body);
createBorder(CommonBorderPaddingBackground.END, body);
createBorder(CommonBorderPaddingBackground.BEFORE);
createBorder(CommonBorderPaddingBackground.AFTER);
}

/** @return the "break-after" property. */
public int getBreakAfter() {
return breakAfter;

+ 60
- 22
src/java/org/apache/fop/fo/flow/table/VariableColRowGroupBuilder.java Vedi File

@@ -19,9 +19,12 @@

package org.apache.fop.fo.flow.table;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.fop.layoutmgr.table.EmptyGridUnit;
import org.apache.fop.fo.ValidationException;


/**
* A row group builder accommodating a variable number of columns. More flexible, but less
@@ -31,34 +34,69 @@ class VariableColRowGroupBuilder extends RowGroupBuilder {

VariableColRowGroupBuilder(Table t) {
super(t);
numberOfColumns = 1;
}

/**
* Fills the given row group with empty grid units if necessary, so that it matches
* the given number of columns.
*
* @param rowGroup a List of List of GridUnit
* @param numberOfColumns the number of columns that the row group must have
* Each event is recorded and will be played once the table is finished, and the final
* number of columns known.
*/
static void fillWithEmptyGridUnits(List rowGroup, int numberOfColumns) {
for (int i = 0; i < rowGroup.size(); i++) {
List effRow = (List) rowGroup.get(i);
for (int j = effRow.size(); j < numberOfColumns; j++) {
effRow.add(new EmptyGridUnit(null, null, null, j));
private static interface Event {
/**
* Plays this event
*
* @param rowGroupBuilder the delegate builder which will actually create the row
* groups
* @throws ValidationException if a row-spanning cell overflows its parent body
*/
void play(RowGroupBuilder rowGroupBuilder) throws ValidationException;
}

/** The queue of events sent to this builder. */
private List events = new LinkedList();

/** {@inheritDoc} */
void addTableCell(final TableCell cell) {
events.add(new Event() {
public void play(RowGroupBuilder rowGroupBuilder) {
rowGroupBuilder.addTableCell(cell);
}
}
});
}

/**
* Updates the current row group to match the given number of columns, by adding empty
* grid units if necessary.
*
* @param numberOfColumns new number of columns
*/
void ensureNumberOfColumns(int numberOfColumns) {
this.numberOfColumns = numberOfColumns;
fillWithEmptyGridUnits(rows, numberOfColumns);
/** {@inheritDoc} */
void endRow(final TableCellContainer container) {
events.add(new Event() {
public void play(RowGroupBuilder rowGroupBuilder) {
rowGroupBuilder.endRow(container);
}
});
}

/** {@inheritDoc} */
void startTablePart(final TableBody part) {
events.add(new Event() {
public void play(RowGroupBuilder rowGroupBuilder) {
rowGroupBuilder.startTablePart(part);
}
});
}

/** {@inheritDoc} */
void endTablePart(final TableBody tableBody) throws ValidationException {
// TODO catch the ValidationException sooner?
events.add(new Event() {
public void play(RowGroupBuilder rowGroupBuilder) throws ValidationException {
rowGroupBuilder.endTablePart(tableBody);
}
});
}

/** {@inheritDoc} */
void endTable(final TableBody lastTablePart) throws ValidationException {
RowGroupBuilder delegate = new FixedColRowGroupBuilder(table);
for (Iterator eventIter = events.iterator(); eventIter.hasNext();) {
((Event) eventIter.next()).play(delegate);
}
delegate.endTable(lastTablePart);
}
}

+ 6
- 2
src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java Vedi File

@@ -83,7 +83,7 @@ public class CommonBorderPaddingBackground {
private Color mColor; // Border color
private CondLengthProperty mWidth;

BorderInfo(int style, CondLengthProperty width, Color color) {
public BorderInfo(int style, CondLengthProperty width, Color color) {
mStyle = style;
mWidth = width;
mColor = color;
@@ -227,7 +227,11 @@ public class CommonBorderPaddingBackground {
* @return the border info for a side
*/
public BorderInfo getBorderInfo(int side) {
return this.borderInfo[side];
if (this.borderInfo[side] == null) {
return new BorderInfo(Constants.EN_NONE, null, null); // TODO
} else {
return this.borderInfo[side];
}
}
/**

+ 74
- 20
src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModel.java Vedi File

@@ -20,8 +20,8 @@
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;

/**
* This class is a superclass for the two collapsing border models defined
@@ -37,10 +37,7 @@ public abstract class CollapsingBorderModel {
protected static final int START = CommonBorderPaddingBackground.START;
/** end side */
protected static final int END = CommonBorderPaddingBackground.END;
/** Flag: current grid unit is either start or end of the table. */
public static final int VERTICAL_START_END_OF_TABLE = 1;

/** Indicates that the cell is/starts in the first row being painted on a particular page */
//public static final int FIRST_ROW_IN_TABLE_PART = 1;
/** Indicates that the cell is/ends in the last row being painted on a particular page */
@@ -53,7 +50,7 @@ public abstract class CollapsingBorderModel {
//These statics are used singleton-style. No MT issues here.
private static CollapsingBorderModel collapse = null;
private static CollapsingBorderModel collapseWithPrecedence = null;
/**
* @param borderCollapse border collapse control
* @return the border model for the cell
@@ -74,12 +71,12 @@ public abstract class CollapsingBorderModel {
throw new IllegalArgumentException("Illegal border-collapse mode.");
}
}
/**
* @param side the side on the current cell
* @return the adjacent side on the neighbouring cell
*/
public static int getOtherSide(int side) {
static int getOtherSide(int side) {
switch (side) {
case CommonBorderPaddingBackground.BEFORE:
return CommonBorderPaddingBackground.AFTER;
@@ -93,23 +90,32 @@ public abstract class CollapsingBorderModel {
throw new IllegalArgumentException("Illegal parameter: side");
}
}
/**
* @param side the side to investigate
* @return true if the adjacent cell is before or after
*/
protected boolean isVerticalRelation(int side) {
return (side == CommonBorderPaddingBackground.BEFORE
return (side == CommonBorderPaddingBackground.BEFORE
|| side == CommonBorderPaddingBackground.AFTER);
}

private static int compareInt(int value1, int value2) {
if (value1 < value2) {
return -1;
} else if (value1 == value2) {
return 0;
} else {
return 1;
}
}

/**
* See rule 4 in 6.7.10 for the collapsing border model.
* @param style the border style to get the preference value for
* @return the preference value of the style
*/
public int getPreferenceValue(int style) {
private static int getStylePreferenceValue(int style) {
switch (style) {
case Constants.EN_DOUBLE: return 0;
case Constants.EN_SOLID: return -1;
@@ -122,14 +128,62 @@ public abstract class CollapsingBorderModel {
default: throw new IllegalStateException("Illegal border style: " + style);
}
}

/**
* Compares the two given styles (see {@link Constants}).
*
* @param style1 a style constant
* @param style2 another style constant
* @return a value &lt; 0 if style1 has less priority than style2, 0 if both are
* equal, a value &gt; 0 if style1 has more priority than style2
*/
static int compareStyles(int style1, int style2) {
int value1 = getStylePreferenceValue(style1);
int value2 = getStylePreferenceValue(style2);
return compareInt(value1, value2);
}

private static int getHolderPreferenceValue(int id) {
switch (id) {
case Constants.FO_TABLE_CELL: return 0;
case Constants.FO_TABLE_ROW: return -1;
case Constants.FO_TABLE_HEADER:
case Constants.FO_TABLE_FOOTER:
case Constants.FO_TABLE_BODY:
return -2;
case Constants.FO_TABLE_COLUMN: return -3;
// TODO colgroup
case Constants.FO_TABLE: return -4;
default: throw new IllegalStateException();
}
}

/**
* Compares the two given FO ids ({@link Constants}.FO*) in terms of border
* declaration.
*
* @param id1 a FO id ({@link Constants#FO_TABLE}, {@link Constants#FO_TABLE_BODY},
* etc.)
* @param id2 another FO id
* @return a value &lt; 0 if id1 has less priority than id2, 0 if both are equal, a
* value &gt; 0 if id1 has more priority than id2
*/
static int compareFOs(int id1, int id2) {
int p1 = getHolderPreferenceValue(id1);
int p2 = getHolderPreferenceValue(id2);
return compareInt(p1, p2);
}

/**
* Determines the winning BorderInfo.
* @param current grid unit of the current element
* @param neighbour grid unit of the neighbouring element
* @return the winning BorderInfo
* Returns the border which wins the border conflict resolution. In case the two
* borders are equivalent (identical, or only the color is different), null is
* returned.
*
* @param border1 a border specification
* @param border2 another border specification
* @return the winning border, null if the two borders are equivalent
*/
public abstract BorderInfo determineWinner(
GridUnit current, GridUnit neighbour, int side, int flags);
public abstract BorderSpecification determineWinner(BorderSpecification border1,
BorderSpecification border2);
}

+ 36
- 263
src/java/org/apache/fop/layoutmgr/table/CollapsingBorderModelEyeCatching.java Vedi File

@@ -20,11 +20,7 @@
package org.apache.fop.layoutmgr.table;

import org.apache.fop.fo.Constants;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.flow.table.BorderSpecification;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;

/**
@@ -34,268 +30,45 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
*/
public class CollapsingBorderModelEyeCatching extends CollapsingBorderModel {

public BorderInfo determineWinner(GridUnit currentGridUnit,
GridUnit otherGridUnit, int side, int flags) {
final boolean vertical = isVerticalRelation(side);
final int otherSide = getOtherSide(side);
//Get cells
TableCell currentCell = currentGridUnit.getCell();
TableCell otherCell = null;
if (otherGridUnit != null) {
otherCell = otherGridUnit.getCell();
}
//Get rows
TableRow currentRow = currentGridUnit.getRow();
TableRow otherRow = null;
if (vertical && otherCell != null) {
otherRow = otherGridUnit.getRow();
}
//get bodies
TableBody currentBody = currentGridUnit.getBody();
TableBody otherBody = null;
if (otherRow != null) {
otherBody = otherGridUnit.getBody();
}

//get columns
TableColumn currentColumn = currentGridUnit.getColumn();
TableColumn otherColumn = null;
if (otherGridUnit != null) {
otherColumn = otherGridUnit.getColumn();
}
//TODO get column groups
//Get table
Table table = currentGridUnit.getTable();
//----------------------------------------------------------------------
//We're creating two arrays containing the applicable BorderInfos for
//each cell in question.
//0 = cell, 1 = row, 2 = row group (body), 3 = column,
//4 = col group (spanned column, see 6.7.3), 5 = table

BorderInfo[] current = new BorderInfo[6];
BorderInfo[] other = new BorderInfo[6];
//cell
current[0] = currentGridUnit.getOriginalBorderInfoForCell(side);
if (otherGridUnit != null) {
other[0] = otherGridUnit.getOriginalBorderInfoForCell(otherSide);
}
if ((currentRow != null)
&& (side == BEFORE
|| side == AFTER
|| (currentGridUnit.getFlag(GridUnit.IN_FIRST_COLUMN) && side == START)
|| (currentGridUnit.getFlag(GridUnit.IN_LAST_COLUMN) && side == END))) {
//row
current[1] = currentRow.getCommonBorderPaddingBackground().getBorderInfo(side);
}
if (otherRow != null) {
//row
other[1] = otherRow.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
}
if (currentBody != null
&& ((side == BEFORE && currentGridUnit.getFlag(GridUnit.FIRST_IN_PART))
|| (side == AFTER && currentGridUnit.getFlag(GridUnit.LAST_IN_PART))
|| (currentGridUnit.getFlag(GridUnit.IN_FIRST_COLUMN) && side == START)
|| (currentGridUnit.getFlag(GridUnit.IN_LAST_COLUMN) && side == END))) {
//row group (=body, table-header or table-footer)
current[2] = currentBody.getCommonBorderPaddingBackground().getBorderInfo(side);
}
if (otherGridUnit != null
&& otherBody != null
&& ((otherSide == BEFORE && otherGridUnit.getFlag(GridUnit.FIRST_IN_PART))
|| (otherSide == AFTER && otherGridUnit.getFlag(GridUnit.LAST_IN_PART)))) {
//row group (=body, table-header or table-footer)
other[2] = otherBody.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
}
if ((side == BEFORE && otherGridUnit == null)
|| (side == AFTER && otherGridUnit == null)
|| (side == START)
|| (side == END)) {
//column
current[3] = currentColumn.getCommonBorderPaddingBackground().getBorderInfo(side);
}
if (otherColumn != null) {
//column
other[3] = otherColumn.getCommonBorderPaddingBackground().getBorderInfo(otherSide);
}
//TODO current[4] and other[4] for column groups
if (otherGridUnit == null
&& ((side == BEFORE && (flags & VERTICAL_START_END_OF_TABLE) > 0)
|| (side == AFTER && (flags & VERTICAL_START_END_OF_TABLE) > 0)
|| (side == START)
|| (side == END))) {
//table
current[5] = table.getCommonBorderPaddingBackground().getBorderInfo(side);
}
//other[6] is always null, since it's always the same table
BorderInfo resolved = null;
// *** Rule 1 ***
resolved = doRule1(current, other);
if (resolved != null) {
return resolved;
}
// *** Rule 2 ***
if (!doRule2(current, other)) {
}
// *** Rule 3 ***
resolved = doRule3(current, other);
if (resolved != null) {
return resolved;
}
// *** Rule 4 ***
resolved = doRule4(current, other);
if (resolved != null) {
return resolved;
}
// *** Rule 5 ***
resolved = doRule5(current, other);
if (resolved != null) {
return resolved;
}
return null; //no winner, no border
}

private BorderInfo doRule1(BorderInfo[] current, BorderInfo[] other) {
for (int i = 0; i < current.length; i++) {
if ((current[i] != null) && (current[i].getStyle() == Constants.EN_HIDDEN)) {
return current[i];
}
if ((other[i] != null) && (other[i].getStyle() == Constants.EN_HIDDEN)) {
return other[i];
}
}
return null;
}
private boolean doRule2(BorderInfo[] current, BorderInfo[] other) {
boolean found = false;
for (int i = 0; i < current.length; i++) {
if ((current[i] != null) && (current[i].getStyle() != Constants.EN_NONE)) {
found = true;
break;
/** {@inheritDoc} */
public BorderSpecification determineWinner(BorderSpecification border1,
BorderSpecification border2) {
BorderInfo bi1 = border1.getBorderInfo();
BorderInfo bi2 = border2.getBorderInfo();
// Rule 1
if (bi1.getStyle() == Constants.EN_HIDDEN) {
return border1;
} else if (bi2.getStyle() == Constants.EN_HIDDEN) {
return border2;
}
// Rule 2
if (bi2.getStyle() == Constants.EN_NONE) {
return border1;
} else if (bi1.getStyle() == Constants.EN_NONE) {
return border2;
}
// Rule 3
int width1 = bi1.getRetainedWidth();
int width2 = bi2.getRetainedWidth();
if (width1 > width2) {
return border1;
} else if (width1 == width2) {
int cmp = compareStyles(bi1.getStyle(), bi2.getStyle());
if (cmp > 0) {
return border1;
} else if (cmp < 0) {
return border2;
}
if ((other[i] != null) && (other[i].getStyle() != Constants.EN_NONE)) {
found = true;
break;
}
}
return found;
}

private BorderInfo doRule3(BorderInfo[] current, BorderInfo[] other) {
int width = 0;
//Find max border width
for (int i = 0; i < current.length; i++) {
if ((current[i] != null) && (current[i].getRetainedWidth() > width)) {
width = current[i].getRetainedWidth();
}
if ((other[i] != null) && (other[i].getRetainedWidth() > width)) {
width = other[i].getRetainedWidth();
}
}
BorderInfo widest = null;
int count = 0;
//See if there's only one with the widest border
for (int i = 0; i < current.length; i++) {
if ((current[i] != null) && (current[i].getRetainedWidth() == width)) {
count++;
if (widest == null) {
widest = current[i];
}
} else {
current[i] = null; //Discard the narrower ones
}
if ((other[i] != null) && (other[i].getRetainedWidth() == width)) {
count++;
if (widest == null) {
widest = other[i];
}
} else {
other[i] = null; //Discard the narrower ones
}
}
if (count == 1) {
return widest;
} else {
return null;
return border2;
}
}

private BorderInfo doRule4(BorderInfo[] current, BorderInfo[] other) {
int pref = getPreferenceValue(Constants.EN_INSET); //Lowest preference
//Find highest preference value
for (int i = 0; i < current.length; i++) {
if (current[i] != null) {
int currPref = getPreferenceValue(current[i].getStyle());
if (currPref > pref) {
pref = currPref;
}
}
if (other[i] != null) {
int currPref = getPreferenceValue(other[i].getStyle());
if (currPref > pref) {
pref = currPref;
}
}
}
BorderInfo preferred = null;
int count = 0;
//See if there's only one with the preferred border style
for (int i = 0; i < current.length; i++) {
if (current[i] != null) {
int currPref = getPreferenceValue(current[i].getStyle());
if (currPref == pref) {
count++;
if (preferred == null) {
preferred = current[i];
}
break;
}
} else {
current[i] = null; //Discard the ones that are not preferred
}
if (other[i] != null) {
int currPref = getPreferenceValue(other[i].getStyle());
if (currPref == pref) {
count++;
if (preferred == null) {
preferred = other[i];
}
break;
}
} else {
other[i] = null; //Discard the ones that are not preferred
}
}
if (count == 1) {
return preferred;
} else {
return null;
}
}

private BorderInfo doRule5(BorderInfo[] current, BorderInfo[] other) {
for (int i = 0; i < current.length; i++) {
if (current[i] != null) {
return current[i];
}
if (other[i] != null) {
return other[i];
}
// Rule 4
int cmp = compareFOs(border1.getHolder(), border2.getHolder());
if (cmp > 0) {
return border1;
} else if (cmp < 0) {
return border2;
}
return null;
}

}

+ 4
- 2
src/java/org/apache/fop/layoutmgr/table/EffRow.java Vedi File

@@ -47,12 +47,14 @@ class EffRow {
* Creates a new effective row instance.
* @param index index of the row
* @param bodyType type of body (one of HEADER, FOOTER, BODY as found on TableRowIterator)
* @param gridUnits the grid units this row is made of
*/
public EffRow(int index, int bodyType) {
public EffRow(int index, int bodyType, List gridUnits) {
this.index = index;
this.bodyType = bodyType;
this.gridUnits = gridUnits;
}
/** @return the index of the EffRow in the sequence of rows */
public int getIndex() {
return this.index;

+ 35
- 13
src/java/org/apache/fop/layoutmgr/table/EmptyGridUnit.java Vedi File

@@ -19,9 +19,12 @@

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.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;

/**
* GridUnit subclass for empty grid units.
@@ -30,25 +33,34 @@ public class EmptyGridUnit extends GridUnit {

private TableRow row;
private TableBody body;
/**
* @param row Optional table-row instance
* @param column table-column instance
* @param body table-body the grid unit belongs to
* @param startCol column index
* @param table the containing table
* @param startRow index of the row this grid unit belongs to, 0-based
* @param startCol column index, 0-based
*/
public EmptyGridUnit(TableRow row, TableColumn column, TableBody body,
int startCol) {
super(null, null, column, startCol, 0);
this.row = row;
this.body = body;
public EmptyGridUnit(Table table, int startRow, int startCol) {
super(table, table.getColumn(startCol), startCol, 0, 0);
}

/** {@inheritDoc} */
protected void setBorder(int side) {
resolvedBorders[side] = new BorderSpecification(
new CommonBorderPaddingBackground.BorderInfo(Constants.EN_NONE, null, null),
Constants.FO_TABLE_CELL);
}

/** {@inheritDoc} */
public PrimaryGridUnit getPrimary() {
throw new UnsupportedOperationException();
// return this; TODO
}

/** {@inheritDoc} */
public boolean isPrimary() {
return true;
}
/** {@inheritDoc} */
public TableBody getBody() {
return this.body;
@@ -58,4 +70,14 @@ public class EmptyGridUnit extends GridUnit {
public TableRow getRow() {
return this.row;
}

/** {@inheritDoc} */
public boolean isLastGridUnitColSpan() {
return true;
}

/** {@inheritDoc} */
public boolean isLastGridUnitRowSpan() {
return true;
}
}

+ 145
- 82
src/java/org/apache/fop/layoutmgr/table/GridUnit.java Vedi File

@@ -22,10 +22,12 @@ package org.apache.fop.layoutmgr.table;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.table.BorderSpecification;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableFObj;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
@@ -39,81 +41,142 @@ public class GridUnit {

/** Indicates that the grid unit is in the first column. */
public static final int IN_FIRST_COLUMN = 0;

/** Indicates that the grid unit is in the last column. */
public static final int IN_LAST_COLUMN = 1;

/** Indicates that the grid unit is in the first row of the table. */
public static final int FIRST_IN_TABLE = 2;
/** Indicates that the grid unit is in the first row of the table part (header, footer, body). */

/**
* Indicates that the grid unit is in the first row of the table part (header, footer,
* body).
*/
public static final int FIRST_IN_PART = 3;
/** Indicates that the grid unit is in the last row of the table part (header, footer, body). */

/**
* Indicates that the grid unit is in the last row of the table part (header, footer,
* body).
*/
public static final int LAST_IN_PART = 4;

/** Indicates that the grid unit is in the last row of the table. */
public static final int LAST_IN_TABLE = 5;

/** Indicates that the primary grid unit has a pending keep-with-next. */
public static final int KEEP_WITH_NEXT_PENDING = 6;

/** Indicates that the primary grid unit has a pending keep-with-previous. */
public static final int KEEP_WITH_PREVIOUS_PENDING = 7;

/** Primary grid unit */
private PrimaryGridUnit primary;

/** Table cell which occupies this grid unit */
private TableCell cell;
protected TableCell cell;

/** Table row which occupies this grid unit (may be null) */
private TableRow row;

/** Table column that this grid unit belongs to */
private TableColumn column;

/** start index of grid unit within row in column direction */
private int startCol;

/** index of grid unit within cell in column direction */
private int colSpanIndex;

/** index of grid unit within cell in row direction */
private int rowSpanIndex;

/** effective borders for a cell slot */
private CommonBorderPaddingBackground effectiveBorders;

/** flags for the grid unit */
private byte flags = 0;

protected BorderSpecification[] resolvedBorders;

private CollapsingBorderModel collapsingBorderModel;

/**
* Creates a new grid unit.
*
* @param cell table cell which occupies this grid unit
*
* @param table the containing table
* @param column table column this grid unit belongs to
* @param startCol index of the column this grid unit belongs to
* @param colSpanIndex index of this grid unit in the span, in column direction
* @param rowSpanIndex index of this grid unit in the span, in row direction
*/
public GridUnit(TableCell cell, TableColumn column, int startCol, int colSpanIndex) {
this(null, cell, column, startCol, colSpanIndex);
protected GridUnit(Table table, TableColumn column, int startCol, int colSpanIndex,
int rowSpanIndex) {
this(column, startCol, colSpanIndex, rowSpanIndex);
setBorders(table);
}

/**
* Creates a new grid unit.
*
* @param primary the before-start grid unit of the cell containing this grid unit
*
* @param cell table cell which occupies this grid unit
* @param column table column this grid unit belongs to
* @param startCol index of the column this grid unit belongs to
* @param colSpanIndex index of this grid unit in the span, in column direction
* @param rowSpanIndex index of this grid unit in the span, in row direction
*/
public GridUnit(PrimaryGridUnit primary, TableColumn column, int startCol, int colSpanIndex) {
this(primary, primary.getCell(), column, startCol, colSpanIndex);
protected GridUnit(TableCell cell, TableColumn column, int startCol, int colSpanIndex,
int rowSpanIndex) {
this(column, startCol, colSpanIndex, rowSpanIndex);
this.cell = cell;
setBorders(cell.getTable());
}

/**
* Creates a new grid unit.
*
*
* @param primary the before-start grid unit of the cell containing this grid unit
* @param cell table cell which occupies this grid unit
* @param column table column this grid unit belongs to
* @param startCol index of the column this grid unit belongs to
* @param colSpanIndex index of this grid unit in the span, in column direction
* @param rowSpanIndex index of this grid unit in the span, in row direction
*/
protected GridUnit(PrimaryGridUnit primary, TableCell cell, TableColumn column, int startCol, int colSpanIndex) {
public GridUnit(PrimaryGridUnit primary, TableColumn column, int startCol, int colSpanIndex,
int rowSpanIndex) {
this(primary.getCell(), column, startCol, colSpanIndex, rowSpanIndex);
this.primary = primary;
this.cell = cell;
}

private GridUnit(TableColumn column, int startCol, int colSpanIndex, int rowSpanIndex) {
this.column = column;
this.startCol = startCol;
this.colSpanIndex = colSpanIndex;
this.rowSpanIndex = rowSpanIndex;
}

private void setBorders(Table table/*TODO*/) {
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);
}
}
}

protected void setBorder(int side) {
resolvedBorders[side] = cell.resolvedBorders[side];
}

public TableCell getCell() {
@@ -128,7 +191,7 @@ public class GridUnit {
if (row != null) {
return row;
} else if (getCell().getParent() instanceof TableRow) {
return (TableRow)getCell().getParent();
return (TableRow) getCell().getParent();
} else {
return null;
}
@@ -136,6 +199,7 @@ public class GridUnit {

/**
* Sets the table-row FO, if applicable.
*
* @param row the table-row FO
*/
public void setRow(TableRow row) {
@@ -147,18 +211,7 @@ public class GridUnit {
while (node != null && !(node instanceof TableBody)) {
node = node.getParent();
}
return (TableBody)node;
}

public Table getTable() {
FONode node = getBody();
while (node != null && !(node instanceof Table)) {
node = node.getParent();
}
if (node == null && getColumn() != null) {
node = getColumn().getParent();
}
return (Table)node;
return (TableBody) node;
}

/**
@@ -167,7 +220,7 @@ public class GridUnit {
* @return the before-start grid unit of the cell containing this grid unit.
*/
public PrimaryGridUnit getPrimary() {
return (isPrimary() ? (PrimaryGridUnit)this : primary);
return primary;
}

/**
@@ -194,20 +247,12 @@ public class GridUnit {

/** @return true if the grid unit is the last in column spanning direction */
public boolean isLastGridUnitColSpan() {
if (cell != null) {
return (colSpanIndex == cell.getNumberColumnsSpanned() - 1);
} else {
return true;
}
return (colSpanIndex == cell.getNumberColumnsSpanned() - 1);
}

/** @return true if the grid unit is the last in row spanning direction */
public boolean isLastGridUnitRowSpan() {
if (cell != null) {
return (rowSpanIndex == cell.getNumberRowsSpanned() - 1);
} else {
return true;
}
return (rowSpanIndex == cell.getNumberRowsSpanned() - 1);
}

/**
@@ -225,9 +270,10 @@ public class GridUnit {
}

/**
* Returns a BorderInfo instance for a side of the currently applicable cell before border
* resolution (i.e. the value from the FO). A return value of null indicates an empty cell.
* See CollapsingBorderModel(EyeCatching) where this method is used.
* Returns a BorderInfo instance for a side of the currently applicable cell before
* border resolution (i.e. the value from the FO). A return value of null indicates an
* empty cell. See CollapsingBorderModel(EyeCatching) where this method is used.
*
* @param side for which side to return the BorderInfo
* @return the requested BorderInfo instance or null if the grid unit is an empty cell
*/
@@ -243,9 +289,33 @@ public class GridUnit {
* @return the resolved normal borders for this grid unit
*/
public CommonBorderPaddingBackground getBorders() {
// TODO
if (effectiveBorders == null) {
effectiveBorders = new CommonBorderPaddingBackground();
setBorderInfo(CommonBorderPaddingBackground.BEFORE);
setBorderInfo(CommonBorderPaddingBackground.AFTER);
setBorderInfo(CommonBorderPaddingBackground.START);
setBorderInfo(CommonBorderPaddingBackground.END);
if (cell != null) {
effectiveBorders.setPadding(cell.getCommonBorderPaddingBackground());
}
if (log.isDebugEnabled()) {
log.debug(this + " resolved borders: " + "before="
+ effectiveBorders.getBorderBeforeWidth(false) + ", " + "after="
+ effectiveBorders.getBorderAfterWidth(false) + ", " + "start="
+ effectiveBorders.getBorderStartWidth(false) + ", " + "end="
+ effectiveBorders.getBorderEndWidth(false));
}
}
return effectiveBorders;
}

private void setBorderInfo(int side) {
if (resolvedBorders[side] != null) {
effectiveBorders.setBorderInfo(resolvedBorders[side].getBorderInfo(), side);
}
}

/**
* @return true if the grid unit has any borders.
*/
@@ -254,8 +324,8 @@ public class GridUnit {
}

/**
* Assigns the borders from the given cell to this cell info. Used in
* case of separate border model.
* Assigns the borders from the given cell to this cell info. Used in case of separate
* border model.
*/
public void assignBorderForSeparateBorderModel() {
if (cell != null) {
@@ -264,42 +334,39 @@ public class GridUnit {
}

/**
* Resolve collapsing borders for the given cell. Used in case of the collapsing border model.
* @param other neighbouring grid unit if any
* @param side the side to resolve (one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
* Resolve collapsing borders for the given cell. Used in case of the collapsing
* border model.
*
* @param other neighbouring grid unit
* @param side the side to resolve (one of
* CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
*/
public void resolveBorder(GridUnit other, int side) {
resolveBorder(other, side, 0);
BorderSpecification resolvedBorder = collapsingBorderModel.determineWinner(
resolvedBorders[side], other.resolvedBorders[CollapsingBorderModel
.getOtherSide(side)]);
if (resolvedBorder != null) {
this.resolvedBorders[side] = resolvedBorder;
other.resolvedBorders[CollapsingBorderModel.getOtherSide(side)] = resolvedBorder;
}
}

/**
* Resolve collapsing borders for the given cell. Used in case of the collapsing border model.
* @param other neighbouring grid unit if any
* @param side the side to resolve (one of CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
* @param resFlags flags for the border resolution
* Resolves the border on the given side of this grid unit, comparing it against the
* same border of the given parent element.
*
* @param side the side to resolve (one of
* CommonBorderPaddingBackground.BEFORE|AFTER|START|END)
* @param parent the parent element holding a competing border
*/
public void resolveBorder(GridUnit other, int side, int resFlags) {
CollapsingBorderModel borderModel = CollapsingBorderModel.getBorderModelFor(
getTable().getBorderCollapse());
if (effectiveBorders == null) {
effectiveBorders = new CommonBorderPaddingBackground();
}
effectiveBorders.setBorderInfo(borderModel.determineWinner(this, other,
side, resFlags), side);
if (cell != null) {
effectiveBorders.setPadding(cell.getCommonBorderPaddingBackground());
}
if (log.isDebugEnabled()) {
log.debug(this + " resolved borders: "
+ "before=" + effectiveBorders.getBorderBeforeWidth(false) + ", "
+ "after=" + effectiveBorders.getBorderAfterWidth(false) + ", "
+ "start=" + effectiveBorders.getBorderStartWidth(false) + ", "
+ "end=" + effectiveBorders.getBorderEndWidth(false));
}
public void resolveBorder(int side, TableFObj parent) {
resolvedBorders[side] = collapsingBorderModel.determineWinner(resolvedBorders[side],
parent.resolvedBorders[side]);
}

/**
* Returns a flag for this GridUnit.
*
* @param which the requested flag
* @return the value of the flag
*/
@@ -309,29 +376,25 @@ public class GridUnit {

/**
* Sets a flag on a GridUnit.
*
* @param which the flag to set
* @param value the new value for the flag
*/
public void setFlag(int which, boolean value) {
if (value) {
flags |= (1 << which); //set flag
flags |= (1 << which); // set flag
} else {
flags &= ~(1 << which); //clear flag
flags &= ~(1 << which); // clear flag
}
}

/**
* @return the grid unit just below this grid unit if the cell is spanning.
* Sets the given flag on this grid unit.
*
* @param which the flag to set
*/
public GridUnit createNextRowSpanningGridUnit() {
if (isLastGridUnitRowSpan()) {
return null;
} else {
//cloning the current GridUnit with adjustments
GridUnit gu = new GridUnit(getPrimary(), getColumn(), startCol, colSpanIndex);
gu.rowSpanIndex = rowSpanIndex + 1;
return gu;
}
public void setFlag(int which) {
setFlag(which, true);
}

/** {@inheritDoc} */

+ 16
- 4
src/java/org/apache/fop/layoutmgr/table/PrimaryGridUnit.java Vedi File

@@ -55,18 +55,22 @@ public class PrimaryGridUnit extends GridUnit {
* @param startRow index of the row this grid unit belongs to, zero-based
*/
public PrimaryGridUnit(TableCell cell, TableColumn column, int startCol, int startRow) {
super(cell, column, startCol, 0);
super(cell, column, startCol, 0, 0);
this.startRow = startRow;
log.trace("PrimaryGridUnit created, row " + startRow + " col " + startCol);
if (cell != null) {
cellLM = new TableCellLayoutManager(cell, this);
}
}

public TableCellLayoutManager getCellLM() {
assert cellLM != null;
return cellLM;
}

/** {@inheritDoc} */
public PrimaryGridUnit getPrimary() {
return this;
}

/** {@inheritDoc} */
public boolean isPrimary() {
return true;
}
@@ -225,4 +229,12 @@ public class PrimaryGridUnit extends GridUnit {
|| (getCell().getNumberRowsSpanned() > 1);
}

/**
* Creates a cellLM for the corresponding table-cell. A new one must be created
* for each new static-content (TODO).
*/
public void createCellLM() {
cellLM = new TableCellLayoutManager(cell, this);
}

}

+ 1
- 105
src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java Vedi File

@@ -97,10 +97,6 @@ class RowGroupLayoutManager {

public LinkedList getNextKnuthElements(LayoutContext context, int alignment, int bodyType) {
LinkedList returnList = new LinkedList();
//Border resolution
if (!tableLM.getTable().isSeparateBorderModel()) {
resolveNormalBeforeAfterBordersForRowGroup();
}

//Reset keep-with-next when remaining inside the table.
//The context flag is only used to propagate keep-with-next to the outside.
@@ -133,107 +129,6 @@ class RowGroupLayoutManager {
return returnList;
}

/**
* Resolves normal borders for a row group.
* @param iter Table row iterator to operate on
*/
private void resolveNormalBeforeAfterBordersForRowGroup() {
for (int rgi = 0; rgi < rowGroup.length; rgi++) {
EffRow row = rowGroup[rgi];
EffRow prevRow = thisIter.getPrecedingRow(row);
EffRow nextRow = thisIter.getFollowingRow(row);
if ((prevRow == null) && (thisIter == bodyIter) && (headerIter != null)) {
prevRow = headerIter.getLastRow();
}
if ((nextRow == null) && (thisIter == headerIter)) {
nextRow = bodyIter.getFirstRow();
}
if ((nextRow == null) && (thisIter == bodyIter) && (footerIter != null)) {
nextRow = footerIter.getFirstRow();
}
if ((prevRow == null) && (thisIter == footerIter)) {
//TODO This could be bad for memory consumption because it already causes the
//whole body iterator to be prefetched!
prevRow = bodyIter.getLastRow();
}
log.debug("prevRow-row-nextRow: " + prevRow + " - " + row + " - " + nextRow);
//Determine the grid units necessary for getting all the borders right
int guCount = row.getGridUnits().size();
if (prevRow != null) {
guCount = Math.max(guCount, prevRow.getGridUnits().size());
}
if (nextRow != null) {
guCount = Math.max(guCount, nextRow.getGridUnits().size());
}
GridUnit gu = row.getGridUnit(0);
//Create empty grid units to hold resolved borders of neighbouring cells
//TODO maybe this needs to be done differently (and sooner)
for (int i = 0; i < guCount - row.getGridUnits().size(); i++) {
//TODO This block is untested!
int pos = row.getGridUnits().size() + i;
row.getGridUnits().add(new EmptyGridUnit(gu.getRow(),
tableLM.getColumns().getColumn(pos + 1), gu.getBody(),
pos));
}
//Now resolve normal borders
if (tableLM.getTable().isSeparateBorderModel()) {
//nop, borders are already assigned at this point
} else {
for (int i = 0; i < row.getGridUnits().size(); i++) {
gu = row.getGridUnit(i);
GridUnit other;
int flags = 0;
if (prevRow != null && i < prevRow.getGridUnits().size()) {
other = prevRow.getGridUnit(i);
} else {
other = null;
}
if (other == null
|| other.isEmpty()
|| gu.isEmpty()
|| gu.getPrimary() != other.getPrimary()) {
if ((thisIter == bodyIter)
&& gu.getFlag(GridUnit.FIRST_IN_TABLE)
&& (headerIter == null)) {
flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
}
if ((thisIter == headerIter)
&& gu.getFlag(GridUnit.FIRST_IN_TABLE)) {
flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
}
gu.resolveBorder(other,
CommonBorderPaddingBackground.BEFORE, flags);
}
flags = 0;
if (nextRow != null && i < nextRow.getGridUnits().size()) {
other = nextRow.getGridUnit(i);
} else {
other = null;
}
if (other == null
|| other.isEmpty()
|| gu.isEmpty()
|| gu.getPrimary() != other.getPrimary()) {
if ((thisIter == bodyIter)
&& gu.getFlag(GridUnit.LAST_IN_TABLE)
&& (footerIter == null)) {
flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
}
if ((thisIter == footerIter)
&& gu.getFlag(GridUnit.LAST_IN_TABLE)) {
flags |= CollapsingBorderModel.VERTICAL_START_END_OF_TABLE;
}
gu.resolveBorder(other,
CommonBorderPaddingBackground.AFTER, flags);
}
}
}
}
}

/**
* Creates Knuth elements for a row group (see TableRowIterator.getNextRowGroup()).
* @param context Active LayoutContext
@@ -271,6 +166,7 @@ class RowGroupLayoutManager {
PrimaryGridUnit primary = gu.getPrimary();
if (gu.isPrimary()) {
primary.createCellLM(); // TODO a new LM must be created for every new static-content
primary.getCellLM().setParent(tableLM);
//Determine the table-row if any

+ 52
- 61
src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java Vedi File

@@ -20,11 +20,14 @@
package org.apache.fop.layoutmgr.table;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FONode.FONodeIterator;
import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
@@ -98,6 +101,8 @@ public class TableRowIterator {
/** Iterator over a part's child elements (either table-rows or table-cells). */
private ListIterator tablePartChildIterator = null;

private Iterator rowGroupsIter;

/**
* Creates a new TableRowIterator.
* @param table the table to iterate over
@@ -110,19 +115,23 @@ public class TableRowIterator {
this.tablePart = tablePart;
switch(tablePart) {
case HEADER: {
List bodyList = new java.util.ArrayList();
bodyList.add(table.getTableHeader());
this.tablePartIterator = bodyList.listIterator();
rowGroupsIter = table.getTableHeader().getRowGroups().iterator();
break;
}
case FOOTER: {
List bodyList = new java.util.ArrayList();
bodyList.add(table.getTableFooter());
this.tablePartIterator = bodyList.listIterator();
rowGroupsIter = table.getTableFooter().getRowGroups().iterator();
break;
}
default: {
this.tablePartIterator = table.getChildNodes();
List rowGroupsList = new LinkedList();
// TODO this is ugly
for (FONodeIterator iter = table.getChildNodes(); iter.hasNext();) {
FONode node = iter.nextNode();
if (node instanceof TableBody) {
rowGroupsList.addAll(((TableBody) node).getRowGroups());
}
}
rowGroupsIter = rowGroupsList.iterator();
}
}
}
@@ -132,38 +141,19 @@ public class TableRowIterator {
* consecutive rows which contains all spanned grid units of its cells.
* @return the next row group, or null
*/
public EffRow[] getNextRowGroup() {
EffRow firstRowInGroup = getNextRow();
if (firstRowInGroup == null) {
EffRow[] getNextRowGroup() {
if (!rowGroupsIter.hasNext()) {
return null;
}
EffRow lastRowInGroup = firstRowInGroup;
int lastIndex = lastRowInGroup.getIndex();
boolean allFinished;
do {
allFinished = true;
Iterator iter = lastRowInGroup.getGridUnits().iterator();
while (iter.hasNext()) {
GridUnit gu = (GridUnit)iter.next();
if (!gu.isLastGridUnitRowSpan()) {
allFinished = false;
break;
}
}
lastIndex = lastRowInGroup.getIndex();
if (!allFinished) {
lastRowInGroup = getNextRow();
if (lastRowInGroup == null) {
allFinished = true;
}
}
} while (!allFinished);
int rowCount = lastIndex - firstRowInGroup.getIndex() + 1;
EffRow[] rowGroup = new EffRow[rowCount];
for (int i = 0; i < rowCount; i++) {
rowGroup[i] = getCachedRow(i + firstRowInGroup.getIndex());
List rowGroup = (List) rowGroupsIter.next();
EffRow[] effRowGroup = new EffRow[rowGroup.size()];
int i = 0;
for (Iterator rowIter = rowGroup.iterator(); rowIter.hasNext();) {
List gridUnits = (List) rowIter.next();
effRowGroup[i] = new EffRow(i, tablePart, gridUnits);
i++;
}
return rowGroup;
return effRowGroup;
}

/**
@@ -197,7 +187,7 @@ public class TableRowIterator {
* @return the preceding row, or null if there is no such row (the given row is the
* first one in the table part)
*/
public EffRow getPrecedingRow(EffRow row) {
EffRow getPrecedingRow(EffRow row) {
return getRow(row.getIndex() - 1);
}

@@ -207,7 +197,7 @@ public class TableRowIterator {
* @param row a row in the iterated table part
* @return the following row, or null if there is no more row
*/
public EffRow getFollowingRow(EffRow row) {
EffRow getFollowingRow(EffRow row) {
return getRow(row.getIndex() + 1);
}

@@ -215,7 +205,7 @@ public class TableRowIterator {
* Returns the first effective row.
* @return the requested effective row.
*/
public EffRow getFirstRow() {
EffRow getFirstRow() {
if (fetchedRows.size() == 0) {
prefetchNext();
}
@@ -228,7 +218,7 @@ public class TableRowIterator {
* if preloaded.</p>
* @return the requested effective row.
*/
public EffRow getLastRow() {
EffRow getLastRow() {
while (prefetchNext()) {
//nop
}
@@ -377,7 +367,7 @@ public class TableRowIterator {
* @return the list of grid units
*/
private EffRow buildGridRow(List cells, TableRow rowFO) {
EffRow row = new EffRow(this.fetchIndex, tablePart);
EffRow row = new EffRow(this.fetchIndex, tablePart, null);
List gridUnits = row.getGridUnits();

TableBody bodyFO = null;
@@ -393,7 +383,8 @@ public class TableRowIterator {
if (gu.getColSpanIndex() == 0) {
horzSpan = new GridUnit[gu.getCell().getNumberColumnsSpanned()];
}
GridUnit newGU = gu.createNextRowSpanningGridUnit();
// GridUnit newGU = gu.createNextRowSpanningGridUnit();
GridUnit newGU = null;
newGU.setRow(rowFO);
safelySetListItem(gridUnits, colnum - 1, newGU);
horzSpan[newGU.getColSpanIndex()] = newGU;
@@ -455,7 +446,7 @@ public class TableRowIterator {
horzSpan[0] = gu;
for (int j = 1; j < cell.getNumberColumnsSpanned(); j++) {
colnum++;
GridUnit guSpan = new GridUnit(gu, columns.getColumn(colnum), colnum - 1, j);
GridUnit guSpan = new GridUnit(gu, columns.getColumn(colnum), colnum - 1, j, 0);
//TODO: remove the check below???
other = (GridUnit)safelyGetListItem(gridUnits, colnum - 1);
if (other != null) {
@@ -486,29 +477,29 @@ public class TableRowIterator {
}

//Post-processing the list (looking for gaps and resolve start and end borders)
fillEmptyGridUnits(gridUnits, rowFO, bodyFO);
// fillEmptyGridUnits(gridUnits, rowFO, bodyFO);
resolveStartEndBorders(gridUnits);

return row;
}

private void fillEmptyGridUnits(List gridUnits, TableRow row, TableBody body) {
for (int pos = 1; pos <= gridUnits.size(); pos++) {
GridUnit gu = (GridUnit)gridUnits.get(pos - 1);
//Empty grid units
if (gu == null) {
//Add grid unit
gu = new EmptyGridUnit(row, columns.getColumn(pos), body,
pos - 1);
gridUnits.set(pos - 1, gu);
}
//Set flags
gu.setFlag(GridUnit.IN_FIRST_COLUMN, (pos == 1));
gu.setFlag(GridUnit.IN_LAST_COLUMN, (pos == gridUnits.size()));
}
}
// private void fillEmptyGridUnits(List gridUnits, TableRow row, TableBody body) {
// for (int pos = 1; pos <= gridUnits.size(); pos++) {
// GridUnit gu = (GridUnit)gridUnits.get(pos - 1);
//
// //Empty grid units
// if (gu == null) {
// //Add grid unit
// gu = new EmptyGridUnit(row, columns.getColumn(pos), body,
// pos - 1);
// gridUnits.set(pos - 1, gu);
// }
//
// //Set flags
// gu.setFlag(GridUnit.IN_FIRST_COLUMN, (pos == 1));
// gu.setFlag(GridUnit.IN_LAST_COLUMN, (pos == gridUnits.size()));
// }
// }

private void resolveStartEndBorders(List gridUnits) {
for (int pos = 1; pos <= gridUnits.size(); pos++) {

+ 15
- 0
status.xml Vedi File

@@ -28,6 +28,21 @@

<changes>
<release version="FOP Trunk">
<action context="Code" dev="VH" type="add">
Step towards performance: the collapsing-border resolution algorithm no longer triggers the
retrieving of the whole table, when possible.
</action>
<action context="Code" dev="VH" type="fix">
In case of missing cells the border-end of the table was applied to an inner cell, instead
of the (empty) cell in the last column.
</action>
<action context="Code" dev="VH" type="fix">
Fixed the resolution of borders with table-columns (border-before/after was wrongly applied
to every cell of the column).
</action>
<action context="Code" dev="VH" type="fix">
Fixed the resolution of border-end on cells spanning several rows.
</action>
<action context="Code" dev="JM" type="fix" fixes-bug="43835" due-to="David Churavy">
Bugfix: Use Font.getName() (logical font name) instead of Font.getFontName()
(localized) when registering fonts from AWT.

+ 448
- 0
test/layoutengine/standard-testcases/table_border-collapse_collapse_nrnc_no-col.xml Vedi File

@@ -0,0 +1,448 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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$ -->
<!--
NOTE: this test is a clone of table_border-collapse_collapse_nrnc.xml where all of the
fo:table-column elements have been removed.
-->
<testcase>
<info>
<p>
This test checks tables with collapse border model. It tries to be as exhaustive as possible
by making a lot of situations to occur: different border widths, styles, colors, none/hidden
border styles, big borders, computation of row height, etc.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="16cm" page-height="15cm" margin="20pt">
<fo:region-body margin="0pt"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal">
<fo:flow flow-name="xsl-region-body">
<fo:block>Before the tables</fo:block>

<!-- table 1 -->
<fo:table table-layout="fixed" width="200pt" border-collapse="collapse">
<fo:table-column column-width="proportional-column-width(1)"
number-columns-repeated="2"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell
border-top="12pt solid black"
border-bottom="12pt solid blue"
border-left="12pt solid red"
border-right="12pt solid orange">
<fo:block>Cell 1.1 Cell 1.1 Cell 1.1 Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top="4pt solid gray"
border-bottom="10pt solid navy"
border-left="4pt solid purple"
border-right="4pt solid yellow">
<fo:block>Cell 1.2</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top="6pt solid gray"
border-bottom="6pt solid navy"
border-left="6pt solid purple"
border-right="6pt solid yellow">
<fo:block>Cell 2.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top="10pt solid black"
border-bottom="10pt solid blue"
border-left="10pt solid red"
border-right="10pt solid orange">
<fo:block>Cell 2.2 Cell 2.2 Cell 2.2 Cell 2.2</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>

<fo:block>Between tables</fo:block>
<!-- table 2 -->
<fo:table table-layout="fixed" width="400pt" border-collapse="collapse">
<fo:table-body>
<!-- the height of this row is fixed by the 4th cell: only one row but big borders
which actually makes it higher than the 3rd cell -->
<fo:table-row>
<fo:table-cell
border-top ="4pt solid black"
border-bottom="4pt solid black"
border-left ="4pt solid black"
border-right ="4pt solid black">
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="6pt solid silver"
border-bottom="6pt solid silver"
border-left ="6pt solid silver"
border-right ="6pt solid silver">
<fo:block>Cell 1.2</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="5pt solid green"
border-bottom="5pt solid green"
border-left ="5pt solid green"
border-right ="5pt solid green">
<fo:block>Cell 1.3 Cell 1.3 Cell 1.3 Cell 1.3</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="15pt solid navy"
border-bottom="30pt solid navy"
border-left ="15pt solid navy"
border-right =" 5pt solid navy">
<fo:block>Cell 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top ="12pt solid maroon"
border-bottom=" 6pt double maroon"
border-left =" 6pt solid maroon"
border-right =" 6pt solid maroon">
<fo:block>Cell 2.1 Cell 2.1 Cell 2.1 Cell 2.1 Cell 2.1 Cell 2.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="4pt hidden red"
border-bottom="4pt dashed red"
border-left ="10pt dashed red"
border-right ="4pt double red">
<fo:block>Cell 2.2</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="6pt none maroon"
border-bottom="6pt dotted maroon"
border-left ="10pt solid maroon"
border-right ="6pt ridge maroon">
<fo:block>Cell 2.3</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="5pt solid purple"
border-bottom="5pt ridge purple"
border-left ="5pt dotted purple"
border-right ="5pt solid purple">
<fo:block>Cell 2.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top ="6pt double fuchsia"
border-bottom="6pt inset fuchsia"
border-left ="30pt solid fuchsia"
border-right ="6pt inset fuchsia">
<fo:block>Cell 3.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top =" 4pt dashed lime"
border-bottom=" 5pt outset lime"
border-left =" 5pt solid lime"
border-right ="10pt groove lime">
<fo:block>Cell 3.2 Cell 3.2 Cell 3.2 Cell 3.2 Cell 3.2 Cell 3.2</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="6pt dotted teal"
border-bottom="4pt solid teal"
border-left ="10pt dotted teal"
border-right ="4pt none teal">
<fo:block>Cell 3.3</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="5pt ridge maroon"
border-bottom="6pt solid maroon"
border-left ="10pt none maroon"
border-right ="6pt none maroon">
<fo:block>Cell 3.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top =" 6pt inset black"
border-bottom=" 4pt solid black"
border-left =" 4pt solid black"
border-right ="40pt solid black">
<fo:block>Cell 4.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top =" 5pt outset silver"
border-bottom="60pt solid silver"
border-left =" 6pt solid silver"
border-right =" 6pt none silver">
<fo:block>Cell 4.2 Cell 4.2</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="4pt double green"
border-bottom="5pt solid green"
border-left ="6pt solid green"
border-right ="5pt dashed green">
<fo:block>Cell 4.3 Cell 4.3 Cell 4.3 Cell 4.3</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="6pt dotted navy"
border-bottom="30pt solid navy"
border-left =" 5pt ridge navy"
border-right ="50pt solid navy">
<fo:block>Cell 4.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
<fo:block>After the tables</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<!-- table 1 -->
<eval expected="200000" xpath="//flow/block[2]/@ipd"/>
<eval expected="200000" xpath="//flow/block[2]/@ipda"/>
<eval expected="79600" xpath="//flow/block[2]/@bpd"/>
<eval expected="79600" xpath="//flow/block[2]/@bpda"/>
<!-- row 1 cell 1 -->
<eval expected="88000" xpath="//flow/block[2]/block[1]/@ipd"/>
<eval expected="112000" xpath="//flow/block[2]/block[1]/@ipda"/>
<eval expected="28800" xpath="//flow/block[2]/block[1]/@bpd"/>
<eval expected="52800" xpath="//flow/block[2]/block[1]/@bpda"/>
<eval expected="6000" xpath="//flow/block[2]/block[1]/@left-offset"/>
<eval expected="-6000" xpath="//flow/block[2]/block[1]/@top-offset"/>
<eval expected="(solid,#000000,12000,collapse-outer)" xpath="//flow/block[2]/block[1]/@border-before"/>
<eval expected="(solid,#0000ff,12000,collapse-inner)" xpath="//flow/block[2]/block[1]/@border-after"/>
<eval expected="(solid,#ff0000,12000,collapse-outer)" xpath="//flow/block[2]/block[1]/@border-start"/>
<eval expected="(solid,#ffa500,12000,collapse-inner)" xpath="//flow/block[2]/block[1]/@border-end"/>
<!-- row 1 cell 2 -->
<eval expected="92000" xpath="//flow/block[2]/block[2]/@ipd"/>
<eval expected="108000" xpath="//flow/block[2]/block[2]/@ipda"/>
<eval expected="33800" xpath="//flow/block[2]/block[2]/@bpd"/>
<eval expected="47800" xpath="//flow/block[2]/block[2]/@bpda"/>
<eval expected="106000" xpath="//flow/block[2]/block[2]/@left-offset"/>
<eval expected="-2000" xpath="//flow/block[2]/block[2]/@top-offset"/>
<eval expected="(solid,#808080,4000,collapse-outer)" xpath="//flow/block[2]/block[2]/@border-before"/>
<eval expected="(solid,#000080,10000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-after"/>
<eval expected="(solid,#ffa500,12000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-start"/>
<eval expected="(solid,#ffff00,4000,collapse-outer)" xpath="//flow/block[2]/block[2]/@border-end"/>
<!-- row 2 cell 1 -->
<eval expected="92000" xpath="//flow/block[2]/block[3]/@ipd"/>
<eval expected="108000" xpath="//flow/block[2]/block[3]/@ipda"/>
<eval expected="29800" xpath="//flow/block[2]/block[3]/@bpd"/>
<eval expected="47800" xpath="//flow/block[2]/block[3]/@bpda"/>
<eval expected="3000" xpath="//flow/block[2]/block[3]/@left-offset"/>
<eval expected="34800" xpath="//flow/block[2]/block[3]/@top-offset"/>
<eval expected="(solid,#0000ff,12000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-before"/>
<eval expected="(solid,#000080,6000,collapse-outer)" xpath="//flow/block[2]/block[3]/@border-after"/>
<eval expected="(solid,#800080,6000,collapse-outer)" xpath="//flow/block[2]/block[3]/@border-start"/>
<eval expected="(solid,#ff0000,10000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-end"/>
<!-- row 2 cell 2 -->
<eval expected="90000" xpath="//flow/block[2]/block[4]/@ipd"/>
<eval expected="110000" xpath="//flow/block[2]/block[4]/@ipda"/>
<eval expected="28800" xpath="//flow/block[2]/block[4]/@bpd"/>
<eval expected="48800" xpath="//flow/block[2]/block[4]/@bpda"/>
<eval expected="105000" xpath="//flow/block[2]/block[4]/@left-offset"/>
<eval expected="35800" xpath="//flow/block[2]/block[4]/@top-offset"/>
<eval expected="(solid,#000000,10000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-before"/>
<eval expected="(solid,#0000ff,10000,collapse-outer)" xpath="//flow/block[2]/block[4]/@border-after"/>
<eval expected="(solid,#ff0000,10000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-start"/>
<eval expected="(solid,#ffa500,10000,collapse-outer)" xpath="//flow/block[2]/block[4]/@border-end"/>

<!-- table 2 -->
<eval expected="400000" xpath="//flow/block[4]/@ipd"/>
<eval expected="400000" xpath="//flow/block[4]/@ipda"/>
<eval expected="198100" xpath="//flow/block[4]/@bpd"/>
<eval expected="198100" xpath="//flow/block[4]/@bpda"/>
<!-- row 1 cell 1 -->
<eval expected="95000" xpath="//flow/block[4]/block[1]/@ipd"/>
<eval expected="105000" xpath="//flow/block[4]/block[1]/@ipda"/>
<eval expected="28900" xpath="//flow/block[4]/block[1]/@bpd"/>
<eval expected="44900" xpath="//flow/block[4]/block[1]/@bpda"/>
<eval expected="2000" xpath="//flow/block[4]/block[1]/@left-offset"/>
<eval expected="-2000" xpath="//flow/block[4]/block[1]/@top-offset"/>
<eval expected="(solid,#000000,4000,collapse-outer)" xpath="//flow/block[4]/block[1]/@border-before"/>
<eval expected="(solid,#800000,12000,collapse-inner)" xpath="//flow/block[4]/block[1]/@border-after"/>
<eval expected="(solid,#000000,4000,collapse-outer)" xpath="//flow/block[4]/block[1]/@border-start"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[4]/block[1]/@border-end"/>
<!-- row 1 cell 2 -->
<eval expected="94000" xpath="//flow/block[4]/block[2]/@ipd"/>
<eval expected="106000" xpath="//flow/block[4]/block[2]/@ipda"/>
<eval expected="33900" xpath="//flow/block[4]/block[2]/@bpd"/>
<eval expected="39900" xpath="//flow/block[4]/block[2]/@bpda"/>
<eval expected="103000" xpath="//flow/block[4]/block[2]/@left-offset"/>
<eval expected="-3000" xpath="//flow/block[4]/block[2]/@top-offset"/>
<eval expected="(solid,#c0c0c0,6000,collapse-outer)" xpath="//flow/block[4]/block[2]/@border-before"/>
<eval expected="0" xpath="count(//flow/block[4]/block[2]/@border-after)"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-start"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-end"/>
<!-- row 1 cell 3 -->
<eval expected="89500" xpath="//flow/block[4]/block[3]/@ipd"/>
<eval expected="110500" xpath="//flow/block[4]/block[3]/@ipda"/>
<eval expected="31900" xpath="//flow/block[4]/block[3]/@bpd"/>
<eval expected="41900" xpath="//flow/block[4]/block[3]/@bpda"/>
<eval expected="203000" xpath="//flow/block[4]/block[3]/@left-offset"/>
<eval expected="-2500" xpath="//flow/block[4]/block[3]/@top-offset"/>
<eval expected="(solid,#008000,5000,collapse-outer)" xpath="//flow/block[4]/block[3]/@border-before"/>
<eval expected="(solid,#008000,5000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-after"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-start"/>
<eval expected="(solid,#000080,15000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-end"/>
<!-- row 1 cell 4 -->
<eval expected="90000" xpath="//flow/block[4]/block[4]/@ipd"/>
<eval expected="110000" xpath="//flow/block[4]/block[4]/@ipda"/>
<eval expected="14400" xpath="//flow/block[4]/block[4]/@bpd"/>
<eval expected="59400" xpath="//flow/block[4]/block[4]/@bpda"/>
<eval expected="307500" xpath="//flow/block[4]/block[4]/@left-offset"/>
<eval expected="-7500" xpath="//flow/block[4]/block[4]/@top-offset"/>
<eval expected="(solid,#000080,15000,collapse-outer)" xpath="//flow/block[4]/block[4]/@border-before"/>
<eval expected="(solid,#000080,30000,collapse-inner)" xpath="//flow/block[4]/block[4]/@border-after"/>
<eval expected="(solid,#000080,15000,collapse-inner)" xpath="//flow/block[4]/block[4]/@border-start"/>
<eval expected="(solid,#000080,5000,collapse-outer)" xpath="//flow/block[4]/block[4]/@border-end"/>
<!-- row 2 cell 1 -->
<eval expected="92000" xpath="//flow/block[4]/block[5]/@ipd"/>
<eval expected="108000" xpath="//flow/block[4]/block[5]/@ipda"/>
<eval expected="43200" xpath="//flow/block[4]/block[5]/@bpd"/>
<eval expected="61200" xpath="//flow/block[4]/block[5]/@bpda"/>
<eval expected="3000" xpath="//flow/block[4]/block[5]/@left-offset"/>
<eval expected="30900" xpath="//flow/block[4]/block[5]/@top-offset"/>
<eval expected="(solid,#800000,12000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-before"/>
<eval expected="(double,#800000,6000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-after"/>
<eval expected="(solid,#800000,6000,collapse-outer)" xpath="//flow/block[4]/block[5]/@border-start"/>
<eval expected="(dashed,#ff0000,10000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-end"/>
<!-- row 2 cell 2 -->
<eval expected="90000" xpath="//flow/block[4]/block[6]/@ipd"/>
<eval expected="110000" xpath="//flow/block[4]/block[6]/@ipda"/>
<eval expected="50200" xpath="//flow/block[4]/block[6]/@bpd"/>
<eval expected="54200" xpath="//flow/block[4]/block[6]/@bpda"/>
<eval expected="105000" xpath="//flow/block[4]/block[6]/@left-offset"/>
<eval expected="36900" xpath="//flow/block[4]/block[6]/@top-offset"/>
<eval expected="0" xpath="count(//flow/block[4]/block[6]/@border-before)"/>
<eval expected="(dashed,#ff0000,4000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-after"/>
<eval expected="(dashed,#ff0000,10000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-start"/>
<eval expected="(solid,#800000,10000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-end"/>
<!-- row 2 cell 3 -->
<eval expected="92000" xpath="//flow/block[4]/block[7]/@ipd"/>
<eval expected="108000" xpath="//flow/block[4]/block[7]/@ipda"/>
<eval expected="46700" xpath="//flow/block[4]/block[7]/@bpd"/>
<eval expected="57700" xpath="//flow/block[4]/block[7]/@bpda"/>
<eval expected="205000" xpath="//flow/block[4]/block[7]/@left-offset"/>
<eval expected="34400" xpath="//flow/block[4]/block[7]/@top-offset"/>
<eval expected="(solid,#008000,5000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-before"/>
<eval expected="(dotted,#800000,6000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-after"/>
<eval expected="(solid,#800000,10000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-start"/>
<eval expected="(ridge,#800000,6000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-end"/>
<!-- row 2 cell 4 -->
<eval expected="94500" xpath="//flow/block[4]/block[8]/@ipd"/>
<eval expected="105500" xpath="//flow/block[4]/block[8]/@ipda"/>
<eval expected="34700" xpath="//flow/block[4]/block[8]/@bpd"/>
<eval expected="69700" xpath="//flow/block[4]/block[8]/@bpda"/>
<eval expected="303000" xpath="//flow/block[4]/block[8]/@left-offset"/>
<eval expected="21900" xpath="//flow/block[4]/block[8]/@top-offset"/>
<eval expected="(solid,#000080,30000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-before"/>
<eval expected="(ridge,#800080,5000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-after"/>
<eval expected="(ridge,#800000,6000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-start"/>
<eval expected="(solid,#800080,5000,collapse-outer)" xpath="//flow/block[4]/block[8]/@border-end"/>
<!-- row 3 cell 1 -->
<eval expected="82000" xpath="//flow/block[4]/block[9]/@ipd"/>
<eval expected="118000" xpath="//flow/block[4]/block[9]/@ipda"/>
<eval expected="41700" xpath="//flow/block[4]/block[9]/@bpd"/>
<eval expected="53700" xpath="//flow/block[4]/block[9]/@bpda"/>
<eval expected="15000" xpath="//flow/block[4]/block[9]/@left-offset"/>
<eval expected="86100" xpath="//flow/block[4]/block[9]/@top-offset"/>
<eval expected="(double,#ff00ff,6000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-before"/>
<eval expected="(inset,#ff00ff,6000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-after"/>
<eval expected="(solid,#ff00ff,30000,collapse-outer)" xpath="//flow/block[4]/block[9]/@border-start"/>
<eval expected="(inset,#ff00ff,6000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-end"/>
<!-- row 3 cell 2 -->
<eval expected="92000" xpath="//flow/block[4]/block[10]/@ipd"/>
<eval expected="108000" xpath="//flow/block[4]/block[10]/@ipda"/>
<eval expected="43200" xpath="//flow/block[4]/block[10]/@bpd"/>
<eval expected="52200" xpath="//flow/block[4]/block[10]/@bpda"/>
<eval expected="103000" xpath="//flow/block[4]/block[10]/@left-offset"/>
<eval expected="87100" xpath="//flow/block[4]/block[10]/@top-offset"/>
<eval expected="(dashed,#00ff00,4000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-before"/>
<eval expected="(outset,#00ff00,5000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-after"/>
<eval expected="(inset,#ff00ff,6000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-start"/>
<eval expected="(dotted,#008080,10000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-end"/>
<!-- row 3 cell 3 -->
<eval expected="95000" xpath="//flow/block[4]/block[11]/@ipd"/>
<eval expected="105000" xpath="//flow/block[4]/block[11]/@ipda"/>
<eval expected="42700" xpath="//flow/block[4]/block[11]/@bpd"/>
<eval expected="52700" xpath="//flow/block[4]/block[11]/@bpda"/>
<eval expected="205000" xpath="//flow/block[4]/block[11]/@left-offset"/>
<eval expected="86100" xpath="//flow/block[4]/block[11]/@top-offset"/>
<eval expected="(dotted,#008080,6000,collapse-inner)" xpath="//flow/block[4]/block[11]/@border-before"/>
<eval expected="(double,#008000,4000,collapse-inner)" xpath="//flow/block[4]/block[11]/@border-after"/>
<eval expected="(dotted,#008080,10000,collapse-inner)" xpath="//flow/block[4]/block[11]/@border-start"/>
<eval expected="0" xpath="count(//flow/block[4]/block[11]/@border-end)"/>
<!-- row 3 cell 4 -->
<eval expected="100000" xpath="//flow/block[4]/block[12]/@ipd"/>
<eval expected="100000" xpath="//flow/block[4]/block[12]/@ipda"/>
<eval expected="42200" xpath="//flow/block[4]/block[12]/@bpd"/>
<eval expected="53200" xpath="//flow/block[4]/block[12]/@bpda"/>
<eval expected="300000" xpath="//flow/block[4]/block[12]/@left-offset"/>
<eval expected="86600" xpath="//flow/block[4]/block[12]/@top-offset"/>
<eval expected="(ridge,#800000,5000,collapse-inner)" xpath="//flow/block[4]/block[12]/@border-before"/>
<eval expected="(solid,#800000,6000,collapse-inner)" xpath="//flow/block[4]/block[12]/@border-after"/>
<eval expected="0" xpath="count(//flow/block[4]/block[12]/@border-start)"/>
<eval expected="0" xpath="count(//flow/block[4]/block[12]/@border-end)"/>
<!-- row 4 cell 1 -->
<eval expected="78000" xpath="//flow/block[4]/block[13]/@ipd"/>
<eval expected="122000" xpath="//flow/block[4]/block[13]/@ipda"/>
<eval expected="56300" xpath="//flow/block[4]/block[13]/@bpd"/>
<eval expected="66300" xpath="//flow/block[4]/block[13]/@bpda"/>
<eval expected="2000" xpath="//flow/block[4]/block[13]/@left-offset"/>
<eval expected="133800" xpath="//flow/block[4]/block[13]/@top-offset"/>
<eval expected="(inset,#000000,6000,collapse-inner)" xpath="//flow/block[4]/block[13]/@border-before"/>
<eval expected="(solid,#000000,4000,collapse-outer)" xpath="//flow/block[4]/block[13]/@border-after"/>
<eval expected="(solid,#000000,4000,collapse-outer)" xpath="//flow/block[4]/block[13]/@border-start"/>
<eval expected="(solid,#000000,40000,collapse-inner)" xpath="//flow/block[4]/block[13]/@border-end"/>
<!-- row 4 cell 2 -->
<eval expected="77000" xpath="//flow/block[4]/block[14]/@ipd"/>
<eval expected="123000" xpath="//flow/block[4]/block[14]/@ipda"/>
<eval expected="28800" xpath="//flow/block[4]/block[14]/@bpd"/>
<eval expected="93800" xpath="//flow/block[4]/block[14]/@bpda"/>
<eval expected="120000" xpath="//flow/block[4]/block[14]/@left-offset"/>
<eval expected="134300" xpath="//flow/block[4]/block[14]/@top-offset"/>
<eval expected="(outset,#c0c0c0,5000,collapse-inner)" xpath="//flow/block[4]/block[14]/@border-before"/>
<eval expected="(solid,#c0c0c0,60000,collapse-outer)" xpath="//flow/block[4]/block[14]/@border-after"/>
<eval expected="(solid,#000000,40000,collapse-inner)" xpath="//flow/block[4]/block[14]/@border-start"/>
<eval expected="(solid,#008000,6000,collapse-inner)" xpath="//flow/block[4]/block[14]/@border-end"/>
<!-- row 4 cell 3 -->
<eval expected="94500" xpath="//flow/block[4]/block[15]/@ipd"/>
<eval expected="105500" xpath="//flow/block[4]/block[15]/@ipda"/>
<eval expected="56800" xpath="//flow/block[4]/block[15]/@bpd"/>
<eval expected="65800" xpath="//flow/block[4]/block[15]/@bpda"/>
<eval expected="203000" xpath="//flow/block[4]/block[15]/@left-offset"/>
<eval expected="134800" xpath="//flow/block[4]/block[15]/@top-offset"/>
<eval expected="(double,#008000,4000,collapse-inner)" xpath="//flow/block[4]/block[15]/@border-before"/>
<eval expected="(solid,#008000,5000,collapse-outer)" xpath="//flow/block[4]/block[15]/@border-after"/>
<eval expected="(solid,#008000,6000,collapse-inner)" xpath="//flow/block[4]/block[15]/@border-start"/>
<eval expected="(dashed,#008000,5000,collapse-inner)" xpath="//flow/block[4]/block[15]/@border-end"/>
<!-- row 4 cell 4 -->
<eval expected="72500" xpath="//flow/block[4]/block[16]/@ipd"/>
<eval expected="127500" xpath="//flow/block[4]/block[16]/@ipda"/>
<eval expected="43300" xpath="//flow/block[4]/block[16]/@bpd"/>
<eval expected="79300" xpath="//flow/block[4]/block[16]/@bpda"/>
<eval expected="302500" xpath="//flow/block[4]/block[16]/@left-offset"/>
<eval expected="133800" xpath="//flow/block[4]/block[16]/@top-offset"/>
<eval expected="(solid,#800000,6000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-before"/>
<eval expected="(solid,#000080,30000,collapse-outer)" xpath="//flow/block[4]/block[16]/@border-after"/>
<eval expected="(dashed,#008000,5000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-start"/>
<eval expected="(solid,#000080,50000,collapse-outer)" xpath="//flow/block[4]/block[16]/@border-end"/>
</checks>
</testcase>

+ 337
- 0
test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution.xml Vedi File

@@ -0,0 +1,337 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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$ -->
<testcase>
<info>
<p>
This test checks tables with collapsing-border model. Resolution between table, table-body,
table-row, table-cell...
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="20cm" page-height="15cm" margin="20pt">
<fo:region-body margin="0pt"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal">
<fo:flow flow-name="xsl-region-body">
<fo:block>Before the tables</fo:block>

<!-- table 1 -->
<fo:table table-layout="fixed" width="400pt" border-collapse="collapse"
border="10pt solid black">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(1)"
border="6pt solid blue" border-before-width="12pt" border-after-width="14pt"/>
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-body border="4pt solid red" border-after-width="12pt">
<fo:table-row border="2pt solid green">
<fo:table-cell border="1pt solid yellow" border-start-width="12pt">
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 1.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-before-width="12pt">
<fo:block>Cell 1.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-end-width="12pt"
number-rows-spanned="2">
<fo:block>Cell 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="2pt solid green" border-start-width="12pt">
<fo:table-cell border="1pt solid yellow" number-rows-spanned="2">
<fo:block>Cell 2.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 2.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 2.3</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="2pt solid cyan">
<fo:table-cell border="1pt solid yellow" border-before-width="12pt">
<fo:block>Cell 3.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-after-width="14pt">
<fo:block>Cell 3.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 3.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>

<!-- table 2 -->
<fo:block space-before="10pt" space-after="10pt">Between tables</fo:block>
<fo:table table-layout="fixed" width="400pt" border-collapse="collapse"
border="10pt solid black">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(1)"
border="6pt solid blue" border-before-width="12pt" border-after-width="14pt"/>
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-header border="4pt solid magenta">
<fo:table-row border="2pt solid green">
<fo:table-cell border="1pt solid yellow">
<fo:block>Header 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Header 1.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Header 1.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid grey" border-after-width="10pt">
<fo:block>Header 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-footer border="4pt solid olive" border-after-width="12pt">
<fo:table-row border="2pt solid green">
<fo:table-cell border="1pt solid yellow">
<fo:block>Footer 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Footer 1.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Footer 1.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-after-width="14pt"
border-before-color="black" border-before-width="16pt">
<fo:block>Footer 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-footer>
<fo:table-body border="4pt solid red" border-after-width="12pt">
<fo:table-row border="2pt solid green">
<fo:table-cell border="1pt solid yellow" border-start-width="12pt">
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 1.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-before-width="12pt">
<fo:block>Cell 1.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-end-width="12pt"
number-rows-spanned="2">
<fo:block>Cell 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="2pt solid green" border-start-width="12pt">
<fo:table-cell border="1pt solid yellow" number-rows-spanned="2">
<fo:block>Cell 2.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 2.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 2.3</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="2pt solid cyan">
<fo:table-cell border="1pt solid yellow" border-before-width="12pt">
<fo:block>Cell 3.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-after-width="14pt">
<fo:block>Cell 3.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 3.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>

<fo:block>After the tables</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>

<!-- table 1 -->
<!-- cell 1.1 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[1]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[1]/@border-after"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[2]/block[1]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[1]/@border-end"/>
<!-- cell 1.2 -->
<eval expected="(solid,#0000ff,12000,collapse-outer)" xpath="//flow/block[2]/block[2]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-end"/>
<!-- cell 1.3 -->
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[2]/block[3]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-end"/>
<!-- cell 2.2 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-before"/>
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-end"/>
<!-- cell 2.3 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-end"/>
<!-- cell 1.4 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[6]/@border-before"/>
<eval expected="" xpath="//flow/block[2]/block[6]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[6]/@border-start"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[2]/block[6]/@border-end"/>
<eval expected="" xpath="//flow/block[2]/block[7]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[7]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[7]/@border-start"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[2]/block[7]/@border-end"/>
<!-- cell 2.1 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[9]/@border-before"/>
<eval expected="" xpath="//flow/block[2]/block[9]/@border-after"/>
<eval expected="(solid,#008000,12000,collapse-outer)" xpath="//flow/block[2]/block[9]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[9]/@border-end"/>
<eval expected="" xpath="//flow/block[2]/block[10]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-outer)" xpath="//flow/block[2]/block[10]/@border-after"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[10]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[10]/@border-end"/>
<!-- cell 3.2 -->
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-before"/>
<eval expected="(solid,#0000ff,14000,collapse-outer)" xpath="//flow/block[2]/block[12]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-end"/>
<!-- cell 3.3 -->
<eval expected="(solid,#00ffff,2000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-before"/>
<eval expected="(solid,#ffff00,14000,collapse-outer)" xpath="//flow/block[2]/block[13]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-end"/>
<!-- cell 3.4 -->
<eval expected="(solid,#00ffff,2000,collapse-inner)" xpath="//flow/block[2]/block[14]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-outer)" xpath="//flow/block[2]/block[14]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[14]/@border-start"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[14]/@border-end"/>

<!-- table 2 -->
<!-- header 1.1 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[1]/@border-before"/>
<eval expected="(solid,#ff00ff,4000,collapse-inner)" xpath="//flow/block[4]/block[1]/@border-after"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[1]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[1]/@border-end"/>
<!-- header 1.2 -->
<eval expected="(solid,#0000ff,12000,collapse-outer)" xpath="//flow/block[4]/block[2]/@border-before"/>
<eval expected="(solid,#ff00ff,4000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-end"/>
<!-- header 1.3 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[3]/@border-before"/>
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-end"/>
<!-- header 1.4 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[4]/@border-before"/>
<eval expected="(solid,#808080,10000,collapse-inner)" xpath="//flow/block[4]/block[4]/@border-after"/>
<eval expected="(solid,#808080,1000,collapse-inner)" xpath="//flow/block[4]/block[4]/@border-start"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[4]/@border-end"/>
<!-- cell 1.1 -->
<eval expected="(solid,#ff0000,4000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-after"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[4]/block[5]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-end"/>
<!-- cell 1.2 -->
<eval expected="(solid,#ff0000,4000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-end"/>
<!-- cell 1.3 -->
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-end"/>
<!-- cell 2.2 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-before"/>
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-end"/>
<!-- cell 2.3 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-end"/>
<!-- cell 1.4 -->
<eval expected="(solid,#808080,10000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-before"/>
<eval expected="" xpath="//flow/block[4]/block[10]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-start"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[4]/block[10]/@border-end"/>
<eval expected="" xpath="//flow/block[4]/block[11]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[11]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[11]/@border-start"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[4]/block[11]/@border-end"/>
<!-- cell 2.1 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[13]/@border-before"/>
<eval expected="" xpath="//flow/block[4]/block[13]/@border-after"/>
<eval expected="(solid,#008000,12000,collapse-outer)" xpath="//flow/block[4]/block[13]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[13]/@border-end"/>
<eval expected="" xpath="//flow/block[4]/block[14]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-inner)" xpath="//flow/block[4]/block[14]/@border-after"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[14]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[14]/@border-end"/>
<!-- cell 3.2 -->
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-end"/>
<!-- cell 3.3 -->
<eval expected="(solid,#00ffff,2000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-before"/>
<eval expected="(solid,#ffff00,14000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-end"/>
<!-- cell 3.4 -->
<eval expected="(solid,#00ffff,2000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-before"/>
<eval expected="(solid,#000000,16000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-start"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[18]/@border-end"/>
<!-- footer 1.1 -->
<eval expected="(solid,#ff0000,12000,collapse-inner)" xpath="//flow/block[4]/block[19]/@border-before"/>
<eval expected="(solid,#808000,12000,collapse-outer)" xpath="//flow/block[4]/block[19]/@border-after"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[19]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[19]/@border-end"/>
<!-- footer 1.2 -->
<eval expected="(solid,#ff0000,12000,collapse-inner)" xpath="//flow/block[4]/block[20]/@border-before"/>
<eval expected="(solid,#0000ff,14000,collapse-outer)" xpath="//flow/block[4]/block[20]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[20]/@border-start"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[20]/@border-end"/>
<!-- footer 1.3 -->
<eval expected="(solid,#ffff00,14000,collapse-inner)" xpath="//flow/block[4]/block[21]/@border-before"/>
<eval expected="(solid,#808000,12000,collapse-outer)" xpath="//flow/block[4]/block[21]/@border-after"/>
<eval expected="(solid,#0000ff,6000,collapse-inner)" xpath="//flow/block[4]/block[21]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[21]/@border-end"/>
<!-- footer 1.4 -->
<eval expected="(solid,#000000,16000,collapse-inner)" xpath="//flow/block[4]/block[22]/@border-before"/>
<eval expected="(solid,#ffff00,14000,collapse-outer)" xpath="//flow/block[4]/block[22]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[22]/@border-start"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[22]/@border-end"/>

</checks>
</testcase>

+ 333
- 0
test/layoutengine/standard-testcases/table_border-collapse_collapse_resolution_no-col.xml Vedi File

@@ -0,0 +1,333 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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$ -->

<!--
NOTE: this test is a copy of table_border-collapse_collapse_resolution.xml, with all of the
fo:table-column elements removed. The checks for the borders in the second column of the first
table have been changed accordingly (no more column which plays in the resolution).
-->
<testcase>
<info>
<p>
This test checks tables with collapsing-border model. Resolution between table, table-body,
table-row, table-cell...
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="20cm" page-height="15cm" margin="20pt">
<fo:region-body margin="0pt"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal">
<fo:flow flow-name="xsl-region-body">
<fo:block>Before the tables</fo:block>

<!-- table 1 -->
<fo:table table-layout="fixed" width="400pt" border-collapse="collapse"
border="10pt solid black">
<fo:table-body border="4pt solid red" border-after-width="12pt">
<fo:table-row border="2pt solid green">
<fo:table-cell border="1pt solid yellow" border-start-width="12pt">
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 1.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-before-width="12pt">
<fo:block>Cell 1.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-end-width="12pt"
number-rows-spanned="2">
<fo:block>Cell 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="2pt solid green" border-start-width="12pt">
<fo:table-cell border="1pt solid yellow" number-rows-spanned="2">
<fo:block>Cell 2.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 2.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 2.3</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="2pt solid cyan">
<fo:table-cell border="1pt solid yellow" border-before-width="12pt">
<fo:block>Cell 3.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-after-width="14pt">
<fo:block>Cell 3.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 3.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>

<!-- table 2 -->
<fo:block space-before="10pt" space-after="10pt">Between tables</fo:block>
<fo:table table-layout="fixed" width="400pt" border-collapse="collapse"
border="10pt solid black">
<fo:table-header border="4pt solid magenta">
<fo:table-row border="2pt solid green">
<fo:table-cell border="1pt solid yellow">
<fo:block>Header 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Header 1.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Header 1.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid grey" border-after-width="10pt">
<fo:block>Header 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-footer border="4pt solid olive" border-after-width="12pt">
<fo:table-row border="2pt solid green">
<fo:table-cell border="1pt solid yellow">
<fo:block>Footer 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Footer 1.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Footer 1.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-after-width="14pt"
border-before-color="black" border-before-width="16pt">
<fo:block>Footer 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-footer>
<fo:table-body border="4pt solid red" border-after-width="12pt">
<fo:table-row border="2pt solid green">
<fo:table-cell border="1pt solid yellow" border-start-width="12pt">
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 1.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-before-width="12pt">
<fo:block>Cell 1.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-end-width="12pt"
number-rows-spanned="2">
<fo:block>Cell 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="2pt solid green" border-start-width="12pt">
<fo:table-cell border="1pt solid yellow" number-rows-spanned="2">
<fo:block>Cell 2.1</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 2.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 2.3</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row border="2pt solid cyan">
<fo:table-cell border="1pt solid yellow" border-before-width="12pt">
<fo:block>Cell 3.2</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow" border-after-width="14pt">
<fo:block>Cell 3.3</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid yellow">
<fo:block>Cell 3.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>

<fo:block>After the tables</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>

<!-- table 1 -->
<!-- cell 1.1 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[1]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[1]/@border-after"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[2]/block[1]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[1]/@border-end"/>
<!-- cell 1.2 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[2]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-end"/>
<!-- cell 1.3 -->
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[2]/block[3]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-end"/>
<!-- cell 2.2 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-before"/>
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-end"/>
<!-- cell 2.3 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-end"/>
<!-- cell 1.4 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[6]/@border-before"/>
<eval expected="" xpath="//flow/block[2]/block[6]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[6]/@border-start"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[2]/block[6]/@border-end"/>
<eval expected="" xpath="//flow/block[2]/block[7]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[7]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[7]/@border-start"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[2]/block[7]/@border-end"/>
<!-- cell 2.1 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[2]/block[9]/@border-before"/>
<eval expected="" xpath="//flow/block[2]/block[9]/@border-after"/>
<eval expected="(solid,#008000,12000,collapse-outer)" xpath="//flow/block[2]/block[9]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[9]/@border-end"/>
<eval expected="" xpath="//flow/block[2]/block[10]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-outer)" xpath="//flow/block[2]/block[10]/@border-after"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[10]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[10]/@border-end"/>
<!-- cell 3.2 -->
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-outer)" xpath="//flow/block[2]/block[12]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-end"/>
<!-- cell 3.3 -->
<eval expected="(solid,#00ffff,2000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-before"/>
<eval expected="(solid,#ffff00,14000,collapse-outer)" xpath="//flow/block[2]/block[13]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-end"/>
<!-- cell 3.4 -->
<eval expected="(solid,#00ffff,2000,collapse-inner)" xpath="//flow/block[2]/block[14]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-outer)" xpath="//flow/block[2]/block[14]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[2]/block[14]/@border-start"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[2]/block[14]/@border-end"/>

<!-- table 2 -->
<!-- header 1.1 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[1]/@border-before"/>
<eval expected="(solid,#ff00ff,4000,collapse-inner)" xpath="//flow/block[4]/block[1]/@border-after"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[1]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[1]/@border-end"/>
<!-- header 1.2 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[2]/@border-before"/>
<eval expected="(solid,#ff00ff,4000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-end"/>
<!-- header 1.3 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[3]/@border-before"/>
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-end"/>
<!-- header 1.4 -->
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[4]/@border-before"/>
<eval expected="(solid,#808080,10000,collapse-inner)" xpath="//flow/block[4]/block[4]/@border-after"/>
<eval expected="(solid,#808080,1000,collapse-inner)" xpath="//flow/block[4]/block[4]/@border-start"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[4]/@border-end"/>
<!-- cell 1.1 -->
<eval expected="(solid,#ff0000,4000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-after"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[4]/block[5]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-end"/>
<!-- cell 1.2 -->
<eval expected="(solid,#ff0000,4000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-end"/>
<!-- cell 1.3 -->
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-end"/>
<!-- cell 2.2 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-before"/>
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-end"/>
<!-- cell 2.3 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-end"/>
<!-- cell 1.4 -->
<eval expected="(solid,#808080,10000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-before"/>
<eval expected="" xpath="//flow/block[4]/block[10]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-start"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[4]/block[10]/@border-end"/>
<eval expected="" xpath="//flow/block[4]/block[11]/@border-before"/>
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[11]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[11]/@border-start"/>
<eval expected="(solid,#ffff00,12000,collapse-outer)" xpath="//flow/block[4]/block[11]/@border-end"/>
<!-- cell 2.1 -->
<eval expected="(solid,#008000,2000,collapse-inner)" xpath="//flow/block[4]/block[13]/@border-before"/>
<eval expected="" xpath="//flow/block[4]/block[13]/@border-after"/>
<eval expected="(solid,#008000,12000,collapse-outer)" xpath="//flow/block[4]/block[13]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[13]/@border-end"/>
<eval expected="" xpath="//flow/block[4]/block[14]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-inner)" xpath="//flow/block[4]/block[14]/@border-after"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[14]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[14]/@border-end"/>
<!-- cell 3.2 -->
<eval expected="(solid,#ffff00,12000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-before"/>
<eval expected="(solid,#ff0000,12000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[16]/@border-end"/>
<!-- cell 3.3 -->
<eval expected="(solid,#00ffff,2000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-before"/>
<eval expected="(solid,#ffff00,14000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-end"/>
<!-- cell 3.4 -->
<eval expected="(solid,#00ffff,2000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-before"/>
<eval expected="(solid,#000000,16000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-start"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[18]/@border-end"/>
<!-- footer 1.1 -->
<eval expected="(solid,#ff0000,12000,collapse-inner)" xpath="//flow/block[4]/block[19]/@border-before"/>
<eval expected="(solid,#808000,12000,collapse-outer)" xpath="//flow/block[4]/block[19]/@border-after"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[19]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[19]/@border-end"/>
<!-- footer 1.2 -->
<eval expected="(solid,#ff0000,12000,collapse-inner)" xpath="//flow/block[4]/block[20]/@border-before"/>
<eval expected="(solid,#808000,12000,collapse-outer)" xpath="//flow/block[4]/block[20]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[20]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[20]/@border-end"/>
<!-- footer 1.3 -->
<eval expected="(solid,#ffff00,14000,collapse-inner)" xpath="//flow/block[4]/block[21]/@border-before"/>
<eval expected="(solid,#808000,12000,collapse-outer)" xpath="//flow/block[4]/block[21]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[21]/@border-start"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[21]/@border-end"/>
<!-- footer 1.4 -->
<eval expected="(solid,#000000,16000,collapse-inner)" xpath="//flow/block[4]/block[22]/@border-before"/>
<eval expected="(solid,#ffff00,14000,collapse-outer)" xpath="//flow/block[4]/block[22]/@border-after"/>
<eval expected="(solid,#ffff00,1000,collapse-inner)" xpath="//flow/block[4]/block[22]/@border-start"/>
<eval expected="(solid,#000000,10000,collapse-outer)" xpath="//flow/block[4]/block[22]/@border-end"/>

</checks>
</testcase>

+ 0
- 10
test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_2.xml Vedi File

@@ -329,10 +329,8 @@
<eval expected="63500" xpath="//flow/block[2]/block[7]/@bpda"/>
<eval expected="307500" xpath="//flow/block[2]/block[7]/@left-offset"/>
<eval expected="7500" xpath="//flow/block[2]/block[7]/@top-offset"/>
<!--
<eval expected="80000" xpath="//flow/block[2]/block[8]/@ipd"/>
<eval expected="120000" xpath="//flow/block[2]/block[8]/@ipda"/>
-->
<eval expected="43400" xpath="//flow/block[2]/block[8]/@bpd"/>
<eval expected="55400" xpath="//flow/block[2]/block[8]/@bpda"/>
<eval expected="15000" xpath="//flow/block[2]/block[8]/@left-offset"/>
@@ -340,9 +338,7 @@
<eval expected="(double,#ff00ff,6000,collapse-inner)" xpath="//flow/block[2]/block[8]/@border-before"/>
<eval expected="(inset,#ff00ff,6000,collapse-inner)" xpath="//flow/block[2]/block[8]/@border-after"/>
<eval expected="(solid,#ff00ff,30000,collapse-outer)" xpath="//flow/block[2]/block[8]/@border-start"/>
<!--
<eval expected="(dashed,#ff0000,10000,collapse-inner)" xpath="//flow/block[2]/block[8]/@border-end"/>
-->
<eval expected="95000" xpath="//flow/block[2]/block[9]/@ipd"/>
<eval expected="105000" xpath="//flow/block[2]/block[9]/@ipda"/>
<eval expected="52200" xpath="//flow/block[2]/block[9]/@bpd"/>
@@ -350,18 +346,14 @@
<eval expected="105000" xpath="//flow/block[2]/block[9]/@left-offset"/>
<eval expected="33800" xpath="//flow/block[2]/block[9]/@top-offset"/>
<eval expected="(dashed,#ff0000,10000,collapse-inner)" xpath="//flow/block[2]/block[9]/@border-start"/>
<!--
<eval expected="92500" xpath="//flow/block[2]/block[10]/@ipd"/>
<eval expected="107500" xpath="//flow/block[2]/block[10]/@ipda"/>
-->
<eval expected="49700" xpath="//flow/block[2]/block[10]/@bpd"/>
<eval expected="54700" xpath="//flow/block[2]/block[10]/@bpda"/>
<eval expected="200000" xpath="//flow/block[2]/block[10]/@left-offset"/>
<eval expected="31300" xpath="//flow/block[2]/block[10]/@top-offset"/>
<eval expected="(solid,#008000,5000,collapse-inner)" xpath="//flow/block[2]/block[10]/@border-before"/>
<!--
<eval expected="(solid,#000080,15000,collapse-inner)" xpath="//flow/block[2]/block[10]/@border-end"/>
-->
<eval expected="95000" xpath="//flow/block[2]/block[11]/@ipd"/>
<eval expected="105000" xpath="//flow/block[2]/block[11]/@ipda"/>
<eval expected="46900" xpath="//flow/block[2]/block[11]/@bpd"/>
@@ -378,10 +370,8 @@
<eval expected="86000" xpath="//flow/block[2]/block[12]/@top-offset"/>
<eval expected="(double,#008000,40000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-after"/>
<eval expected="(double,#ff0000,4000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-end"/>
<!--
<eval expected="187500" xpath="//flow/block[2]/block[13]/@ipd"/>
<eval expected="187500" xpath="//flow/block[2]/block[13]/@ipda"/>
-->
<eval expected="79100" xpath="//flow/block[2]/block[13]/@bpd"/>
<eval expected="79100" xpath="//flow/block[2]/block[13]/@bpda"/>
<eval expected="105000" xpath="//flow/block[2]/block[13]/@left-offset"/>

+ 639
- 0
test/layoutengine/standard-testcases/table_border-collapse_collapse_spans_2_no-col.xml Vedi File

@@ -0,0 +1,639 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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$ -->
<!--
NOTE: this test is a copy of table_border-collapse_collapse_spans_2.xml, slightly adapted to test
that the number of columns is correctly updated as we progress in the table.

TODO: empty cells are currently not painted. The test passes because there are no checks for empty
cells but they will eventually have to be added.
-->
<testcase>
<info>
<p>
This test checks tables with collapsing-border model and complex spanning cells.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="16cm" page-height="30cm" margin="20pt">
<fo:region-body margin="0pt"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal">
<fo:flow flow-name="xsl-region-body">

<fo:block>Before tables</fo:block>
<!-- table 1 -->
<fo:table table-layout="fixed" width="400pt" border-collapse="collapse">
<fo:table-body>
<fo:table-row>
<fo:table-cell
border-top ="4pt solid black"
border-bottom="4pt solid black"
border-left ="4pt solid black"
border-right ="4pt solid black">
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="6pt solid silver"
border-bottom="6pt hidden silver"
border-left ="6pt solid silver"
border-right ="6pt solid silver">
<fo:block>Cell 1.2</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top ="12pt solid maroon"
border-bottom=" 6pt double maroon"
border-left =" 6pt solid maroon"
border-right =" 6pt solid maroon">
<fo:block>Cell 2.1 Cell 2.1 Cell 2.1 Cell 2.1 Cell 2.1 Cell 2.1</fo:block>
</fo:table-cell>
<fo:table-cell number-rows-spanned="2" number-columns-spanned="2"
background-color="yellow"
border-top ="4pt solid red"
border-bottom="4pt dashed red"
border-left ="10pt dashed red"
border-right ="4pt double red">
<fo:block>Cell 2.2</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top ="6pt double fuchsia"
border-bottom="6pt inset fuchsia"
border-left ="30pt solid fuchsia"
border-right ="6pt inset fuchsia">
<fo:block>Cell 3.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="5pt ridge maroon"
border-bottom="6pt solid maroon"
border-left ="10pt none maroon"
border-right ="6pt none maroon">
<fo:block>Cell 3.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top =" 6pt inset black"
border-bottom=" 4pt solid black"
border-left =" 4pt solid black"
border-right ="40pt solid black">
<fo:block>Cell 4.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top =" 5pt outset silver"
border-bottom="60pt solid silver"
border-left =" 6pt solid silver"
border-right =" 6pt none silver">
<fo:block>Cell 4.2 Cell 4.2</fo:block>
</fo:table-cell>
<fo:table-cell number-rows-spanned="3" number-columns-spanned="2"
background-color="yellow"
border-top ="40pt double green"
border-bottom="5pt solid green"
border-left ="6pt solid green"
border-right ="5pt dashed green">
<fo:block>Cell 4.3 Cell 4.3 Cell 4.3 Cell 4.3 Cell 4.3 Cell 4.3</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top ="4pt solid black"
border-bottom="4pt solid black"
border-left ="4pt solid black"
border-right ="4pt solid black">
<fo:block>Cell 5.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top ="6pt solid silver"
border-bottom="6pt hidden silver"
border-left ="6pt solid silver"
border-right ="60pt solid silver">
<fo:block>Cell 5.2</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top ="12pt solid maroon"
border-bottom=" 6pt double maroon"
border-left =" 6pt solid maroon"
border-right =" 6pt solid maroon">
<fo:block>Cell 6.1 Cell 6.1 Cell 6.1 Cell 6.1 Cell 6.1 Cell 6.1</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>

<fo:block space-before="10pt" space-after="10pt">Between tables</fo:block>
<!-- table 2 -->
<fo:table table-layout="fixed" width="400pt" border-collapse="collapse">
<fo:table-column number-columns-repeated="4" column-width="proportional-column-width(1)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell
border-top="12pt solid black"
border-bottom="12pt solid blue"
border-left="12pt solid red"
border-right="4pt solid teal">
<fo:block>Cell 1.1</fo:block>
</fo:table-cell>
<fo:table-cell
padding="10pt"
border-top="4pt solid silver"
border-bottom="5pt solid purple"
border-left="5pt solid purple"
border-right="10pt solid olive">
<fo:block>Cell 1.2 Cell 1.2</fo:block>
</fo:table-cell>
<fo:table-cell
border-top="6pt solid black"
border-bottom="6pt solid navy"
border-left="6pt solid purple"
border-right="16pt solid red">
<fo:block>Cell 1.3</fo:block>
</fo:table-cell>
<fo:table-cell
border-top="0pt solid black"
border-bottom="10pt solid blue"
border-left="12pt solid red"
border-right="4pt solid teal">
<fo:block>Cell 1.4</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top="10pt solid black"
border-bottom="4pt solid blue"
border-left="12pt solid purple"
border-right="4pt solid teal">
<fo:block>Cell 2.1</fo:block>
</fo:table-cell>
<fo:table-cell number-rows-spanned="3" number-columns-spanned="3"
background-color="yellow"
padding="15pt"
border-top="4pt solid silver"
border-bottom="12pt solid navy"
border-left="2pt solid purple"
border-right="4pt solid olive">
<fo:block>Cell 2.2</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top="3pt solid black"
border-bottom="10pt solid silver"
border-left="3pt solid red"
border-right="10pt solid teal">
<fo:block>Cell 3.1 Cell 3.1 Cell 3.1 Cell 3.1</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top="6pt solid silver"
border-bottom="6pt solid navy"
border-left="6pt solid purple"
border-right="16pt solid olive">
<fo:block>Cell 4.1</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
border-top="12pt solid black"
border-bottom="12pt solid blue"
border-left="12pt solid red"
border-right="12pt solid teal">
<fo:block>Cell 5.1</fo:block>
</fo:table-cell>
<fo:table-cell
border-top="4pt solid silver"
border-bottom="4pt solid purple"
border-left="4pt solid purple"
border-right="10pt solid olive">
<fo:block>Cell 5.2 Cell 5.2</fo:block>
</fo:table-cell>
<fo:table-cell
border-top="30pt solid silver"
border-bottom="6pt solid navy"
border-left="6pt solid purple"
border-right="16pt solid olive">
<fo:block>Cell 5.3</fo:block>
</fo:table-cell>
<fo:table-cell
padding="20pt"
border-top="10pt solid black"
border-bottom="4pt solid blue"
border-left="12pt solid red"
border-right="4pt solid teal">
<fo:block>Cell 5.4</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>

<fo:block>After the tables</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>

<!-- table 1 -->
<eval expected="269400" xpath="//flow/block[2]/@bpd"/>
<eval expected="269400" xpath="//flow/block[2]/@bpda"/>
<eval expected="95000" xpath="//flow/block[2]/block[1]/@ipd"/>
<eval expected="105000" xpath="//flow/block[2]/block[1]/@ipda"/>
<eval expected="14400" xpath="//flow/block[2]/block[1]/@bpd"/>
<eval expected="30400" xpath="//flow/block[2]/block[1]/@bpda"/>
<eval expected="2000" xpath="//flow/block[2]/block[1]/@left-offset"/>
<eval expected="-2000" xpath="//flow/block[2]/block[1]/@top-offset"/>
<eval expected="(solid,#000000,4000,collapse-outer)" xpath="//flow/block[2]/block[1]/@border-before"/>
<eval expected="(solid,#800000,12000,collapse-inner)" xpath="//flow/block[2]/block[1]/@border-after"/>
<eval expected="(solid,#000000,4000,collapse-outer)" xpath="//flow/block[2]/block[1]/@border-start"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[2]/block[1]/@border-end"/>
<eval expected="94000" xpath="//flow/block[2]/block[2]/@ipd"/>
<eval expected="106000" xpath="//flow/block[2]/block[2]/@ipda"/>
<eval expected="19400" xpath="//flow/block[2]/block[2]/@bpd"/>
<eval expected="25400" xpath="//flow/block[2]/block[2]/@bpda"/>
<eval expected="103000" xpath="//flow/block[2]/block[2]/@left-offset"/>
<eval expected="-3000" xpath="//flow/block[2]/block[2]/@top-offset"/>
<eval expected="(solid,#c0c0c0,6000,collapse-outer)" xpath="//flow/block[2]/block[2]/@border-before"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-start"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[2]/block[2]/@border-end"/>
<eval expected="92000" xpath="//flow/block[2]/block[3]/@ipd"/>
<eval expected="108000" xpath="//flow/block[2]/block[3]/@ipda"/>
<eval expected="43200" xpath="//flow/block[2]/block[3]/@bpd"/>
<eval expected="61200" xpath="//flow/block[2]/block[3]/@bpda"/>
<eval expected="3000" xpath="//flow/block[2]/block[3]/@left-offset"/>
<eval expected="16400" xpath="//flow/block[2]/block[3]/@top-offset"/>
<eval expected="(solid,#800000,12000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-before"/>
<eval expected="(double,#800000,6000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-after"/>
<eval expected="(solid,#800000,6000,collapse-outer)" xpath="//flow/block[2]/block[3]/@border-start"/>
<eval expected="(dashed,#ff0000,10000,collapse-inner)" xpath="//flow/block[2]/block[3]/@border-end"/>
<eval expected="80000" xpath="//flow/block[2]/block[4]/@ipd"/>
<eval expected="120000" xpath="//flow/block[2]/block[4]/@ipda"/>
<eval expected="30900" xpath="//flow/block[2]/block[4]/@bpd"/>
<eval expected="42900" xpath="//flow/block[2]/block[4]/@bpda"/>
<eval expected="15000" xpath="//flow/block[2]/block[4]/@left-offset"/>
<eval expected="71600" xpath="//flow/block[2]/block[4]/@top-offset"/>
<eval expected="(double,#ff00ff,6000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-before"/>
<eval expected="(inset,#ff00ff,6000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-after"/>
<eval expected="(solid,#ff00ff,30000,collapse-outer)" xpath="//flow/block[2]/block[4]/@border-start"/>
<eval expected="(dashed,#ff0000,10000,collapse-inner)" xpath="//flow/block[2]/block[4]/@border-end"/>
<eval expected="95000" xpath="//flow/block[2]/block[5]/@ipd"/>
<eval expected="105000" xpath="//flow/block[2]/block[5]/@ipda"/>
<eval expected="52200" xpath="//flow/block[2]/block[5]/@bpd"/>
<eval expected="52200" xpath="//flow/block[2]/block[5]/@bpda"/>
<eval expected="105000" xpath="//flow/block[2]/block[5]/@left-offset"/>
<eval expected="22400" xpath="//flow/block[2]/block[5]/@top-offset"/>
<eval expected="(dashed,#ff0000,10000,collapse-inner)" xpath="//flow/block[2]/block[5]/@border-start"/>
<eval expected="98000" xpath="//flow/block[2]/block[6]/@ipd"/>
<eval expected="102000" xpath="//flow/block[2]/block[6]/@ipda"/>
<eval expected="50200" xpath="//flow/block[2]/block[6]/@bpd"/>
<eval expected="54200" xpath="//flow/block[2]/block[6]/@bpda"/>
<eval expected="200000" xpath="//flow/block[2]/block[6]/@left-offset"/>
<eval expected="20400" xpath="//flow/block[2]/block[6]/@top-offset"/>
<eval expected="(solid,#ff0000,4000,collapse-inner)" xpath="//flow/block[2]/block[6]/@border-before"/>
<eval expected="(double,#ff0000,4000,collapse-inner)" xpath="//flow/block[2]/block[6]/@border-end"/>
<eval expected="95000" xpath="//flow/block[2]/block[7]/@ipd"/>
<eval expected="105000" xpath="//flow/block[2]/block[7]/@ipda"/>
<eval expected="34400" xpath="//flow/block[2]/block[7]/@bpd"/>
<eval expected="39400" xpath="//flow/block[2]/block[7]/@bpda"/>
<eval expected="105000" xpath="//flow/block[2]/block[7]/@left-offset"/>
<eval expected="74600" xpath="//flow/block[2]/block[7]/@top-offset"/>
<eval expected="(outset,#c0c0c0,5000,collapse-inner)" xpath="//flow/block[2]/block[7]/@border-after"/>
<eval expected="(dashed,#ff0000,10000,collapse-inner)" xpath="//flow/block[2]/block[7]/@border-start"/>
<eval expected="98000" xpath="//flow/block[2]/block[8]/@ipd"/>
<eval expected="102000" xpath="//flow/block[2]/block[8]/@ipda"/>
<eval expected="16900" xpath="//flow/block[2]/block[8]/@bpd"/>
<eval expected="56900" xpath="//flow/block[2]/block[8]/@bpda"/>
<eval expected="200000" xpath="//flow/block[2]/block[8]/@left-offset"/>
<eval expected="74600" xpath="//flow/block[2]/block[8]/@top-offset"/>
<eval expected="(double,#008000,40000,collapse-inner)" xpath="//flow/block[2]/block[8]/@border-after"/>
<eval expected="(double,#ff0000,4000,collapse-inner)" xpath="//flow/block[2]/block[8]/@border-end"/>
<eval expected="193000" xpath="//flow/block[2]/block[9]/@ipd"/>
<eval expected="193000" xpath="//flow/block[2]/block[9]/@ipda"/>
<eval expected="67100" xpath="//flow/block[2]/block[9]/@bpd"/>
<eval expected="67100" xpath="//flow/block[2]/block[9]/@bpda"/>
<eval expected="105000" xpath="//flow/block[2]/block[9]/@left-offset"/>
<eval expected="24400" xpath="//flow/block[2]/block[9]/@top-offset"/>
<eval expected="98000" xpath="//flow/block[2]/block[10]/@ipd"/>
<eval expected="102000" xpath="//flow/block[2]/block[10]/@ipda"/>
<eval expected="14400" xpath="//flow/block[2]/block[10]/@bpd"/>
<eval expected="59400" xpath="//flow/block[2]/block[10]/@bpda"/>
<eval expected="302000" xpath="//flow/block[2]/block[10]/@left-offset"/>
<eval expected="72100" xpath="//flow/block[2]/block[10]/@top-offset"/>
<eval expected="(ridge,#800000,5000,collapse-inner)" xpath="//flow/block[2]/block[10]/@border-before"/>
<eval expected="(double,#008000,40000,collapse-inner)" xpath="//flow/block[2]/block[10]/@border-after"/>
<eval expected="(double,#ff0000,4000,collapse-inner)" xpath="//flow/block[2]/block[10]/@border-start"/>
<eval expected="78000" xpath="//flow/block[2]/block[11]/@ipd"/>
<eval expected="122000" xpath="//flow/block[2]/block[11]/@ipda"/>
<eval expected="56300" xpath="//flow/block[2]/block[11]/@bpd"/>
<eval expected="66300" xpath="//flow/block[2]/block[11]/@bpda"/>
<eval expected="2000" xpath="//flow/block[2]/block[11]/@left-offset"/>
<eval expected="108500" xpath="//flow/block[2]/block[11]/@top-offset"/>
<eval expected="(inset,#000000,6000,collapse-inner)" xpath="//flow/block[2]/block[11]/@border-before"/>
<eval expected="(solid,#000000,4000,collapse-inner)" xpath="//flow/block[2]/block[11]/@border-after"/>
<eval expected="(solid,#000000,4000,collapse-outer)" xpath="//flow/block[2]/block[11]/@border-start"/>
<eval expected="(solid,#000000,40000,collapse-inner)" xpath="//flow/block[2]/block[11]/@border-end"/>
<eval expected="77000" xpath="//flow/block[2]/block[12]/@ipd"/>
<eval expected="123000" xpath="//flow/block[2]/block[12]/@ipda"/>
<eval expected="28800" xpath="//flow/block[2]/block[12]/@bpd"/>
<eval expected="93800" xpath="//flow/block[2]/block[12]/@bpda"/>
<eval expected="120000" xpath="//flow/block[2]/block[12]/@left-offset"/>
<eval expected="109000" xpath="//flow/block[2]/block[12]/@top-offset"/>
<eval expected="(outset,#c0c0c0,5000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-before"/>
<eval expected="(solid,#c0c0c0,60000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-after"/>
<eval expected="(solid,#000000,40000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-start"/>
<eval expected="(solid,#008000,6000,collapse-inner)" xpath="//flow/block[2]/block[12]/@border-end"/>
<eval expected="95000" xpath="//flow/block[2]/block[13]/@ipd"/>
<eval expected="105000" xpath="//flow/block[2]/block[13]/@ipda"/>
<eval expected="36400" xpath="//flow/block[2]/block[13]/@bpd"/>
<eval expected="52400" xpath="//flow/block[2]/block[13]/@bpda"/>
<eval expected="2000" xpath="//flow/block[2]/block[13]/@left-offset"/>
<eval expected="170800" xpath="//flow/block[2]/block[13]/@top-offset"/>
<eval expected="(solid,#000000,4000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-before"/>
<eval expected="(solid,#800000,12000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-after"/>
<eval expected="(solid,#000000,4000,collapse-outer)" xpath="//flow/block[2]/block[13]/@border-start"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[2]/block[13]/@border-end"/>
<eval expected="67000" xpath="//flow/block[2]/block[14]/@ipd"/>
<eval expected="133000" xpath="//flow/block[2]/block[14]/@ipda"/>
<eval expected="14400" xpath="//flow/block[2]/block[14]/@bpd"/>
<eval expected="74400" xpath="//flow/block[2]/block[14]/@bpda"/>
<eval expected="103000" xpath="//flow/block[2]/block[14]/@left-offset"/>
<eval expected="142800" xpath="//flow/block[2]/block[14]/@top-offset"/>
<eval expected="(solid,#c0c0c0,60000,collapse-inner)" xpath="//flow/block[2]/block[14]/@border-before"/>
<eval expected="(solid,#c0c0c0,6000,collapse-inner)" xpath="//flow/block[2]/block[14]/@border-start"/>
<eval expected="(solid,#c0c0c0,60000,collapse-inner)" xpath="//flow/block[2]/block[14]/@border-end"/>
<eval expected="94000" xpath="//flow/block[2]/block[15]/@ipd"/>
<eval expected="106000" xpath="//flow/block[2]/block[15]/@ipda"/>
<eval expected="43200" xpath="//flow/block[2]/block[15]/@bpd"/>
<eval expected="61200" xpath="//flow/block[2]/block[15]/@bpda"/>
<eval expected="3000" xpath="//flow/block[2]/block[15]/@left-offset"/>
<eval expected="211200" xpath="//flow/block[2]/block[15]/@top-offset"/>
<eval expected="(solid,#800000,12000,collapse-inner)" xpath="//flow/block[2]/block[15]/@border-before"/>
<eval expected="(double,#800000,6000,collapse-outer)" xpath="//flow/block[2]/block[15]/@border-after"/>
<eval expected="(solid,#800000,6000,collapse-outer)" xpath="//flow/block[2]/block[15]/@border-start"/>
<eval expected="(solid,#800000,6000,collapse-inner)" xpath="//flow/block[2]/block[15]/@border-end"/>
<!--
<eval expected="94000" xpath="//flow/block[2]/block[16]/@ipd"/>
<eval expected="106000" xpath="//flow/block[2]/block[16]/@ipda"/>
<eval expected="52200" xpath="//flow/block[2]/block[16]/@bpd"/>
<eval expected="52200" xpath="//flow/block[2]/block[16]/@bpda"/>
<eval expected="103000" xpath="//flow/block[2]/block[16]/@left-offset"/>
<eval expected="217200" xpath="//flow/block[2]/block[16]/@top-offset"/>
<eval expected="(double,#800000,0,collapse-outer)" xpath="//flow/block[2]/block[16]/@border-after"/>
<eval expected="(solid,#800000,6000,collapse-inner)" xpath="//flow/block[2]/block[16]/@border-start"/>
<eval expected="(solid,#008000,6000,collapse-inner)" xpath="//flow/block[2]/block[16]/@border-end"/>
-->
<eval expected="97000" xpath="//flow/block[2]/block[16]/@ipd"/>
<eval expected="103000" xpath="//flow/block[2]/block[16]/@ipda"/>
<eval expected="41300" xpath="//flow/block[2]/block[16]/@bpd"/>
<eval expected="81300" xpath="//flow/block[2]/block[16]/@bpda"/>
<eval expected="203000" xpath="//flow/block[2]/block[16]/@left-offset"/>
<eval expected="91500" xpath="//flow/block[2]/block[16]/@top-offset"/>
<eval expected="(double,#008000,40000,collapse-inner)" xpath="//flow/block[2]/block[16]/@border-before"/>
<eval expected="(solid,#008000,6000,collapse-inner)" xpath="//flow/block[2]/block[16]/@border-start"/>
<eval expected="97500" xpath="//flow/block[2]/block[17]/@ipd"/>
<eval expected="102500" xpath="//flow/block[2]/block[17]/@ipda"/>
<eval expected="41300" xpath="//flow/block[2]/block[17]/@bpd"/>
<eval expected="81300" xpath="//flow/block[2]/block[17]/@bpda"/>
<eval expected="300000" xpath="//flow/block[2]/block[17]/@left-offset"/>
<eval expected="91500" xpath="//flow/block[2]/block[17]/@top-offset"/>
<eval expected="(double,#008000,40000,collapse-inner)" xpath="//flow/block[2]/block[17]/@border-before"/>
<eval expected="(dashed,#008000,5000,collapse-outer)" xpath="//flow/block[2]/block[17]/@border-end"/>
<eval expected="70000" xpath="//flow/block[2]/block[18]/@ipd"/>
<eval expected="130000" xpath="//flow/block[2]/block[18]/@ipda"/>
<eval expected="44400" xpath="//flow/block[2]/block[18]/@bpd"/>
<eval expected="44400" xpath="//flow/block[2]/block[18]/@bpda"/>
<eval expected="230000" xpath="//flow/block[2]/block[18]/@left-offset"/>
<eval expected="172800" xpath="//flow/block[2]/block[18]/@top-offset"/>
<eval expected="(solid,#c0c0c0,60000,collapse-inner)" xpath="//flow/block[2]/block[18]/@border-start"/>
<eval expected="97500" xpath="//flow/block[2]/block[19]/@ipd"/>
<eval expected="102500" xpath="//flow/block[2]/block[19]/@ipda"/>
<eval expected="44400" xpath="//flow/block[2]/block[19]/@bpd"/>
<eval expected="44400" xpath="//flow/block[2]/block[19]/@bpda"/>
<eval expected="300000" xpath="//flow/block[2]/block[19]/@left-offset"/>
<eval expected="172800" xpath="//flow/block[2]/block[19]/@top-offset"/>
<eval expected="(dashed,#008000,5000,collapse-outer)" xpath="//flow/block[2]/block[19]/@border-end"/>
<eval expected="97000" xpath="//flow/block[2]/block[20]/@ipd"/>
<eval expected="103000" xpath="//flow/block[2]/block[20]/@ipda"/>
<eval expected="49700" xpath="//flow/block[2]/block[20]/@bpd"/>
<eval expected="54700" xpath="//flow/block[2]/block[20]/@bpda"/>
<eval expected="203000" xpath="//flow/block[2]/block[20]/@left-offset"/>
<eval expected="217200" xpath="//flow/block[2]/block[20]/@top-offset"/>
<eval expected="(solid,#008000,5000,collapse-outer)" xpath="//flow/block[2]/block[20]/@border-after"/>
<eval expected="(solid,#008000,6000,collapse-inner)" xpath="//flow/block[2]/block[20]/@border-start"/>
<eval expected="97500" xpath="//flow/block[2]/block[21]/@ipd"/>
<eval expected="102500" xpath="//flow/block[2]/block[21]/@ipda"/>
<eval expected="49700" xpath="//flow/block[2]/block[21]/@bpd"/>
<eval expected="54700" xpath="//flow/block[2]/block[21]/@bpda"/>
<eval expected="300000" xpath="//flow/block[2]/block[21]/@left-offset"/>
<eval expected="217200" xpath="//flow/block[2]/block[21]/@top-offset"/>
<eval expected="(solid,#008000,5000,collapse-outer)" xpath="//flow/block[2]/block[21]/@border-after"/>
<eval expected="(dashed,#008000,5000,collapse-outer)" xpath="//flow/block[2]/block[21]/@border-end"/>
<eval expected="167500" xpath="//flow/block[2]/block[22]/@ipd"/>
<eval expected="167500" xpath="//flow/block[2]/block[22]/@ipda"/>
<eval expected="135400" xpath="//flow/block[2]/block[22]/@bpd"/>
<eval expected="135400" xpath="//flow/block[2]/block[22]/@bpda"/>
<eval expected="230000" xpath="//flow/block[2]/block[22]/@left-offset"/>
<eval expected="131500" xpath="//flow/block[2]/block[22]/@top-offset"/>

<!-- table 2 -->
<eval expected="199300" xpath="//flow/block[4]/@bpd"/>
<eval expected="199300" xpath="//flow/block[4]/@bpda"/>
<eval expected="91500" xpath="//flow/block[4]/block[1]/@ipd"/>
<eval expected="108500" xpath="//flow/block[4]/block[1]/@ipda"/>
<eval expected="41300" xpath="//flow/block[4]/block[1]/@bpd"/>
<eval expected="65300" xpath="//flow/block[4]/block[1]/@bpda"/>
<eval expected="6000" xpath="//flow/block[4]/block[1]/@left-offset"/>
<eval expected="-6000" xpath="//flow/block[4]/block[1]/@top-offset"/>
<eval expected="(solid,#000000,12000,collapse-outer)" xpath="//flow/block[4]/block[1]/@border-before"/>
<eval expected="(solid,#0000ff,12000,collapse-inner)" xpath="//flow/block[4]/block[1]/@border-after"/>
<eval expected="(solid,#ff0000,12000,collapse-outer)" xpath="//flow/block[4]/block[1]/@border-start"/>
<eval expected="(solid,#800080,5000,collapse-inner)" xpath="//flow/block[4]/block[1]/@border-end"/>
<eval expected="72500" xpath="//flow/block[4]/block[2]/@ipd"/>
<eval expected="107500" xpath="//flow/block[4]/block[2]/@ipda"/>
<eval expected="28800" xpath="//flow/block[4]/block[2]/@bpd"/>
<eval expected="57800" xpath="//flow/block[4]/block[2]/@bpda"/>
<eval expected="112500" xpath="//flow/block[4]/block[2]/@left-offset"/>
<eval expected="-2000" xpath="//flow/block[4]/block[2]/@top-offset"/>
<eval expected="(solid,#c0c0c0,4000,collapse-outer)" xpath="//flow/block[4]/block[2]/@border-before"/>
<eval expected="(solid,#800080,5000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-after"/>
<eval expected="(solid,#800080,5000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-start"/>
<eval expected="(solid,#808000,10000,collapse-inner)" xpath="//flow/block[4]/block[2]/@border-end"/>
<eval expected="87000" xpath="//flow/block[4]/block[3]/@ipd"/>
<eval expected="113000" xpath="//flow/block[4]/block[3]/@ipda"/>
<eval expected="47300" xpath="//flow/block[4]/block[3]/@bpd"/>
<eval expected="59300" xpath="//flow/block[4]/block[3]/@bpda"/>
<eval expected="205000" xpath="//flow/block[4]/block[3]/@left-offset"/>
<eval expected="-3000" xpath="//flow/block[4]/block[3]/@top-offset"/>
<eval expected="(solid,#000000,6000,collapse-outer)" xpath="//flow/block[4]/block[3]/@border-before"/>
<eval expected="(solid,#000080,6000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-after"/>
<eval expected="(solid,#808000,10000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-start"/>
<eval expected="(solid,#ff0000,16000,collapse-inner)" xpath="//flow/block[4]/block[3]/@border-end"/>
<eval expected="90000" xpath="//flow/block[4]/block[4]/@ipd"/>
<eval expected="110000" xpath="//flow/block[4]/block[4]/@ipda"/>
<eval expected="48300" xpath="//flow/block[4]/block[4]/@bpd"/>
<eval expected="58300" xpath="//flow/block[4]/block[4]/@bpda"/>
<eval expected="308000" xpath="//flow/block[4]/block[4]/@left-offset"/>
<eval expected="(solid,#0000ff,10000,collapse-inner)" xpath="//flow/block[4]/block[4]/@border-after"/>
<eval expected="(solid,#ff0000,16000,collapse-inner)" xpath="//flow/block[4]/block[4]/@border-start"/>
<eval expected="(solid,#008080,4000,collapse-outer)" xpath="//flow/block[4]/block[4]/@border-end"/>
<eval expected="92000" xpath="//flow/block[4]/block[5]/@ipd"/>
<eval expected="108000" xpath="//flow/block[4]/block[5]/@ipda"/>
<eval expected="14400" xpath="//flow/block[4]/block[5]/@bpd"/>
<eval expected="30400" xpath="//flow/block[4]/block[5]/@bpda"/>
<eval expected="6000" xpath="//flow/block[4]/block[5]/@left-offset"/>
<eval expected="47300" xpath="//flow/block[4]/block[5]/@top-offset"/>
<eval expected="(solid,#0000ff,12000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-before"/>
<eval expected="(solid,#0000ff,4000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-after"/>
<eval expected="(solid,#800080,12000,collapse-outer)" xpath="//flow/block[4]/block[5]/@border-start"/>
<eval expected="(solid,#008080,4000,collapse-inner)" xpath="//flow/block[4]/block[5]/@border-end"/>
<eval expected="93500" xpath="//flow/block[4]/block[6]/@ipd"/>
<eval expected="106500" xpath="//flow/block[4]/block[6]/@ipda"/>
<eval expected="28800" xpath="//flow/block[4]/block[6]/@bpd"/>
<eval expected="42800" xpath="//flow/block[4]/block[6]/@bpda"/>
<eval expected="1500" xpath="//flow/block[4]/block[6]/@left-offset"/>
<eval expected="73700" xpath="//flow/block[4]/block[6]/@top-offset"/>
<eval expected="(solid,#0000ff,4000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-before"/>
<eval expected="(solid,#c0c0c0,10000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-after"/>
<eval expected="(solid,#ff0000,3000,collapse-outer)" xpath="//flow/block[4]/block[6]/@border-start"/>
<eval expected="(solid,#008080,10000,collapse-inner)" xpath="//flow/block[4]/block[6]/@border-end"/>
<eval expected="89000" xpath="//flow/block[4]/block[7]/@ipd"/>
<eval expected="111000" xpath="//flow/block[4]/block[7]/@ipda"/>
<eval expected="14400" xpath="//flow/block[4]/block[7]/@bpd"/>
<eval expected="36400" xpath="//flow/block[4]/block[7]/@bpda"/>
<eval expected="3000" xpath="//flow/block[4]/block[7]/@left-offset"/>
<eval expected="106500" xpath="//flow/block[4]/block[7]/@top-offset"/>
<eval expected="(solid,#c0c0c0,10000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-before"/>
<eval expected="(solid,#000000,12000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-after"/>
<eval expected="(solid,#800080,6000,collapse-outer)" xpath="//flow/block[4]/block[7]/@border-start"/>
<eval expected="(solid,#808000,16000,collapse-inner)" xpath="//flow/block[4]/block[7]/@border-end"/>
<eval expected="98000" xpath="//flow/block[4]/block[8]/@ipd"/>
<eval expected="102000" xpath="//flow/block[4]/block[8]/@ipda"/>
<eval expected="19900" xpath="//flow/block[4]/block[8]/@bpd"/>
<eval expected="24900" xpath="//flow/block[4]/block[8]/@bpda"/>
<eval expected="102000" xpath="//flow/block[4]/block[8]/@left-offset"/>
<eval expected="50800" xpath="//flow/block[4]/block[8]/@top-offset"/>
<eval expected="(solid,#800080,5000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-before"/>
<eval expected="(solid,#008080,4000,collapse-inner)" xpath="//flow/block[4]/block[8]/@border-start"/>
<eval expected="100000" xpath="//flow/block[4]/block[9]/@ipd"/>
<eval expected="100000" xpath="//flow/block[4]/block[9]/@ipda"/>
<eval expected="19400" xpath="//flow/block[4]/block[9]/@bpd"/>
<eval expected="25400" xpath="//flow/block[4]/block[9]/@bpda"/>
<eval expected="200000" xpath="//flow/block[4]/block[9]/@left-offset"/>
<eval expected="50300" xpath="//flow/block[4]/block[9]/@top-offset"/>
<eval expected="(solid,#000080,6000,collapse-inner)" xpath="//flow/block[4]/block[9]/@border-before"/>
<eval expected="98000" xpath="//flow/block[4]/block[10]/@ipd"/>
<eval expected="102000" xpath="//flow/block[4]/block[10]/@ipda"/>
<eval expected="17400" xpath="//flow/block[4]/block[10]/@bpd"/>
<eval expected="27400" xpath="//flow/block[4]/block[10]/@bpda"/>
<eval expected="300000" xpath="//flow/block[4]/block[10]/@left-offset"/>
<eval expected="48300" xpath="//flow/block[4]/block[10]/@top-offset"/>
<eval expected="(solid,#0000ff,10000,collapse-inner)" xpath="//flow/block[4]/block[10]/@border-before"/>
<eval expected="(solid,#808000,4000,collapse-outer)" xpath="//flow/block[4]/block[10]/@border-end"/>
<eval expected="95000" xpath="//flow/block[4]/block[11]/@ipd"/>
<eval expected="105000" xpath="//flow/block[4]/block[11]/@ipda"/>
<eval expected="35800" xpath="//flow/block[4]/block[11]/@bpd"/>
<eval expected="35800" xpath="//flow/block[4]/block[11]/@bpda"/>
<eval expected="105000" xpath="//flow/block[4]/block[11]/@left-offset"/>
<eval expected="75700" xpath="//flow/block[4]/block[11]/@top-offset"/>
<eval expected="(solid,#008080,10000,collapse-inner)" xpath="//flow/block[4]/block[11]/@border-start"/>
<eval expected="98000" xpath="//flow/block[4]/block[12]/@ipd"/>
<eval expected="102000" xpath="//flow/block[4]/block[12]/@ipda"/>
<eval expected="35800" xpath="//flow/block[4]/block[12]/@bpd"/>
<eval expected="35800" xpath="//flow/block[4]/block[12]/@bpda"/>
<eval expected="300000" xpath="//flow/block[4]/block[12]/@left-offset"/>
<eval expected="75700" xpath="//flow/block[4]/block[12]/@top-offset"/>
<eval expected="(solid,#808000,4000,collapse-outer)" xpath="//flow/block[4]/block[12]/@border-end"/>
<eval expected="92000" xpath="//flow/block[4]/block[13]/@ipd"/>
<eval expected="108000" xpath="//flow/block[4]/block[13]/@ipda"/>
<eval expected="19400" xpath="//flow/block[4]/block[13]/@bpd"/>
<eval expected="31400" xpath="//flow/block[4]/block[13]/@bpda"/>
<eval expected="108000" xpath="//flow/block[4]/block[13]/@left-offset"/>
<eval expected="111500" xpath="//flow/block[4]/block[13]/@top-offset"/>
<eval expected="(solid,#000080,12000,collapse-inner)" xpath="//flow/block[4]/block[13]/@border-after"/>
<eval expected="(solid,#808000,16000,collapse-inner)" xpath="//flow/block[4]/block[13]/@border-start"/>
<eval expected="100000" xpath="//flow/block[4]/block[14]/@ipd"/>
<eval expected="100000" xpath="//flow/block[4]/block[14]/@ipda"/>
<eval expected="10400" xpath="//flow/block[4]/block[14]/@bpd"/>
<eval expected="40400" xpath="//flow/block[4]/block[14]/@bpda"/>
<eval expected="200000" xpath="//flow/block[4]/block[14]/@left-offset"/>
<eval expected="111500" xpath="//flow/block[4]/block[14]/@top-offset"/>
<eval expected="(solid,#c0c0c0,30000,collapse-inner)" xpath="//flow/block[4]/block[14]/@border-after"/>
<eval expected="98000" xpath="//flow/block[4]/block[15]/@ipd"/>
<eval expected="102000" xpath="//flow/block[4]/block[15]/@ipda"/>
<eval expected="19400" xpath="//flow/block[4]/block[15]/@bpd"/>
<eval expected="31400" xpath="//flow/block[4]/block[15]/@bpda"/>
<eval expected="300000" xpath="//flow/block[4]/block[15]/@left-offset"/>
<eval expected="111500" xpath="//flow/block[4]/block[15]/@top-offset"/>
<eval expected="(solid,#000080,12000,collapse-inner)" xpath="//flow/block[4]/block[15]/@border-after"/>
<eval expected="(solid,#808000,4000,collapse-outer)" xpath="//flow/block[4]/block[15]/@border-end"/>
<eval expected="260000" xpath="//flow/block[4]/block[16]/@ipd"/>
<eval expected="290000" xpath="//flow/block[4]/block[16]/@ipda"/>
<eval expected="33600" xpath="//flow/block[4]/block[16]/@bpd"/>
<eval expected="63600" xpath="//flow/block[4]/block[16]/@bpda"/>
<eval expected="123000" xpath="//flow/block[4]/block[16]/@left-offset"/>
<eval expected="58300" xpath="//flow/block[4]/block[16]/@top-offset"/>
<eval expected="88000" xpath="//flow/block[4]/block[17]/@ipd"/>
<eval expected="112000" xpath="//flow/block[4]/block[17]/@ipda"/>
<eval expected="50400" xpath="//flow/block[4]/block[17]/@bpd"/>
<eval expected="74400" xpath="//flow/block[4]/block[17]/@bpda"/>
<eval expected="6000" xpath="//flow/block[4]/block[17]/@left-offset"/>
<eval expected="130900" xpath="//flow/block[4]/block[17]/@top-offset"/>
<eval expected="(solid,#000000,12000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-before"/>
<eval expected="(solid,#0000ff,12000,collapse-outer)" xpath="//flow/block[4]/block[17]/@border-after"/>
<eval expected="(solid,#ff0000,12000,collapse-outer)" xpath="//flow/block[4]/block[17]/@border-start"/>
<eval expected="(solid,#008080,12000,collapse-inner)" xpath="//flow/block[4]/block[17]/@border-end"/>
<eval expected="89000" xpath="//flow/block[4]/block[18]/@ipd"/>
<eval expected="111000" xpath="//flow/block[4]/block[18]/@ipda"/>
<eval expected="54400" xpath="//flow/block[4]/block[18]/@bpd"/>
<eval expected="70400" xpath="//flow/block[4]/block[18]/@bpda"/>
<eval expected="106000" xpath="//flow/block[4]/block[18]/@left-offset"/>
<eval expected="130900" xpath="//flow/block[4]/block[18]/@top-offset"/>
<eval expected="(solid,#000080,12000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-before"/>
<eval expected="(solid,#800080,4000,collapse-outer)" xpath="//flow/block[4]/block[18]/@border-after"/>
<eval expected="(solid,#008080,12000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-start"/>
<eval expected="(solid,#808000,10000,collapse-inner)" xpath="//flow/block[4]/block[18]/@border-end"/>
<eval expected="87000" xpath="//flow/block[4]/block[19]/@ipd"/>
<eval expected="113000" xpath="//flow/block[4]/block[19]/@ipda"/>
<eval expected="44400" xpath="//flow/block[4]/block[19]/@bpd"/>
<eval expected="80400" xpath="//flow/block[4]/block[19]/@bpda"/>
<eval expected="205000" xpath="//flow/block[4]/block[19]/@left-offset"/>
<eval expected="121900" xpath="//flow/block[4]/block[19]/@top-offset"/>
<eval expected="(solid,#c0c0c0,30000,collapse-inner)" xpath="//flow/block[4]/block[19]/@border-before"/>
<eval expected="(solid,#000080,6000,collapse-outer)" xpath="//flow/block[4]/block[19]/@border-after"/>
<eval expected="(solid,#808000,10000,collapse-inner)" xpath="//flow/block[4]/block[19]/@border-start"/>
<eval expected="(solid,#808000,16000,collapse-inner)" xpath="//flow/block[4]/block[19]/@border-end"/>
<eval expected="50000" xpath="//flow/block[4]/block[20]/@ipd"/>
<eval expected="110000" xpath="//flow/block[4]/block[20]/@ipda"/>
<eval expected="14400" xpath="//flow/block[4]/block[20]/@bpd"/>
<eval expected="70400" xpath="//flow/block[4]/block[20]/@bpda"/>
<eval expected="328000" xpath="//flow/block[4]/block[20]/@left-offset"/>
<eval expected="130900" xpath="//flow/block[4]/block[20]/@top-offset"/>
<eval expected="(solid,#000080,12000,collapse-inner)" xpath="//flow/block[4]/block[20]/@border-before"/>
<eval expected="(solid,#0000ff,4000,collapse-outer)" xpath="//flow/block[4]/block[20]/@border-after"/>
<eval expected="(solid,#808000,16000,collapse-inner)" xpath="//flow/block[4]/block[20]/@border-start"/>
<eval expected="(solid,#008080,4000,collapse-outer)" xpath="//flow/block[4]/block[20]/@border-end"/>
</checks>
</testcase>

Loading…
Annulla
Salva