You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by sp...@apache.org on 2008/02/14 22:57:53 UTC
svn commit: r627882 [9/41] - in
/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking: ./
examples/embedding/ examples/embedding/java/embedding/
examples/embedding/java/embedding/intermediate/ examples/embedding/xml/xml/
examples/fo/ examples/f...
Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/RowPainter.java?rev=627882&r1=627881&r2=627882&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/RowPainter.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/RowPainter.java Thu Feb 14 13:55:44 2008
@@ -26,31 +26,39 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.fo.flow.table.ConditionalBorder;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.TableRow;
-import org.apache.fop.fo.properties.LengthRangeProperty;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthPossPosIter;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.SpaceResolver;
+import org.apache.fop.traits.BorderProps;
class RowPainter {
private static Log log = LogFactory.getLog(RowPainter.class);
/** The fo:table-row containing the currently handled grid rows. */
private TableRow rowFO = null;
private int colCount;
- private int yoffset = 0;
- private int accumulatedBPD = 0;
+ private int currentRowOffset = 0;
/** Currently handled row (= last encountered row). */
- private EffRow lastRow = null;
+ private EffRow currentRow = null;
private LayoutContext layoutContext;
/**
* Index of the first row of the current part present on the current page.
*/
private int firstRowIndex;
+
+ /**
+ * Index of the very first row on the current page. Needed to properly handle
+ * {@link BorderProps#COLLAPSE_OUTER}. This is not the same as {@link #firstRowIndex}
+ * when the table has headers!
+ */
+ private int firstRowOnPageIndex;
+
/**
* Keeps track of the y-offsets of each row on a page.
* This is particularly needed for spanned cells where you need to know the y-offset
@@ -58,40 +66,27 @@
*/
private List rowOffsets = new ArrayList();
- //These three variables are our buffer to recombine the individual steps into cells
- /** Primary grid units corresponding to the currently handled grid units, per row. */
- private PrimaryGridUnit[] primaryGridUnits;
- /**
- * Index, in the corresponding table cell's list of Knuth elements, of the first
- * element present on the current page, per column.
- */
- private int[] start;
- /**
- * Index, in the corresponding table cell's list of Knuth elements, of the last
- * element present on the current page, per column.
- */
- private int[] end;
- /**
- * Length, for each column, of the elements from the current cell put on the
- * current page. This is the corresponding area's bpd.
- */
- private int[] partBPD;
+ private int[] cellHeights;
+ private boolean[] firstCellOnPage;
+ private CellPart[] firstCellParts;
+ private CellPart[] lastCellParts;
+
private TableContentLayoutManager tclm;
RowPainter(TableContentLayoutManager tclm, LayoutContext layoutContext) {
this.tclm = tclm;
this.layoutContext = layoutContext;
this.colCount = tclm.getColumns().getColumnCount();
- this.primaryGridUnits = new PrimaryGridUnit[colCount];
- this.start = new int[colCount];
- this.end = new int[colCount];
- this.partBPD = new int[colCount];
+ this.cellHeights = new int[colCount];
+ this.firstCellOnPage = new boolean[colCount];
+ this.firstCellParts = new CellPart[colCount];
+ this.lastCellParts = new CellPart[colCount];
this.firstRowIndex = -1;
- Arrays.fill(end, -1);
+ this.firstRowOnPageIndex = -1;
}
int getAccumulatedBPD() {
- return this.accumulatedBPD;
+ return currentRowOffset;
}
/**
@@ -101,16 +96,24 @@
* @param tcpos a position representing the row fragment
*/
void handleTableContentPosition(TableContentPosition tcpos) {
- if (lastRow != tcpos.row && lastRow != null) {
- addAreasAndFlushRow(false);
- }
if (log.isDebugEnabled()) {
log.debug("===handleTableContentPosition(" + tcpos);
}
- rowFO = tcpos.row.getTableRow();
- lastRow = tcpos.row;
+ if (currentRow == null) {
+ currentRow = tcpos.getNewPageRow();
+ } else {
+ EffRow row = tcpos.getRow();
+ if (row.getIndex() > currentRow.getIndex()) {
+ addAreasAndFlushRow(false, false);
+ currentRow = row;
+ }
+ }
+ rowFO = currentRow.getTableRow();
if (firstRowIndex < 0) {
- firstRowIndex = lastRow.getIndex();
+ firstRowIndex = currentRow.getIndex();
+ if (firstRowOnPageIndex < 0) {
+ firstRowOnPageIndex = firstRowIndex;
+ }
}
Iterator partIter = tcpos.cellParts.iterator();
//Iterate over all grid units in the current step
@@ -119,212 +122,204 @@
if (log.isDebugEnabled()) {
log.debug(">" + cellPart);
}
- int colIndex = cellPart.pgu.getStartCol();
- if (primaryGridUnits[colIndex] != cellPart.pgu) {
- if (primaryGridUnits[colIndex] != null) {
- log.warn("Replacing GU in slot " + colIndex
- + ". Some content may not be painted.");
- }
- primaryGridUnits[colIndex] = cellPart.pgu;
- start[colIndex] = cellPart.start;
- end[colIndex] = cellPart.end;
+ int colIndex = cellPart.pgu.getColIndex();
+ if (firstCellParts[colIndex] == null) {
+ firstCellParts[colIndex] = cellPart;
+ cellHeights[colIndex] = cellPart.getBorderPaddingBefore(firstCellOnPage[colIndex]);
} else {
- if (cellPart.end < end[colIndex]) {
- throw new IllegalStateException("Internal Error: stepper problem");
- }
- end[colIndex] = cellPart.end;
+ assert firstCellParts[colIndex].pgu == cellPart.pgu;
+ cellHeights[colIndex] += cellPart.getConditionalBeforeContentLength();
}
+ cellHeights[colIndex] += cellPart.getLength();
+ lastCellParts[colIndex] = cellPart;
}
}
/**
- * Create the areas corresponding to the last row. This method is called either
- * because the row is finished (all of the elements present on this row have been
- * added), or because this is the last row on the current page, and the part of it
- * lying on the current page must be drawn.
+ * Creates the areas corresponding to the last row. That is, an area with background
+ * for the row, plus areas for all the cells that finish on the row (not spanning over
+ * further rows).
*
- * @param forcedFlush true if the elements must be drawn even if the row isn't
- * finished yet (last row on the page), or if the row is the last of the current table
- * part
- * @return the height of the (grid) row
+ * @param lastInPart true if the row is the last from its table part to be displayed
+ * on the current page. In which case all the cells must be flushed even if they
+ * aren't finished, plus the proper collapsed borders must be selected (trailing
+ * instead of normal, or rest if the cell is unfinished)
+ * @param lastOnPage true if the row is the very last row of the table that will be
+ * displayed on the current page. In which case collapsed after borders must be drawn
+ * in the outer mode
*/
- int addAreasAndFlushRow(boolean forcedFlush) {
- int actualRowHeight = 0;
-
+ void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) {
if (log.isDebugEnabled()) {
- log.debug("Remembering yoffset for row " + lastRow.getIndex() + ": " + yoffset);
+ log.debug("Remembering yoffset for row " + currentRow.getIndex() + ": "
+ + currentRowOffset);
}
- recordRowOffset(lastRow.getIndex(), yoffset);
+ recordRowOffset(currentRow.getIndex(), currentRowOffset);
- for (int i = 0; i < primaryGridUnits.length; i++) {
- if ((primaryGridUnits[i] != null)
- && (forcedFlush || (end[i] == primaryGridUnits[i].getElements().size() - 1))) {
- actualRowHeight = Math.max(actualRowHeight, computeSpanHeight(
- primaryGridUnits[i], start[i], end[i], i));
+ // Need to compute the actual row height first
+ int actualRowHeight = 0;
+ for (int i = 0; i < colCount; i++) {
+ GridUnit currentGU = currentRow.getGridUnit(i);
+ if (!currentGU.isEmpty() && 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);
}
}
- actualRowHeight += 2 * tclm.getTableLM().getHalfBorderSeparationBPD();
- //Add areas for row
- tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(), yoffset);
- for (int i = 0; i < primaryGridUnits.length; i++) {
- GridUnit currentGU = lastRow.getGridUnit(i);
+ // Then add areas for cells finishing on the current row
+ tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(),
+ currentRowOffset);
+ for (int i = 0; i < colCount; i++) {
+ GridUnit currentGU = currentRow.getGridUnit(i);
if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0
- && (forcedFlush || currentGU.isLastGridUnitRowSpan())) {
- addAreasForCell(currentGU.getPrimary(), start[i], end[i], lastRow, partBPD[i],
- actualRowHeight);
- primaryGridUnits[i] = null;
- start[i] = 0;
- end[i] = -1;
- partBPD[i] = 0;
+ && (lastInPart || currentGU.isLastGridUnitRowSpan())
+ && firstCellParts[i] != null) {
+ assert firstCellParts[i].pgu == currentGU.getPrimary();
+ int borderBeforeWhich;
+ if (firstCellParts[i].start == 0) {
+ 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;
+ }
+ addAreasForCell(firstCellParts[i].pgu,
+ firstCellParts[i].start, lastCellParts[i].end,
+ actualRowHeight, borderBeforeWhich, borderAfterWhich,
+ lastOnPage);
+ firstCellParts[i] = null;
+ firstCellOnPage[i] = false;
}
}
- yoffset += actualRowHeight;
- accumulatedBPD += actualRowHeight;
- if (forcedFlush) {
- // Either the end of the page is reached, then this was the last call of this
- // method and we no longer care about lastRow; 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 recall this
- // method in the first lines of handleTableContentPosition, so we may reset
- // the following variables
- lastRow = null;
+ 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;
}
- return actualRowHeight;
}
- /**
- * Computes the total height of the part of the given cell spanning on the current
- * active row, including borders and paddings. The bpd is also stored in partBPD, and
- * it is ensured that the cell's or row's explicit height is respected. yoffset is
- * updated accordingly.
- *
- * @param pgu primary grid unit corresponding to the cell
- * @param start index of the first element of the cell occuring on the current page
- * @param end index of the last element of the cell occuring on the current page
- * @param columnIndex column index of the cell
- * @param bodyType {@link TableRowIterator#HEADER}, {@link TableRowIterator#FOOTER}, or
- * {@link TableRowIterator#BODY}
- * @return the cell's height
- */
- private int computeSpanHeight(PrimaryGridUnit pgu, int start, int end, int columnIndex) {
- if (log.isTraceEnabled()) {
- log.trace("getting len for " + columnIndex + " "
- + start + "-" + end);
- }
- int actualStart = start;
- // Skip from the content length calculation glues and penalties occuring at the
- // beginning of the page
- while (actualStart <= end && !((KnuthElement)pgu.getElements().get(actualStart)).isBox()) {
- actualStart++;
- }
- int len = ElementListUtils.calcContentLength(
- pgu.getElements(), actualStart, end);
- KnuthElement el = (KnuthElement)pgu.getElements().get(end);
- if (el.isPenalty()) {
- len += el.getW();
- }
- partBPD[columnIndex] = len;
- if (log.isTraceEnabled()) {
- log.trace("len of part: " + len);
- }
-
- if (start == 0) {
- LengthRangeProperty bpd = pgu.getCell()
- .getBlockProgressionDimension();
- if (!bpd.getMinimum(tclm.getTableLM()).isAuto()) {
- int min = bpd.getMinimum(tclm.getTableLM())
- .getLength().getValue(tclm.getTableLM());
- if (min > 0) {
- len = Math.max(len, min);
- }
- }
- if (!bpd.getOptimum(tclm.getTableLM()).isAuto()) {
- int opt = bpd.getOptimum(tclm.getTableLM())
- .getLength().getValue(tclm.getTableLM());
- if (opt > 0) {
- len = Math.max(len, opt);
- }
+ // TODO this is not very efficient and should probably be done another way
+ // this method is only necessary when display-align = center or after, in which case
+ // the exact content length is needed to compute the size of the empty block that will
+ // be used as padding.
+ // This should be handled automatically by a proper use of Knuth elements
+ private int computeContentLength(PrimaryGridUnit pgu, int startIndex, int endIndex) {
+ if (startIndex > endIndex) {
+ // May happen if the cell contributes no content on the current page (empty
+ // cell, in most cases)
+ return 0;
+ } else {
+ int actualStart = startIndex;
+ // Skip from the content length calculation glues and penalties occurring at the
+ // beginning of the page
+ while (actualStart <= endIndex
+ && !((KnuthElement) pgu.getElements().get(actualStart)).isBox()) {
+ actualStart++;
}
- if (pgu.getRow() != null) {
- bpd = pgu.getRow().getBlockProgressionDimension();
- if (!bpd.getMinimum(tclm.getTableLM()).isAuto()) {
- int min = bpd.getMinimum(tclm.getTableLM()).getLength()
- .getValue(tclm.getTableLM());
- if (min > 0) {
- len = Math.max(len, min);
- }
- }
+ int len = ElementListUtils.calcContentLength(
+ pgu.getElements(), actualStart, endIndex);
+ KnuthElement el = (KnuthElement)pgu.getElements().get(endIndex);
+ if (el.isPenalty()) {
+ len += el.getW();
}
+ return len;
}
-
- // Add the padding if any
- len += pgu.getBorders()
- .getPaddingBefore(false, pgu.getCellLM());
- len += pgu.getBorders()
- .getPaddingAfter(false, pgu.getCellLM());
-
- //Now add the borders to the contentLength
- if (tclm.isSeparateBorderModel()) {
- len += pgu.getBorders().getBorderBeforeWidth(false);
- len += pgu.getBorders().getBorderAfterWidth(false);
- } else {
- len += pgu.getHalfMaxBeforeBorderWidth();
- len += pgu.getHalfMaxAfterBorderWidth();
- }
- int cellOffset = getRowOffset(Math.max(pgu.getStartRow(), firstRowIndex));
- len -= yoffset - cellOffset;
- return len;
}
private void addAreasForCell(PrimaryGridUnit pgu, int startPos, int endPos,
- EffRow row, int contentHeight, int rowHeight) {
- //Determine the first row in this sequence
- int startRowIndex = Math.max(pgu.getStartRow(), firstRowIndex);
- int lastRowIndex = lastRow.getIndex();
-
- // In collapsing-border model, if the cell spans over several columns/rows then
- // dedicated areas will be created for each grid unit to hold the corresponding
- // borders. For that we need to know the height of each grid unit, that is of each
- // grid row spanned over by the cell
+ int rowHeight, int borderBeforeWhich, int borderAfterWhich, boolean lastOnPage) {
+ /*
+ * Determine the index of the first row of this cell that will be displayed on the
+ * current page.
+ */
+ int startRowIndex = Math.max(pgu.getRowIndex(), firstRowIndex);
+ int currentRowIndex = currentRow.getIndex();
+
+ /*
+ * In collapsing-border model, if the cell spans over several columns/rows then
+ * dedicated areas will be created for each grid unit to hold the corresponding
+ * borders. For that we need to know the height of each grid unit, that is of each
+ * grid row spanned over by the cell
+ */
int[] spannedGridRowHeights = null;
if (!tclm.getTableLM().getTable().isSeparateBorderModel() && pgu.hasSpanning()) {
- spannedGridRowHeights = new int[lastRowIndex - startRowIndex + 1];
+ spannedGridRowHeights = new int[currentRowIndex - startRowIndex + 1];
int prevOffset = getRowOffset(startRowIndex);
- for (int i = 0; i < lastRowIndex - startRowIndex; i++) {
+ for (int i = 0; i < currentRowIndex - startRowIndex; i++) {
int newOffset = getRowOffset(startRowIndex + i + 1);
spannedGridRowHeights[i] = newOffset - prevOffset;
prevOffset = newOffset;
}
- spannedGridRowHeights[lastRowIndex - startRowIndex] = rowHeight;
+ spannedGridRowHeights[currentRowIndex - startRowIndex] = rowHeight;
}
-
int cellOffset = getRowOffset(startRowIndex);
- int effCellHeight = rowHeight;
- effCellHeight += yoffset - cellOffset;
+ int cellTotalHeight = rowHeight + currentRowOffset - cellOffset;
if (log.isDebugEnabled()) {
log.debug("Creating area for cell:");
- log.debug(" current row: " + row.getIndex());
- log.debug(" start row: " + pgu.getStartRow() + " " + yoffset + " " + cellOffset);
- log.debug(" contentHeight: " + contentHeight + " rowHeight=" + rowHeight
- + " effCellHeight=" + effCellHeight);
+ log.debug(" start row: " + pgu.getRowIndex() + " " + currentRowOffset + " "
+ + cellOffset);
+ log.debug(" rowHeight=" + rowHeight + " cellTotalHeight=" + cellTotalHeight);
}
TableCellLayoutManager cellLM = pgu.getCellLM();
cellLM.setXOffset(tclm.getXOffsetOfGridUnit(pgu));
cellLM.setYOffset(cellOffset);
- cellLM.setContentHeight(contentHeight);
- cellLM.setRowHeight(effCellHeight);
- //cellLM.setRowHeight(row.getHeight().opt);
+ cellLM.setContentHeight(computeContentLength(pgu, startPos, endPos));
+ cellLM.setTotalHeight(cellTotalHeight);
int prevBreak = ElementListUtils.determinePreviousBreak(pgu.getElements(), startPos);
if (endPos >= 0) {
SpaceResolver.performConditionalsNotification(pgu.getElements(),
startPos, endPos, prevBreak);
}
cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(), startPos, endPos + 1),
- layoutContext, spannedGridRowHeights, startRowIndex - pgu.getStartRow(),
- lastRowIndex - pgu.getStartRow() + 1);
+ layoutContext, spannedGridRowHeights, startRowIndex - pgu.getRowIndex(),
+ currentRowIndex - pgu.getRowIndex(), borderBeforeWhich, borderAfterWhich,
+ startRowIndex == firstRowOnPageIndex, lastOnPage);
}
/**
@@ -342,7 +337,7 @@
* TableContentPosition will be created for this row. Thus its index will never be
* recorded by the #handleTableContentPosition method.
*
- * The yoffset for such a row is the same as the next non-empty row. It's needed
+ * The offset of such a row is the same as the next non-empty row. It's needed
* to correctly offset blocks for cells starting on this row. Hence the loop
* below.
*/
@@ -359,5 +354,15 @@
*/
private int getRowOffset(int rowIndex) {
return ((Integer) rowOffsets.get(rowIndex - firstRowIndex)).intValue();
+ }
+
+ // TODO get rid of that
+ void startBody() {
+ Arrays.fill(firstCellOnPage, true);
+ }
+
+ // TODO get rid of that
+ void endBody() {
+ Arrays.fill(firstCellOnPage, false);
}
}
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Feb 14 13:55:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Feb 14 13:55:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java?rev=627882&r1=627881&r2=627882&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java Thu Feb 14 13:55:44 2008
@@ -28,11 +28,13 @@
import org.apache.fop.area.Trait;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.flow.table.ConditionalBorder;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
import org.apache.fop.layoutmgr.AreaAdditionUtil;
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
@@ -47,6 +49,7 @@
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.SpaceResolver;
import org.apache.fop.layoutmgr.TraitSetter;
+import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.MinOptMax;
/**
@@ -65,8 +68,6 @@
private Block curBlockArea;
- private int inRowIPDOffset;
-
private int xoffset;
private int yoffset;
private int cellIPD;
@@ -137,7 +138,8 @@
startIndent /= 2;
endIndent /= 2;
}
- startIndent += getTableCell().getCommonBorderPaddingBackground().getPaddingStart(false, this);
+ startIndent += getTableCell().getCommonBorderPaddingBackground().getPaddingStart(false,
+ this);
endIndent += getTableCell().getCommonBorderPaddingBackground().getPaddingEnd(false, this);
return startIndent + endIndent;
}
@@ -208,7 +210,7 @@
// with a SpaceResolver.SpaceHandlingBreakPosition element, having no
// LM associated to it. Thus it will stop early instead of adding
// areas for following Positions. The above test aims at preventing
- // such a situation from occuring. add a null penalty to allow a break
+ // such a situation from occurring. add a null penalty to allow a break
// between blocks
contentList.add(new BreakElement(
new Position(this), 0, context));
@@ -244,6 +246,16 @@
}
//Space resolution
SpaceResolver.resolveElementList(returnList);
+ if (((KnuthElement) returnList.getFirst()).isForcedBreak()) {
+ primaryGridUnit.setBreakBefore(((KnuthPenalty) returnList.getFirst()).getBreakClass());
+ returnList.removeFirst();
+ assert !returnList.isEmpty();
+ }
+ if (((KnuthElement) returnList.getLast()).isForcedBreak()) {
+ KnuthPenalty p = (KnuthPenalty) returnList.getLast();
+ primaryGridUnit.setBreakAfter(p.getBreakClass());
+ p.setP(0);
+ }
getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId());
@@ -272,15 +284,6 @@
}
/**
- * Set the IPD offset of this cell inside the table-row.
- * This offset is used to determine the absolute position of the cell.
- * @param off the IPD offset
- */
- public void setInRowIPDOffset(int off) {
- this.inRowIPDOffset = off;
- }
-
- /**
* Set the content height for this cell. This method is used during
* addAreas() stage.
*
@@ -291,37 +294,16 @@
}
/**
- * Set the row height that contains this cell. This method is used during
- * addAreas() stage.
- *
- * @param h the height of the row
+ * Sets the total height of this cell on the current page. That is, the cell's bpd
+ * plus before and after borders and paddings, plus the table's border-separation.
+ *
+ * @param h the height of cell
*/
- public void setRowHeight(int h) {
+ public void setTotalHeight(int h) {
rowHeight = h;
}
/**
- * Returns the bpd of the given grid unit.
- * @param gu a grid unit belonging to this cell
- * @return the content height of the grid unit
- */
- private int getContentHeight(GridUnit gu) {
- int bpd = rowHeight;
- if (isSeparateBorderModel()) {
- bpd -= gu.getPrimary().getBorders().getBorderBeforeWidth(false);
- bpd -= gu.getPrimary().getBorders().getBorderAfterWidth(false);
- } else {
- bpd -= gu.getPrimary().getHalfMaxBorderWidth();
- }
- CommonBorderPaddingBackground cbpb
- = gu.getCell().getCommonBorderPaddingBackground();
- bpd -= cbpb.getPaddingBefore(false, this);
- bpd -= cbpb.getPaddingAfter(false, this);
- bpd -= 2 * ((TableLayoutManager)getParent()).getHalfBorderSeparationBPD();
- return bpd;
- }
-
- /**
* Add the areas for the break points. The cell contains block stacking layout
* managers that add block areas.
*
@@ -336,99 +318,151 @@
* of each spanned grid row
* @param startRow first grid row on the current page spanned over by the cell,
* inclusive
- * @param endRow last grid row on the current page spanned over by the cell, exclusive
+ * @param endRow last grid row on the current page spanned over by the cell, inclusive
+ * @param borderBeforeWhich one of {@link ConditionalBorder#NORMAL},
+ * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST}
+ * @param borderAfterWhich one of {@link ConditionalBorder#NORMAL},
+ * {@link ConditionalBorder#LEADING_TRAILING} or {@link ConditionalBorder#REST}
+ * @param firstOnPage true if the cell will be the very first one on the page, in
+ * which case collapsed before borders must be drawn in the outer mode
+ * @param lastOnPage true if the cell will be the very last one on the page, in which
+ * case collapsed after borders must be drawn in the outer mode
*/
public void addAreas(PositionIterator parentIter,
LayoutContext layoutContext,
int[] spannedGridRowHeights,
int startRow,
- int endRow) {
+ int endRow,
+ int borderBeforeWhich,
+ int borderAfterWhich,
+ boolean firstOnPage,
+ boolean lastOnPage) {
getParentArea(null);
getPSLM().addIDToPage(getTableCell().getId());
+ int borderBeforeWidth = primaryGridUnit.getBeforeBorderWidth(startRow, borderBeforeWhich);
+ int borderAfterWidth = primaryGridUnit.getAfterBorderWidth(endRow, borderAfterWhich);
if (isSeparateBorderModel()) {
if (!emptyCell || getTableCell().showEmptyCells()) {
- TraitSetter.addBorders(curBlockArea, getTableCell().getCommonBorderPaddingBackground(),
- false, false, false, false, this);
- TraitSetter.addPadding(curBlockArea, getTableCell().getCommonBorderPaddingBackground(),
- false, false, false, false, this);
+ if (borderBeforeWidth > 0) {
+ int halfBorderSepBPD = getTableCell().getTable().getBorderSeparation().getBPD()
+ .getLength().getValue() / 2;
+ adjustYOffset(curBlockArea, halfBorderSepBPD);
+ }
+ TraitSetter.addBorders(curBlockArea,
+ getTableCell().getCommonBorderPaddingBackground(),
+ borderBeforeWidth == 0, borderAfterWidth == 0,
+ false, false, this);
}
} else {
+ boolean inFirstColumn = (primaryGridUnit.getColIndex() == 0);
+ boolean inLastColumn = (primaryGridUnit.getColIndex()
+ + getTableCell().getNumberColumnsSpanned() == getTable()
+ .getNumberOfColumns());
if (!primaryGridUnit.hasSpanning()) {
+ adjustYOffset(curBlockArea, -borderBeforeWidth);
//Can set the borders directly if there's no span
- boolean[] outer = new boolean[] {
- primaryGridUnit.getFlag(GridUnit.FIRST_IN_TABLE),
- primaryGridUnit.getFlag(GridUnit.LAST_IN_TABLE),
- primaryGridUnit.getFlag(GridUnit.IN_FIRST_COLUMN),
- primaryGridUnit.getFlag(GridUnit.IN_LAST_COLUMN)};
+ boolean[] outer = new boolean[] {firstOnPage, lastOnPage, inFirstColumn,
+ inLastColumn};
TraitSetter.addCollapsingBorders(curBlockArea,
- primaryGridUnit.getBorders(), outer, this);
+ primaryGridUnit.getBorderBefore(borderBeforeWhich),
+ primaryGridUnit.getBorderAfter(borderAfterWhich),
+ primaryGridUnit.getBorderStart(),
+ primaryGridUnit.getBorderEnd(), outer);
} else {
- boolean[] outer = new boolean[4];
+ adjustYOffset(curBlockArea, borderBeforeWidth);
+ Block[][] blocks = new Block[getTableCell().getNumberRowsSpanned()][getTableCell()
+ .getNumberColumnsSpanned()];
+ GridUnit[] gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(startRow);
+ for (int x = 0; x < getTableCell().getNumberColumnsSpanned(); x++) {
+ GridUnit gu = gridUnits[x];
+ BorderInfo border = gu.getBorderBefore(borderBeforeWhich);
+ int borderWidth = border.getRetainedWidth() / 2;
+ if (borderWidth > 0) {
+ addBorder(blocks, startRow, x, Trait.BORDER_BEFORE, border, firstOnPage);
+ adjustYOffset(blocks[startRow][x], -borderWidth);
+ adjustBPD(blocks[startRow][x], -borderWidth);
+ }
+ }
+ gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(endRow);
+ for (int x = 0; x < getTableCell().getNumberColumnsSpanned(); x++) {
+ GridUnit gu = gridUnits[x];
+ BorderInfo border = gu.getBorderAfter(borderAfterWhich);
+ int borderWidth = border.getRetainedWidth() / 2;
+ if (borderWidth > 0) {
+ addBorder(blocks, endRow, x, Trait.BORDER_AFTER, border, lastOnPage);
+ adjustBPD(blocks[endRow][x], -borderWidth);
+ }
+ }
+ for (int y = startRow; y <= endRow; y++) {
+ gridUnits = (GridUnit[]) primaryGridUnit.getRows().get(y);
+ BorderInfo border = gridUnits[0].getBorderStart();
+ int borderWidth = border.getRetainedWidth() / 2;
+ if (borderWidth > 0) {
+ addBorder(blocks, y, 0, Trait.BORDER_START, border, inFirstColumn);
+ adjustXOffset(blocks[y][0], borderWidth);
+ adjustIPD(blocks[y][0], -borderWidth);
+ }
+ border = gridUnits[gridUnits.length - 1].getBorderEnd();
+ borderWidth = border.getRetainedWidth() / 2;
+ if (borderWidth > 0) {
+ addBorder(blocks, y, gridUnits.length - 1, Trait.BORDER_END, border,
+ inLastColumn);
+ adjustIPD(blocks[y][gridUnits.length - 1], -borderWidth);
+ }
+ }
int dy = yoffset;
- for (int y = startRow; y < endRow; y++) {
- GridUnit[] gridUnits = (GridUnit[])primaryGridUnit.getRows().get(y);
+ for (int y = startRow; y <= endRow; y++) {
+ int bpd = spannedGridRowHeights[y - startRow];
int dx = xoffset;
for (int x = 0; x < gridUnits.length; x++) {
- GridUnit gu = gridUnits[x];
- if (gu.hasBorders()) {
- //Blocks for painting grid unit borders
- Block block = new Block();
- block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
- block.setPositioning(Block.ABSOLUTE);
-
- int bpd = spannedGridRowHeights[y - startRow];
- bpd -= gu.getBorders().getBorderBeforeWidth(false) / 2;
- bpd -= gu.getBorders().getBorderAfterWidth(false) / 2;
- block.setBPD(bpd);
- if (log.isTraceEnabled()) {
- log.trace("pgu: " + primaryGridUnit + "; gu: " + gu + "; yoffset: "
- + (dy - gu.getBorders().getBorderBeforeWidth(false) / 2)
- + "; bpd: " + bpd);
- }
- int ipd = gu.getColumn().getColumnWidth().getValue(
- (PercentBaseContext) getParent());
- int borderStartWidth = gu.getBorders().getBorderStartWidth(false) / 2;
- ipd -= borderStartWidth;
- ipd -= gu.getBorders().getBorderEndWidth(false) / 2;
- block.setIPD(ipd);
- block.setXOffset(dx + borderStartWidth);
- block.setYOffset(dy - gu.getBorders().getBorderBeforeWidth(false) / 2);
- outer[0] = gu.getFlag(GridUnit.FIRST_IN_TABLE);
- outer[1] = gu.getFlag(GridUnit.LAST_IN_TABLE);
- outer[2] = gu.getFlag(GridUnit.IN_FIRST_COLUMN);
- outer[3] = gu.getFlag(GridUnit.IN_LAST_COLUMN);
- TraitSetter.addCollapsingBorders(block, gu.getBorders(), outer, this);
+ int ipd = getTable().getColumn(primaryGridUnit.getColIndex() + x)
+ .getColumnWidth().getValue((PercentBaseContext) getParent());
+ if (blocks[y][x] != null) {
+ Block block = blocks[y][x];
+ adjustYOffset(block, dy);
+ adjustXOffset(block, dx);
+ adjustIPD(block, ipd);
+ adjustBPD(block, bpd);
parentLM.addChildArea(block);
}
- dx += gu.getColumn().getColumnWidth().getValue(
- (PercentBaseContext) getParent());
+ dx += ipd;
}
- dy += spannedGridRowHeights[y - startRow];
+ dy += bpd;
}
}
}
- TraitSetter.addPadding(curBlockArea, primaryGridUnit.getBorders(),
- false, false, false, false, this);
+
+ CommonBorderPaddingBackground padding = primaryGridUnit.getCell()
+ .getCommonBorderPaddingBackground();
+ TraitSetter.addPadding(curBlockArea,
+ padding,
+ borderBeforeWhich == ConditionalBorder.REST,
+ borderAfterWhich == ConditionalBorder.REST,
+ false, false, this);
+
+ int cellBPD = rowHeight - borderBeforeWidth - borderAfterWidth;
+ cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this);
+ cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this);
//Handle display-align
- int contentBPD = getContentHeight(primaryGridUnit);
- if (usedBPD < contentBPD) {
+ if (usedBPD < cellBPD) {
if (getTableCell().getDisplayAlign() == EN_CENTER) {
Block space = new Block();
- space.setBPD((contentBPD - usedBPD) / 2);
+ space.setBPD((cellBPD - usedBPD) / 2);
curBlockArea.addBlock(space);
} else if (getTableCell().getDisplayAlign() == EN_AFTER) {
Block space = new Block();
- space.setBPD((contentBPD - usedBPD));
+ space.setBPD(cellBPD - usedBPD);
curBlockArea.addBlock(space);
}
}
AreaAdditionUtil.addAreas(this, parentIter, layoutContext);
-
- curBlockArea.setBPD(contentBPD);
+ // Re-adjust the cell's bpd as it may have been modified by the previous call
+ // for some reason (?)
+ curBlockArea.setBPD(cellBPD);
// Add background after we know the BPD
if (isSeparateBorderModel()) {
@@ -448,6 +482,34 @@
curBlockArea = null;
}
+ private void addBorder(Block[][] blocks, int i, int j, Integer side, BorderInfo border,
+ boolean outer) {
+ if (blocks[i][j] == null) {
+ blocks[i][j] = new Block();
+ blocks[i][j].addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
+ blocks[i][j].setPositioning(Block.ABSOLUTE);
+ }
+ blocks[i][j].addTrait(side, new BorderProps(border.getStyle(),
+ border.getRetainedWidth(), border.getColor(),
+ outer ? BorderProps.COLLAPSE_OUTER : BorderProps.COLLAPSE_INNER));
+ }
+
+ private static void adjustXOffset(Block block, int amount) {
+ block.setXOffset(block.getXOffset() + amount);
+ }
+
+ private static void adjustYOffset(Block block, int amount) {
+ block.setYOffset(block.getYOffset() + amount);
+ }
+
+ private static void adjustIPD(Block block, int amount) {
+ block.setIPD(block.getIPD() + amount);
+ }
+
+ private static void adjustBPD(Block block, int amount) {
+ block.setBPD(block.getBPD() + amount);
+ }
+
/**
* Return an Area which can contain the passed childArea. The childArea
* may not yet have any content, but it has essential traits set.
@@ -467,25 +529,10 @@
curBlockArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
TraitSetter.setProducerID(curBlockArea, getTableCell().getId());
curBlockArea.setPositioning(Block.ABSOLUTE);
- // set position
- int borderAdjust = 0;
- if (!isSeparateBorderModel()) {
- if (primaryGridUnit.hasSpanning()) {
- borderAdjust -= primaryGridUnit.getHalfMaxBeforeBorderWidth();
- } else {
- borderAdjust += primaryGridUnit.getHalfMaxBeforeBorderWidth();
- }
- } else {
- //borderAdjust += primaryGridUnit.getBorders().getBorderBeforeWidth(false);
- }
- TableLayoutManager tableLM = (TableLayoutManager)getParent();
- curBlockArea.setXOffset(xoffset + inRowIPDOffset + startIndent);
- curBlockArea.setYOffset(yoffset - borderAdjust
- + tableLM.getHalfBorderSeparationBPD());
+ curBlockArea.setXOffset(xoffset + startIndent);
+ curBlockArea.setYOffset(yoffset);
curBlockArea.setIPD(cellIPD);
- //curBlockArea.setHeight();
- // Set up dimensions
/*Area parentArea =*/ parentLM.getParentArea(curBlockArea);
// Get reference IPD from parentArea
setCurrentArea(curBlockArea); // ??? for generic operations
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Feb 14 13:55:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java?rev=627882&r1=627881&r2=627882&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java Thu Feb 14 13:55:44 2008
@@ -19,6 +19,7 @@
package org.apache.fop.layoutmgr.table;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -32,7 +33,7 @@
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.table.EffRow;
-import org.apache.fop.fo.flow.table.GridUnit;
+import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableRow;
@@ -47,6 +48,7 @@
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition;
+import org.apache.fop.util.BreakUtil;
/**
* Layout manager for table contents, particularly managing the creation of combined element lists.
@@ -68,7 +70,7 @@
private int startXOffset;
private int usedBPD;
- private TableStepper stepper = new TableStepper(this);
+ private TableStepper stepper;
/**
* Main constructor
@@ -84,6 +86,7 @@
if (table.getTableFooter() != null) {
footerIter = new TableRowIterator(table, TableRowIterator.FOOTER);
}
+ stepper = new TableStepper(this);
}
/**
@@ -125,7 +128,7 @@
return this.footerList;
}
- /** @see org.apache.fop.layoutmgr.LayoutManager#getNextKnuthElements(LayoutContext, int) */
+ /** {@inheritDoc} */
public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
if (log.isDebugEnabled()) {
log.debug("==> Columns: " + getTableLM().getColumns());
@@ -210,10 +213,14 @@
while ((rowGroup = iter.getNextRowGroup()) != null) {
RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup,
stepper);
- if (breakBetween == Constants.EN_AUTO) {
- // TODO improve
- breakBetween = rowGroupLM.getBreakBefore();
- }
+ // TODO
+ // The RowGroupLM.getBreakBefore method will work correctly only after
+ // getNextKnuthElements is called. Indeed TableCellLM will set the values for
+ // breaks on PrimaryGridUnit once it has got the Knuth elements of its
+ // children. This can be changed once all the LMs adopt the same scheme of
+ // querying childrens LMs for breaks instead of producing penalty elements
+ List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType);
+ breakBetween = BreakUtil.compareBreakClasses(breakBetween, rowGroupLM.getBreakBefore());
if (breakBetween != Constants.EN_AUTO) {
if (returnList.size() > 0) {
BreakElement breakPoss = (BreakElement) returnList.getLast();
@@ -224,7 +231,7 @@
0, -KnuthPenalty.INFINITE, breakBetween, context));
}
}
- returnList.addAll(rowGroupLM.getNextKnuthElements(context, alignment, bodyType));
+ returnList.addAll(nextRowGroupElems);
breakBetween = rowGroupLM.getBreakAfter();
}
// Break after the table's last row
@@ -271,8 +278,8 @@
* @param gu the grid unit
* @return the requested X offset
*/
- protected int getXOffsetOfGridUnit(GridUnit gu) {
- int col = gu.getStartCol();
+ protected int getXOffsetOfGridUnit(PrimaryGridUnit gu) {
+ int col = gu.getColIndex();
return startXOffset + getTableLM().getColumns().getXOffset(col + 1, getTableLM());
}
@@ -321,9 +328,12 @@
} else if (pos instanceof TableHFPenaltyPosition) {
//ignore for now, see special handling below if break is at a penalty
//Only if the last position in this part/page us such a position it will be used
- } else {
- //leave order as is for the rest
+ } else if (pos instanceof TableContentPosition) {
positions.add(pos);
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Ignoring position: " + pos);
+ }
}
}
if (lastPos instanceof TableHFPenaltyPosition) {
@@ -349,17 +359,20 @@
//header positions for the last part are the second-to-last element and need to
//be handled first before all other TableContentPositions
PositionIterator nestedIter = new KnuthPossPosIter(headerElements);
- iterateAndPaintPositions(nestedIter, painter);
+ iterateAndPaintPositions(nestedIter, painter, false);
}
//Iterate over all steps
Iterator posIter = positions.iterator();
- iterateAndPaintPositions(posIter, painter);
+ painter.startBody();
+ // Here we are sure that posIter iterates only over TableContentPosition instances
+ iterateAndPaintPositions(posIter, painter, footerElements == null);
+ painter.endBody();
if (footerElements != null) {
//Positions for footers are simply added at the end
PositionIterator nestedIter = new KnuthPossPosIter(footerElements);
- iterateAndPaintPositions(nestedIter, painter);
+ iterateAndPaintPositions(nestedIter, painter, true);
}
this.usedBPD += painter.getAccumulatedBPD();
@@ -377,9 +390,12 @@
* @param iterator iterator over Position elements. Those positions correspond to the
* elements of the table present on the current page
* @param painter
+ * @param lastOnPage true if the corresponding part will be the last on the page
+ * (either body or footer, obviously)
*/
- private void iterateAndPaintPositions(Iterator iterator, RowPainter painter) {
- List lst = new java.util.ArrayList();
+ private void iterateAndPaintPositions(Iterator iterator, RowPainter painter,
+ boolean lastOnPage) {
+ List lst = new ArrayList();
boolean firstPos = false;
TableBody body = null;
while (iterator.hasNext()) {
@@ -392,12 +408,12 @@
body = part.pgu.getBody();
}
if (tcpos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP)
- && tcpos.row.getFlag(EffRow.FIRST_IN_PART)) {
+ && tcpos.getRow().getFlag(EffRow.FIRST_IN_PART)) {
firstPos = true;
}
if (tcpos.getFlag(TableContentPosition.LAST_IN_ROWGROUP)
- && tcpos.row.getFlag(EffRow.LAST_IN_PART)) {
+ && tcpos.getRow().getFlag(EffRow.LAST_IN_PART)) {
log.trace("LAST_IN_ROWGROUP + LAST_IN_PART");
handleMarkersAndPositions(lst, body, firstPos, true, painter);
//reset
@@ -405,10 +421,6 @@
body = null;
lst.clear();
}
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Ignoring position: " + pos);
- }
}
}
if (body != null) {
@@ -417,7 +429,7 @@
// lastPos is necessarily false
handleMarkersAndPositions(lst, body, firstPos, false, painter);
}
- painter.addAreasAndFlushRow(true);
+ painter.addAreasAndFlushRow(true, lastOnPage);
}
private void handleMarkersAndPositions(List positions, TableBody body, boolean firstPos,
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Feb 14 13:55:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java?rev=627882&r1=627881&r2=627882&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java Thu Feb 14 13:55:44 2008
@@ -39,10 +39,12 @@
/** the list of CellParts making up this position */
protected List cellParts;
/** effective row this position belongs to */
- protected EffRow row;
+ private EffRow row;
/** flags for the position */
protected int flags;
+ private EffRow newPageRow;
+
/**
* Creates a new TableContentPosition.
* @param lm applicable layout manager
@@ -54,6 +56,27 @@
super(lm);
this.cellParts = cellParts;
this.row = row;
+ this.newPageRow = row;
+ }
+
+ /**
+ * Sets the row corresponding to this position if it starts a new page. In which case,
+ * if the delay mechanism is on, this is the delayed row that starts the page, and not
+ * the current row being extended.
+ *
+ * @param newPageRow the row that will start the page if this position is the first
+ * one on that page
+ */
+ void setNewPageRow(EffRow newPageRow) {
+ this.newPageRow = newPageRow;
+ }
+
+ EffRow getNewPageRow() {
+ return newPageRow;
+ }
+
+ EffRow getRow() {
+ return row;
}
/**
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Feb 14 13:55:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableRowIterator.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Feb 14 13:55:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableStepper.java?rev=627882&r1=627881&r2=627882&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableStepper.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableStepper.java Thu Feb 14 13:55:44 2008
@@ -26,17 +26,16 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.Constants;
-import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
-import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.KnuthPenalty;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.util.BreakUtil;
/**
* This class processes row groups to create combined element lists for tables.
@@ -52,50 +51,69 @@
/** Number of columns in the row group. */
private int columnCount;
private int totalHeight;
- private int previousRowsLength = 0;
+ private int previousRowsLength;
private int activeRowIndex;
- private boolean rowBacktrackForLastStep;
- private boolean skippedStep;
+ private boolean rowFinished;
+
+ /** Cells spanning the current row. */
private List activeCells = new LinkedList();
+ /** Cells that will start the next row. */
+ private List nextActiveCells = new LinkedList();
+
/**
- * Main constructor
- * @param tclm The parent TableContentLayoutManager
+ * True if the next row is being delayed, that is, if cells spanning the current and
+ * the next row have steps smaller than the next row's first step. In this case the
+ * next row may be extended to offer additional break possibilities.
*/
- public TableStepper(TableContentLayoutManager tclm) {
- this.tclm = tclm;
- }
+ private boolean delayingNextRow;
/**
- * Initializes the fields of this instance to handle a new row group.
+ * The first step for a row. This is the minimal step necessary to include some
+ * content from all the cells starting the row.
+ */
+ private int rowFirstStep;
+
+ /**
+ * Flag used to produce an infinite penalty if the height of the current row is
+ * smaller than the first step for that row (may happen with row-spanning cells).
*
- * @param columnCount number of columns the row group has
+ * @see #considerRowLastStep(int)
*/
- private void setup(int columnCount) {
- this.columnCount = columnCount;
- this.activeRowIndex = 0;
- this.previousRowsLength = 0;
- }
+ private boolean rowHeightSmallerThanFirstStep;
/**
- * Returns the row currently being processed.
- *
- * @return the row currently being processed
+ * The class of the next break. One of {@link Constants#EN_AUTO},
+ * {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE},
+ * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}. Defaults to
+ * EN_AUTO.
*/
- private EffRow getActiveRow() {
- return rowGroup[activeRowIndex];
+ private int nextBreakClass;
+
+ /**
+ * Main constructor
+ * @param tclm The parent TableContentLayoutManager
+ */
+ public TableStepper(TableContentLayoutManager tclm) {
+ this.tclm = tclm;
+ this.columnCount = tclm.getTableLM().getTable().getNumberOfColumns();
}
/**
- * Returns the grid unit at the given column number on the active row.
- *
- * @param column column number of the grid unit to get
- * @return the corresponding grid unit (may be null)
- * {@inheritDoc}
+ * Initializes the fields of this instance to handle a new row group.
+ *
+ * @param rows the new row group to handle
*/
- private GridUnit getActiveGridUnit(int column) {
- return getActiveRow().safelyGetGridUnit(column);
+ private void setup(EffRow[] rows) {
+ rowGroup = rows;
+ previousRowsLength = 0;
+ activeRowIndex = 0;
+ activeCells.clear();
+ nextActiveCells.clear();
+ delayingNextRow = false;
+ rowFirstStep = 0;
+ rowHeightSmallerThanFirstStep = false;
}
private void calcTotalHeight() {
@@ -110,30 +128,35 @@
private int getMaxRemainingHeight() {
int maxW = 0;
- if (!rowBacktrackForLastStep) {
- for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
- maxW = Math.max(maxW,
- ((ActiveCell) iter.next()).getRemainingHeight(activeRowIndex));
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ int remain = activeCell.getRemainingLength();
+ PrimaryGridUnit pgu = activeCell.getPrimaryGridUnit();
+ for (int i = activeRowIndex + 1; i < pgu.getRowIndex() - rowGroup[0].getIndex()
+ + pgu.getCell().getNumberRowsSpanned(); i++) {
+ remain -= rowGroup[i].getHeight().opt;
}
+ maxW = Math.max(maxW, remain);
}
- for (int i = activeRowIndex + (rowBacktrackForLastStep ? 0 : 1); i < rowGroup.length; i++) {
+ for (int i = activeRowIndex + 1; i < rowGroup.length; i++) {
maxW += rowGroup[i].getHeight().opt;
}
- log.debug("maxRemainingHeight=" + maxW);
return maxW;
}
/**
- * Initializes the informations relative to the Knuth elements, to handle a new row in
- * the current row group.
+ * Creates ActiveCell instances for cells starting on the row at the given index.
+ *
+ * @param activeCellList the list that will hold the active cells
+ * @param rowIndex the index of the row from which cells must be activated
*/
- private void initializeElementLists() {
- log.trace("Entering initializeElementLists()");
- EffRow row = getActiveRow();
+ private void activateCells(List activeCellList, int rowIndex) {
+ EffRow row = rowGroup[rowIndex];
for (int i = 0; i < columnCount; i++) {
- GridUnit gu = getActiveGridUnit(i);
- if (gu != null && !gu.isEmpty() && gu.isPrimary()) {
- activeCells.add(new ActiveCell((PrimaryGridUnit) gu, row, activeRowIndex, previousRowsLength, getTableLM()));
+ GridUnit gu = row.getGridUnit(i);
+ if (!gu.isEmpty() && gu.isPrimary()) {
+ activeCellList.add(new ActiveCell((PrimaryGridUnit) gu, row, rowIndex,
+ previousRowsLength, getTableLM()));
}
}
}
@@ -141,64 +164,60 @@
/**
* Creates the combined element list for a row group.
* @param context Active LayoutContext
- * @param rowGroup the row group
- * @param maxColumnCount the maximum number of columns to expect
+ * @param rows the row group
* @param bodyType Indicates what type of body is processed (body, header or footer)
* @return the combined element list
*/
- public LinkedList getCombinedKnuthElementsForRowGroup(
- LayoutContext context,
- EffRow[] rowGroup, int maxColumnCount, int bodyType) {
- this.rowGroup = rowGroup;
- setup(maxColumnCount);
- initializeElementLists();
+ public LinkedList getCombinedKnuthElementsForRowGroup(LayoutContext context, EffRow[] rows,
+ int bodyType) {
+ setup(rows);
+ activateCells(activeCells, 0);
calcTotalHeight();
boolean signalKeepWithNext = false;
- int laststep = 0;
- int step;
int cumulateLength = 0; // Length of the content accumulated before the break
TableContentPosition lastTCPos = null;
LinkedList returnList = new LinkedList();
- while ((step = getNextStep()) >= 0) {
- int normalRow = activeRowIndex;
- int increase = step - laststep;
- int penaltyOrGlueLen = step + getMaxRemainingHeight() - totalHeight;
- int boxLen = step - cumulateLength - Math.max(0, penaltyOrGlueLen)/* the penalty, if any */;
+ 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 */;
- boolean forcedBreak = false;
- int breakClass = -1;
+ 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));
+ }
+ }
+
//Put all involved grid units into a list
- List cellParts = new java.util.ArrayList(maxColumnCount);
+ List cellParts = new java.util.ArrayList(columnCount);
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- if (activeCell.contributesContent()) {
- CellPart part = activeCell.createCellPart();
- cellParts.add(part);
- forcedBreak = activeCell.isLastForcedBreak();
- if (forcedBreak) {
- breakClass = activeCell.getLastBreakClass();
- }
- if (returnList.size() == 0 && part.isFirstPart()
- && part.mustKeepWithPrevious()) {
- context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
- }
+ CellPart part = activeCell.createCellPart();
+ cellParts.add(part);
+ if (returnList.size() == 0 && part.isFirstPart()
+ && part.mustKeepWithPrevious()) {
+ context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING);
}
}
- //log.debug(">>> guPARTS: " + cellParts);
//Create elements for step
TableContentPosition tcpos = new TableContentPosition(getTableLM(),
- cellParts, rowGroup[normalRow]);
+ cellParts, rowGroup[activeRowIndex]);
+ if (delayingNextRow) {
+ tcpos.setNewPageRow(rowGroup[activeRowIndex + 1]);
+ }
if (returnList.size() == 0) {
tcpos.setFlag(TableContentPosition.FIRST_IN_ROWGROUP, true);
}
lastTCPos = tcpos;
- if (log.isDebugEnabled()) {
- log.debug(" - backtrack=" + rowBacktrackForLastStep
- + " - row=" + activeRowIndex + " - " + tcpos);
- }
returnList.add(new KnuthBox(boxLen, tcpos, false));
int effPenaltyLen = Math.max(0, penaltyOrGlueLen);
@@ -215,48 +234,36 @@
}
int p = 0;
- boolean allCellsHaveContributed = true;
signalKeepWithNext = false;
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- allCellsHaveContributed &= activeCell.hasStarted();
signalKeepWithNext |= activeCell.keepWithNextSignal();
}
- if (!allCellsHaveContributed) {
- //Not all cells have contributed to a newly started row. The penalty here is
- //used to avoid breaks resulting in badly broken tables.
- //See also: http://marc.theaimsgroup.com/?t=112248999600005&r=1&w=2
- p = 900; //KnuthPenalty.INFINITE; //TODO Arbitrary value. Please refine.
- }
if (signalKeepWithNext || getTableLM().mustKeepTogether()) {
p = KnuthPenalty.INFINITE;
}
- if (skippedStep) {
- p = KnuthPenalty.INFINITE;
- //Need to avoid breaking because borders and/or paddding from other columns would
- //not fit in the available space (see getNextStep())
+ if (rowFinished && activeRowIndex < rowGroup.length - 1) {
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ rowGroup[activeRowIndex].getBreakAfter());
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ rowGroup[activeRowIndex + 1].getBreakBefore());
}
- if (forcedBreak) {
- if (skippedStep) {
- log.error("This is a conflict situation. The output may be wrong."
- + " Please send your FO file to fop-dev@xmlgraphics.apache.org!");
- }
+ if (nextBreakClass != Constants.EN_AUTO) {
+ log.trace("Forced break encountered");
p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
}
- returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context));
+ if (rowHeightSmallerThanFirstStep) {
+ rowHeightSmallerThanFirstStep = false;
+ p = KnuthPenalty.INFINITE;
+ }
+ returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, nextBreakClass, context));
if (penaltyOrGlueLen < 0) {
returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true));
}
- if (log.isDebugEnabled()) {
- log.debug("step=" + step + " (+" + increase + ")"
- + " box=" + boxLen
- + " penalty=" + penaltyOrGlueLen
- + " effPenalty=" + effPenaltyLen);
- }
-
laststep = step;
- }
+ step = getNextStep();
+ } while (step >= 0);
if (signalKeepWithNext) {
//Last step signalled a keep-with-next. Since the last penalty will be removed,
//we have to signal the still pending last keep-with-next using the LayoutContext.
@@ -269,23 +276,77 @@
}
/**
- * Finds the smallest increment leading to the next legal break inside the row-group.
+ * Returns the first step for the current row group.
*
- * @return the size of the increment, -1 if no next step is available (end of row-group reached)
+ * @return the first step for the current row group
+ */
+ private int getFirstStep() {
+ computeRowFirstStep(activeCells);
+ signalRowFirstStep();
+ int minStep = considerRowLastStep(rowFirstStep);
+ signalNextStep(minStep);
+ return minStep;
+ }
+
+ /**
+ * Returns the next break possibility.
+ *
+ * @return the next step
*/
private int getNextStep() {
- log.trace("Entering getNextStep");
- //Check for forced break conditions
- /*
- if (isBreakCondition()) {
- return -1;
- }*/
+ if (rowFinished) {
+ if (activeRowIndex == rowGroup.length - 1) {
+ // The row group is finished, no next step
+ return -1;
+ }
+ rowFinished = false;
+ removeCellsEndingOnCurrentRow();
+ log.trace("Delaying next row");
+ delayingNextRow = true;
+ }
+ if (delayingNextRow) {
+ int minStep = computeMinStep();
+ if (minStep < 0 || minStep >= rowFirstStep
+ || minStep > rowGroup[activeRowIndex].getExplicitHeight().max) {
+ if (log.isTraceEnabled()) {
+ log.trace("Step = " + minStep);
+ }
+ delayingNextRow = false;
+ minStep = rowFirstStep;
+ switchToNextRow();
+ signalRowFirstStep();
+ minStep = considerRowLastStep(minStep);
+ }
+ signalNextStep(minStep);
+ return minStep;
+ } else {
+ int minStep = computeMinStep();
+ minStep = considerRowLastStep(minStep);
+ signalNextStep(minStep);
+ return minStep;
+ }
+ }
- //set starting points
- goToNextRowIfCurrentFinished();
+ /**
+ * Computes the minimal necessary step to make the next row fit. That is, so such as
+ * cell on the next row can contribute some content.
+ *
+ * @param cells the cells occupying the next row (may include cells starting on
+ * previous rows and spanning over this one)
+ */
+ private void computeRowFirstStep(List cells) {
+ for (Iterator iter = cells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ rowFirstStep = Math.max(rowFirstStep, activeCell.getFirstStep());
+ }
+ }
- //Get next possible sequence for each cell
- //Determine smallest possible step
+ /**
+ * Computes the next minimal step.
+ *
+ * @return the minimal step from the active cells, < 0 if there is no such step
+ */
+ private int computeMinStep() {
int minStep = Integer.MAX_VALUE;
boolean stepFound = false;
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
@@ -296,32 +357,113 @@
minStep = Math.min(minStep, nextStep);
}
}
- if (!stepFound) {
+ if (stepFound) {
+ return minStep;
+ } else {
return -1;
}
+ }
+ /**
+ * Signals the first step to the active cells, to allow them to add more content to
+ * the step if possible.
+ *
+ * @see ActiveCell#signalRowFirstStep(int)
+ */
+ private void signalRowFirstStep() {
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ activeCell.signalRowFirstStep(rowFirstStep);
+ }
+ }
- //Reset bigger-than-minimum sequences
- //See http://people.apache.org/~jeremias/fop/NextStepAlgoNotes.pdf
- rowBacktrackForLastStep = false;
- skippedStep = false;
+ /**
+ * Signals the next selected step to the active cells.
+ *
+ * @param step the next step
+ */
+ private void signalNextStep(int step) {
+ nextBreakClass = Constants.EN_AUTO;
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- if (activeCell.signalMinStep(minStep)) {
- if (activeRowIndex == 0) {
- log.debug(" First row. Skip this step.");
- skippedStep = true;
- } else {
- log.debug(" row-span situation: backtracking to last row");
- //Stay on the previous row for another step because borders and padding on
- //columns may make their contribution to the step bigger than the addition
- //of the next element for this step would make the step to grow.
- rowBacktrackForLastStep = true;
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ activeCell.signalNextStep(step));
+ }
+ }
+
+ /**
+ * Determines if the given step will finish the current row, and if so switch to the
+ * last step for this row.
+ * <p>If the row is finished then the after borders for the cell may change (their
+ * conditionalities no longer apply for the cells ending on the current row). Thus the
+ * final step may grow with respect to the given one.</p>
+ * <p>In more rare occasions, the given step may correspond to the first step of a
+ * row-spanning cell, and may be greater than the height of the current row (consider,
+ * for example, an unbreakable cell spanning three rows). In such a case the returned
+ * step will correspond to the row height and a flag will be set to produce an
+ * infinite penalty for this step. This will prevent the breaking algorithm from
+ * choosing this break, but still allow to create the appropriate TableContentPosition
+ * for the cells ending on the current row.</p>
+ *
+ * @param step the next step
+ * @return the updated step if any
+ */
+ private int considerRowLastStep(int step) {
+ rowFinished = true;
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ if (activeCell.endsOnRow(activeRowIndex)) {
+ rowFinished &= activeCell.finishes(step);
+ }
+ }
+ if (rowFinished) {
+ if (log.isTraceEnabled()) {
+ log.trace("Step = " + step);
+ log.trace("Row finished, computing last step");
+ }
+ int maxStep = 0;
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ if (activeCell.endsOnRow(activeRowIndex)) {
+ maxStep = Math.max(maxStep, activeCell.getLastStep());
+ }
+ }
+ if (log.isTraceEnabled()) {
+ log.trace("Max step: " + maxStep);
+ }
+ for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
+ ActiveCell activeCell = (ActiveCell) iter.next();
+ activeCell.endRow(activeRowIndex);
+ if (!activeCell.endsOnRow(activeRowIndex)) {
+ activeCell.signalRowLastStep(maxStep);
}
}
+ if (maxStep < step) {
+ log.trace("Row height smaller than first step, produced penalty will be infinite");
+ rowHeightSmallerThanFirstStep = true;
+ }
+ step = maxStep;
+ prepareNextRow();
}
+ return step;
+ }
- return minStep;
+ /**
+ * Pre-activates the cells that will start the next row, and computes the first step
+ * for that row.
+ */
+ private void prepareNextRow() {
+ if (activeRowIndex < rowGroup.length - 1) {
+ previousRowsLength += rowGroup[activeRowIndex].getHeight().opt;
+ activateCells(nextActiveCells, activeRowIndex + 1);
+ if (log.isTraceEnabled()) {
+ log.trace("Computing first step for row " + (activeRowIndex + 2));
+ }
+ computeRowFirstStep(nextActiveCells);
+ if (log.isTraceEnabled()) {
+ log.trace("Next first step = " + rowFirstStep);
+ }
+ }
}
private void removeCellsEndingOnCurrentRow() {
@@ -333,40 +475,21 @@
}
}
- private void goToNextRowIfCurrentFinished() {
- // We assume that the current grid row is finished. If this is not the case this
- // boolean will be reset
- boolean currentGridRowFinished = true;
+ /**
+ * Actually switches to the next row, increasing activeRowIndex and transferring to
+ * activeCells the cells starting on the next row.
+ */
+ private void switchToNextRow() {
+ activeRowIndex++;
+ if (log.isTraceEnabled()) {
+ log.trace("Switching to row " + (activeRowIndex + 1));
+ }
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- if (activeCell.endsOnRow(activeRowIndex)) {
- currentGridRowFinished &= activeCell.isFinished();
- }
- }
-
- if (currentGridRowFinished) {
- removeCellsEndingOnCurrentRow();
- if (activeRowIndex < rowGroup.length - 1) {
- TableRow rowFO = getActiveRow().getTableRow();
- if (rowFO != null && rowFO.getBreakAfter() != Constants.EN_AUTO) {
- log.warn(FONode.decorateWithContextInfo(
- "break-after ignored on table-row because of row spanning "
- + "in progress (See XSL 1.0, 7.19.1)", rowFO));
- }
- previousRowsLength += rowGroup[activeRowIndex].getHeight().opt;
- activeRowIndex++;
- if (log.isDebugEnabled()) {
- log.debug("===> new row: " + activeRowIndex);
- }
- initializeElementLists();
- rowFO = getActiveRow().getTableRow();
- if (rowFO != null && rowFO.getBreakBefore() != Constants.EN_AUTO) {
- log.warn(FONode.decorateWithContextInfo(
- "break-before ignored on table-row because of row spanning "
- + "in progress (See XSL 1.0, 7.19.2)", rowFO));
- }
- }
+ activeCell.nextRowStarts();
}
+ activeCells.addAll(nextActiveCells);
+ nextActiveCells.clear();
}
/** @return the table layout manager */
Propchange: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
------------------------------------------------------------------------------
--- svn:keywords (original)
+++ svn:keywords Thu Feb 14 13:55:44 2008
@@ -1 +1 @@
-Author Date Id Revision
+Id
Modified: xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/AbstractPDFStream.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/AbstractPDFStream.java?rev=627882&r1=627881&r2=627882&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/AbstractPDFStream.java (original)
+++ xmlgraphics/fop/branches/Temp_Interleaved_Page_Line_Breaking/src/java/org/apache/fop/pdf/AbstractPDFStream.java Thu Feb 14 13:55:44 2008
@@ -21,8 +21,10 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.io.Writer;
import org.apache.commons.io.output.CountingOutputStream;
+
import org.apache.fop.util.CloseBlockerOutputStream;
/**
@@ -169,8 +171,12 @@
* {@inheritDoc}
*/
protected int output(OutputStream stream) throws IOException {
- int length = 0;
setupFilterList();
+
+ CountingOutputStream cout = new CountingOutputStream(stream);
+ Writer writer = PDFDocument.getWriterFor(cout);
+ writer.write(getObjectID());
+ //int length = 0;
StreamCache encodedStream = null;
PDFNumber refLength = null;
@@ -184,38 +190,21 @@
lengthEntry = new Integer(encodedStream.getSize() + 1);
}
- byte[] p = encode(buildStreamDict(lengthEntry));
- stream.write(p);
- length += p.length;
+ populateStreamDict(lengthEntry);
+ writeDictionary(cout, writer);
//Send encoded stream to target OutputStream
+ writer.flush();
if (encodedStream == null) {
- int bytesWritten = encodeAndWriteStream(stream, refLength);
- length += bytesWritten;
+ encodeAndWriteStream(cout, refLength);
} else {
- length += outputStreamData(encodedStream, stream);
+ outputStreamData(encodedStream, cout);
encodedStream.clear(); //Encoded stream can now be discarded
}
- p = encode("\nendobj\n");
- stream.write(p);
- length += p.length;
- return length;
- }
-
- /**
- * Constructs the dictionary for the stream. Override this method if you
- * need additional entries.
- * @param lengthEntry value for the /Length entry
- * @return the newly constructed dictionary
- */
- protected String buildStreamDict(Object lengthEntry) {
- StringBuffer sb = new StringBuffer();
- sb.append(getObjectID());
- populateStreamDict(lengthEntry);
-
- writeDictionary(sb);
- return sb.toString();
+ writer.write("\nendobj\n");
+ writer.flush();
+ return cout.getCount();
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org