in fop-core/src/main/java/org/apache/fop/layoutmgr/table/TableStepper.java [178:294]
public LinkedList getCombinedKnuthElementsForRowGroup(LayoutContext context, EffRow[] rows,
int bodyType) {
setup(rows);
activateCells(activeCells, 0);
calcTotalHeight();
int cumulateLength = 0; // Length of the content accumulated before the break
TableContentPosition lastTCPos = null;
LinkedList<ListElement> returnList = new LinkedList<>();
int laststep = 0;
int step = getFirstStep();
do {
int maxRemainingHeight = getMaxRemainingHeight();
int penaltyOrGlueLen = step + maxRemainingHeight - totalHeight;
int boxLen = step - cumulateLength - Math.max(0, penaltyOrGlueLen)/* penalty, if any */;
cumulateLength += boxLen + Math.max(0, -penaltyOrGlueLen)/* the glue, if any */;
if (log.isDebugEnabled()) {
log.debug("Next step: " + step + " (+" + (step - laststep) + ")");
log.debug(" max remaining height: " + maxRemainingHeight);
if (penaltyOrGlueLen >= 0) {
log.debug(" box = " + boxLen + " penalty = " + penaltyOrGlueLen);
} else {
log.debug(" box = " + boxLen + " glue = " + (-penaltyOrGlueLen));
}
}
LinkedList footnoteList = new LinkedList();
//Put all involved grid units into a list
List cellParts = new java.util.ArrayList(activeCells.size());
for (Object activeCell2 : activeCells) {
ActiveCell activeCell = (ActiveCell) activeCell2;
CellPart part = activeCell.createCellPart();
cellParts.add(part);
activeCell.addFootnotes(footnoteList);
}
//Create elements for step
TableContentPosition tcpos = new TableContentPosition(getTableLM(),
cellParts, rowGroup[activeRowIndex]);
if (delayingNextRow) {
tcpos.setNewPageRow(rowGroup[activeRowIndex + 1]);
}
if (returnList.size() == 0) {
tcpos.setFlag(TableContentPosition.FIRST_IN_ROWGROUP, true);
}
lastTCPos = tcpos;
// TODO TableStepper should remain as footnote-agnostic as possible
if (footnoteList.isEmpty()) {
returnList.add(new KnuthBox(boxLen, tcpos, false));
} else {
returnList.add(new KnuthBlockBox(boxLen, footnoteList, tcpos, false));
}
int effPenaltyLen = Math.max(0, penaltyOrGlueLen);
TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM());
if (bodyType == TableRowIterator.BODY) {
if (!getTableLM().getTable().omitHeaderAtBreak()) {
effPenaltyLen += tclm.getHeaderNetHeight();
penaltyPos.headerElements = tclm.getHeaderElements();
}
if (!getTableLM().getTable().omitFooterAtBreak()) {
effPenaltyLen += tclm.getFooterNetHeight();
penaltyPos.footerElements = tclm.getFooterElements();
}
}
Keep keep = getTableLM().getKeepTogether();
int stepPenalty = 0;
for (Object activeCell1 : activeCells) {
ActiveCell activeCell = (ActiveCell) activeCell1;
keep = keep.compare(activeCell.getKeepWithNext());
stepPenalty = Math.max(stepPenalty, activeCell.getPenaltyValue());
}
if (!rowFinished) {
keep = keep.compare(rowGroup[activeRowIndex].getKeepTogether());
} else if (activeRowIndex < rowGroup.length - 1) {
keep = keep.compare(rowGroup[activeRowIndex].getKeepWithNext());
keep = keep.compare(rowGroup[activeRowIndex + 1].getKeepWithPrevious());
nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
rowGroup[activeRowIndex].getBreakAfter());
nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
rowGroup[activeRowIndex + 1].getBreakBefore());
}
int p = keep.getPenalty();
if (rowHeightSmallerThanFirstStep) {
rowHeightSmallerThanFirstStep = false;
p = KnuthPenalty.INFINITE;
}
p = Math.max(p, stepPenalty);
int breakClass = keep.getContext();
if (nextBreakClass != Constants.EN_AUTO) {
log.trace("Forced break encountered");
p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
breakClass = nextBreakClass;
}
returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context));
laststep = step;
step = getNextStep();
if (penaltyOrGlueLen < 0) {
int shrink = 0;
int stretch = 0;
int width = -penaltyOrGlueLen;
LayoutManager bslm = getTableLM().getParent();
if (bslm instanceof BlockStackingLayoutManager && ((BlockStackingLayoutManager)bslm).isRestartAtLM()
&& keep.getPenalty() == KnuthPenalty.INFINITE) {
width = 0;
}
returnList.add(new KnuthGlue(width, stretch, shrink, new Position(null), true));
}
} while (step >= 0);
assert !returnList.isEmpty();
lastTCPos.setFlag(TableContentPosition.LAST_IN_ROWGROUP, true);
return returnList;
}