private void addAreasAndFlushRow()

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;
        }
    }