in fop-core/src/main/java/org/apache/fop/layoutmgr/table/RowPainter.java [200:345]
private void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) {
if (currentRow == null) {
return;
}
if (log.isDebugEnabled()) {
log.debug("Remembering yoffset for row " + currentRow.getIndex() + ": "
+ currentRowOffset);
}
recordRowOffset(currentRow.getIndex(), currentRowOffset);
// Need to compute the actual row height first
// and determine border behaviour for empty cells
boolean firstCellPart = true;
boolean lastCellPart = true;
int actualRowHeight = 0;
for (int i = 0; i < colCount; i++) {
GridUnit currentGU = currentRow.getGridUnit(i);
if (currentGU.isEmpty()) {
continue;
}
if (currentGU.getColSpanIndex() == 0
&& (lastInPart || currentGU.isLastGridUnitRowSpan())
&& firstCellParts[i] != null) {
// TODO
// The last test above is a workaround for the stepping algorithm's
// fundamental flaw making it unable to produce the right element list for
// multiple breaks inside a same row group.
// (see http://wiki.apache.org/xmlgraphics-fop/TableLayout/KnownProblems)
// In some extremely rare cases (forced breaks, very small page height), a
// TableContentPosition produced during row delaying may end up alone on a
// page. It will not contain the CellPart instances for the cells starting
// the next row, so firstCellParts[i] will still be null for those ones.
int cellHeight = cellHeights[i];
cellHeight += lastCellParts[i].getConditionalAfterContentLength();
cellHeight += lastCellParts[i].getBorderPaddingAfter(lastInPart);
int cellOffset = getRowOffset(Math.max(firstCellParts[i].pgu.getRowIndex(),
firstRowIndex));
actualRowHeight = Math.max(actualRowHeight, cellOffset + cellHeight
- currentRowOffset);
}
if (firstCellParts[i] != null && !firstCellParts[i].isFirstPart()) {
firstCellPart = false;
}
if (lastCellParts[i] != null && !lastCellParts[i].isLastPart()) {
lastCellPart = false;
}
}
// Then add areas for cells finishing on the current row
for (int i = 0; i < colCount; i++) {
GridUnit currentGU = currentRow.getGridUnit(i);
if (currentGU.isEmpty() && !tclm.isSeparateBorderModel()) {
int borderBeforeWhich;
if (firstCellPart) {
if (firstCellOnPage[i]) {
borderBeforeWhich = ConditionalBorder.LEADING_TRAILING;
} else {
borderBeforeWhich = ConditionalBorder.NORMAL;
}
} else {
borderBeforeWhich = ConditionalBorder.REST;
}
int borderAfterWhich;
if (lastCellPart) {
if (lastInPart) {
borderAfterWhich = ConditionalBorder.LEADING_TRAILING;
} else {
borderAfterWhich = ConditionalBorder.NORMAL;
}
} else {
borderAfterWhich = ConditionalBorder.REST;
}
assert (currentGU instanceof EmptyGridUnit);
addAreaForEmptyGridUnit((EmptyGridUnit)currentGU,
currentRow.getIndex(), i,
actualRowHeight,
borderBeforeWhich, borderAfterWhich,
lastOnPage);
firstCellOnPage[i] = false;
} else if (currentGU.getColSpanIndex() == 0
&& (lastInPart || currentGU.isLastGridUnitRowSpan())
&& firstCellParts[i] != null) {
assert firstCellParts[i].pgu == currentGU.getPrimary();
int borderBeforeWhich;
if (firstCellParts[i].isFirstPart()) {
if (firstCellOnPage[i]) {
borderBeforeWhich = ConditionalBorder.LEADING_TRAILING;
} else {
borderBeforeWhich = ConditionalBorder.NORMAL;
}
} else {
assert firstCellOnPage[i];
borderBeforeWhich = ConditionalBorder.REST;
}
int borderAfterWhich;
if (lastCellParts[i].isLastPart()) {
if (lastInPart) {
borderAfterWhich = ConditionalBorder.LEADING_TRAILING;
} else {
borderAfterWhich = ConditionalBorder.NORMAL;
}
} else {
borderAfterWhich = ConditionalBorder.REST;
}
// when adding the areas for the TableCellLayoutManager this helps with the isLast trait
// if, say, the first cell of a row has content that fits in the page, but the content of
// the second cell does not fit this will assure that the isLast trait for the first cell
// will also be false
lastCellParts[i].pgu.getCellLM().setLastTrait(lastCellParts[i].isLastPart());
addAreasForCell(firstCellParts[i].pgu,
firstCellParts[i].start, lastCellParts[i].end,
actualRowHeight, borderBeforeWhich, borderAfterWhich,
lastOnPage);
firstCellParts[i] = null; // why? what about the lastCellParts[i]?
Arrays.fill(firstCellOnPage, i, i + currentGU.getCell().getNumberColumnsSpanned(),
false);
}
}
currentRowOffset += actualRowHeight;
if (lastInPart) {
/*
* Either the end of the page is reached, then this was the last call of this
* method and we no longer care about currentRow; or the end of a table-part
* (header, footer, body) has been reached, and the next row will anyway be
* different from the current one, and this is unnecessary to call this method
* again in the first lines of handleTableContentPosition, so we may reset the
* following variables.
*/
currentRow = null;
firstRowIndex = -1;
rowOffsets.clear();
/*
* The current table part has just been handled. Be it the first one or not,
* the header or the body, in any case the borders-before of the next row
* (i.e., the first row of the next part if any) must be painted in
* COLLAPSE_INNER mode. So the firstRowOnPageIndex indicator must be kept
* disabled. The following way is not the most elegant one but will be good
* enough.
*/
firstRowOnPageIndex = Integer.MAX_VALUE;
}
}