aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2005-06-22 14:59:54 +0000
committerJeremias Maerki <jeremias@apache.org>2005-06-22 14:59:54 +0000
commite3262c749a4db01da99a5ab1bed99c104633c922 (patch)
tree94b16356fb16cdd1597f25a05330e4b3d4f9c6a1 /src/java/org/apache
parentc60570bad47b8563ac7415a6965aec825e6d40dc (diff)
downloadxmlgraphics-fop-e3262c749a4db01da99a5ab1bed99c104633c922.tar.gz
xmlgraphics-fop-e3262c749a4db01da99a5ab1bed99c104633c922.zip
breaks supported on tables, table-row and table-cell content now. Cheap approach for now. TableContentLM is not yet restartable, but the Breaker handles that pretty well.
Improved page break handling to support the different break classes even if no new block sequence is started. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@198765 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/fop/layoutmgr/AbstractBreaker.java44
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/EffRow.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java77
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java22
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableStepper.java48
7 files changed, 178 insertions, 27 deletions
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
index 99dff32ba..b6f2eda24 100644
--- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
+++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
@@ -127,7 +127,7 @@ public abstract class AbstractBreaker {
return (blockLists.size() == 0);
}
- protected void startPart(BlockSequence list, boolean bIsFirstPage) {
+ protected void startPart(BlockSequence list, int breakClass) {
//nop
}
@@ -183,7 +183,7 @@ public abstract class AbstractBreaker {
PageBreakingAlgorithm alg = new PageBreakingAlgorithm(getTopLevelLM(),
getPageViewportProvider(),
alignment, alignmentLast, footnoteSeparatorLength);
- int iOptPageNumber;
+ int iOptPageCount;
BlockSequence effectiveList;
if (alignment == Constants.EN_JUSTIFY) {
@@ -194,16 +194,16 @@ public abstract class AbstractBreaker {
effectiveList = blockList;
}
- //iOptPageNumber = alg.firstFit(effectiveList, flowBPD, 1, true);
+ //iOptPageCount = alg.firstFit(effectiveList, flowBPD, 1, true);
alg.setConstantLineWidth(flowBPD);
- iOptPageNumber = alg.findBreakingPoints(effectiveList, /*flowBPD,*/
- 1, true, true);
- log.debug("PLM> iOptPageNumber= " + iOptPageNumber
+ iOptPageCount = alg.findBreakingPoints(effectiveList, /*flowBPD,*/
+ 1, true, true);
+ log.debug("PLM> iOptPageCount= " + iOptPageCount
+ " pageBreaks.size()= " + alg.getPageBreaks().size());
//*** Phase 3: Add areas ***
- doPhase3(alg, iOptPageNumber, blockList, effectiveList);
+ doPhase3(alg, iOptPageCount, blockList, effectiveList);
}
}
@@ -233,20 +233,38 @@ public abstract class AbstractBreaker {
int endElementIndex = 0;
for (int p = 0; p < partCount; p++) {
PageBreakPosition pbp = (PageBreakPosition) alg.getPageBreaks().get(p);
- endElementIndex = pbp.getLeafPos();
- log.debug("PLM> part: " + (p + 1)
- + ", break at position " + endElementIndex);
- startPart(effectiveList, (p == 0));
-
- int displayAlign = getCurrentDisplayAlign();
+ //Check the last break position for forced breaks
+ int lastBreakClass;
+ if (p == 0) {
+ lastBreakClass = effectiveList.getStartOn();
+ } else {
+ KnuthElement lastBreakElement = effectiveList.getElement(endElementIndex);
+ if (lastBreakElement.isPenalty()) {
+ KnuthPenalty pen = (KnuthPenalty)lastBreakElement;
+ lastBreakClass = pen.getBreakClass();
+ } else {
+ lastBreakClass = Constants.EN_AUTO;
+ }
+ }
+ //the end of the new part
+ endElementIndex = pbp.getLeafPos();
+
// ignore the first elements added by the
// PageSequenceLayoutManager
startElementIndex += (startElementIndex == 0)
? effectiveList.ignoreAtStart
: 0;
+ log.debug("PLM> part: " + (p + 1)
+ + ", start at pos " + startElementIndex
+ + ", break at pos " + endElementIndex);
+
+ startPart(effectiveList, lastBreakClass);
+
+ int displayAlign = getCurrentDisplayAlign();
+
// ignore the last elements added by the
// PageSequenceLayoutManager
endElementIndex -= (endElementIndex == (originalList.size() - 1))
diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
index e36f22c9b..fa65dfda9 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
@@ -822,6 +822,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
breakBefore = ((org.apache.fop.fo.flow.Block) fobj).getBreakBefore();
} else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
breakBefore = ((org.apache.fop.fo.flow.BlockContainer) fobj).getBreakBefore();
+ } else if (fobj instanceof org.apache.fop.fo.flow.Table) {
+ breakBefore = ((org.apache.fop.fo.flow.Table) fobj).getBreakBefore();
}
if (breakBefore == EN_PAGE
|| breakBefore == EN_COLUMN
@@ -849,6 +851,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
breakAfter = ((org.apache.fop.fo.flow.Block) fobj).getBreakAfter();
} else if (fobj instanceof org.apache.fop.fo.flow.BlockContainer) {
breakAfter = ((org.apache.fop.fo.flow.BlockContainer) fobj).getBreakAfter();
+ } else if (fobj instanceof org.apache.fop.fo.flow.Table) {
+ breakAfter = ((org.apache.fop.fo.flow.Table) fobj).getBreakAfter();
}
if (breakAfter == EN_PAGE
|| breakAfter == EN_COLUMN
diff --git a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
index 049811461..59f07bf93 100644
--- a/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
@@ -261,7 +261,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
addAreas(alg, partCount, originalList, effectiveList);
}
- protected void startPart(BlockSequence list, boolean bIsFirstPage) {
+ protected void startPart(BlockSequence list, int breakClass) {
if (curPV == null) {
throw new IllegalStateException("curPV must not be null");
} else {
@@ -276,7 +276,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
// the current BlockSequence, it could have a break
// condition that must be satisfied;
// otherwise, we may simply need a new page
- handleBreakTrait(bIsFirstPage ? list.getStartOn() : Constants.EN_PAGE);
+ handleBreakTrait(breakClass);
}
}
pvProvider.setStartPageOfNextElementList(currentPageNum);
diff --git a/src/java/org/apache/fop/layoutmgr/table/EffRow.java b/src/java/org/apache/fop/layoutmgr/table/EffRow.java
index ddb2a47cb..1e0befa99 100644
--- a/src/java/org/apache/fop/layoutmgr/table/EffRow.java
+++ b/src/java/org/apache/fop/layoutmgr/table/EffRow.java
@@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr.table;
import java.util.Iterator;
import java.util.List;
+import org.apache.fop.fo.flow.TableRow;
import org.apache.fop.traits.MinOptMax;
/**
@@ -63,6 +64,11 @@ public class EffRow {
return this.bodyType;
}
+ /** @return the table-row FO for this EffRow, or null if there is no table-row. */
+ public TableRow getTableRow() {
+ return getGridUnit(0).getRow();
+ }
+
/** @return the calculated height for this EffRow. */
public MinOptMax getHeight() {
return this.height;
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
index 0381b4edd..4ac134309 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
@@ -28,6 +28,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.area.Block;
import org.apache.fop.area.Trait;
+import org.apache.fop.fo.Constants;
import org.apache.fop.fo.flow.Table;
import org.apache.fop.fo.flow.TableBody;
import org.apache.fop.fo.flow.TableRow;
@@ -63,6 +64,7 @@ public class TableContentLayoutManager {
private LinkedList footerList;
private int headerNetHeight = 0;
private int footerNetHeight = 0;
+ private boolean firstBreakBeforeServed = false;
private int startXOffset;
private int usedBPD;
@@ -130,7 +132,7 @@ public class TableContentLayoutManager {
KnuthBox headerAsFirst = null;
KnuthBox headerAsSecondToLast = null;
KnuthBox footerAsLast = null;
- if (headerIter != null) {
+ if (headerIter != null && headerList == null) {
this.headerList = getKnuthElementsForRowIterator(
headerIter, context, alignment, TableRowIterator.HEADER);
ElementListUtils.removeLegalBreaks(this.headerList);
@@ -148,7 +150,7 @@ public class TableContentLayoutManager {
headerAsSecondToLast = box;
}
}
- if (footerIter != null) {
+ if (footerIter != null && footerList == null) {
this.footerList = getKnuthElementsForRowIterator(
footerIter, context, alignment, TableRowIterator.FOOTER);
ElementListUtils.removeLegalBreaks(this.footerList);
@@ -190,11 +192,39 @@ public class TableContentLayoutManager {
LinkedList returnList = new LinkedList();
EffRow[] rowGroup = null;
while ((rowGroup = iter.getNextRowGroup()) != null) {
+ //Check for break-before on the table-row at the start of the row group
+ TableRow rowFO = rowGroup[0].getTableRow();
+ if (rowFO != null && rowFO.getBreakBefore() != Constants.EN_AUTO) {
+ log.info("break-before found");
+ if (returnList.size() > 0) {
+ KnuthElement last = (KnuthElement)returnList.getLast();
+ if (last.isPenalty()) {
+ KnuthPenalty pen = (KnuthPenalty)last;
+ pen.setP(-KnuthPenalty.INFINITE);
+ pen.setBreakClass(rowFO.getBreakBefore());
+ }
+ } else {
+ if (!firstBreakBeforeServed) {
+ returnList.add(new KnuthPenalty(0, -KnuthPenalty.INFINITE,
+ false, rowFO.getBreakBefore(), new Position(getTableLM()), true));
+ iter.backToPreviousRow();
+ firstBreakBeforeServed = true;
+ break;
+ }
+ }
+ }
+ firstBreakBeforeServed = true;
+
+ //Border resolution
if (!isSeparateBorderModel()) {
resolveNormalBeforeAfterBordersForRowGroup(rowGroup, iter);
}
+
+ //Element list creation
createElementsForRowGroup(context, alignment, bodyType,
returnList, rowGroup);
+
+ //Handle keeps
if (context.isKeepWithNextPending()) {
log.debug("child LM (row group) signals pending keep-with-next");
}
@@ -205,7 +235,24 @@ public class TableContentLayoutManager {
KnuthElement last = (KnuthElement)returnList.getLast();
if (last.isPenalty()) {
KnuthPenalty pen = (KnuthPenalty)last;
- pen.setP(KnuthPenalty.INFINITE);
+ //Only honor keep if there's no forced break
+ if (!pen.isForcedBreak()) {
+ pen.setP(KnuthPenalty.INFINITE);
+ }
+ }
+ }
+ }
+
+ //Check for break-after on the table-row at the end of the row group
+ rowFO = rowGroup[rowGroup.length - 1].getTableRow();
+ if (rowFO != null && rowFO.getBreakAfter() != Constants.EN_AUTO) {
+ log.info("break-after found");
+ if (returnList.size() > 0) {
+ KnuthElement last = (KnuthElement)returnList.getLast();
+ if (last.isPenalty()) {
+ KnuthPenalty pen = (KnuthPenalty)last;
+ pen.setP(-KnuthPenalty.INFINITE);
+ pen.setBreakClass(rowFO.getBreakAfter());
}
}
}
@@ -215,7 +262,11 @@ public class TableContentLayoutManager {
//Remove last penalty
KnuthElement last = (KnuthElement)returnList.getLast();
if (last.isPenalty()) {
- returnList.removeLast();
+ KnuthPenalty pen = (KnuthPenalty)last;
+ if (!pen.isForcedBreak()) {
+ //Only remove if we don't signal a forced break
+ returnList.removeLast();
+ }
}
}
return returnList;
@@ -395,8 +446,24 @@ public class TableContentLayoutManager {
//Get the element list for the cell contents
LinkedList elems = primary.getCellLM().getNextKnuthElements(
childLC, alignment);
- primary.setElements(elems);
+ //Temporary? Multiple calls in case of break conditions.
+ //TODO Revisit when table layout is restartable
+ while (!primary.getCellLM().isFinished()) {
+ LinkedList additionalElems = primary.getCellLM().getNextKnuthElements(
+ childLC, alignment);
+ elems.addAll(additionalElems);
+ }
ElementListObserver.observe(elems, "table-cell", primary.getCell().getId());
+
+ if (((KnuthElement)elems.getLast()).isPenalty()
+ && ((KnuthPenalty)elems.getLast()).getP()
+ == -KnuthElement.INFINITE) {
+ // a descendant of this block has break-after
+ log.warn("Descendant of table-cell signals break: "
+ + primary.getCellLM().isFinished());
+ }
+
+ primary.setElements(elems);
if (childLC.isKeepWithNextPending()) {
log.debug("child LM signals pending keep-with-next");
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
index babdaa34b..bb9a40a71 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
@@ -116,12 +116,20 @@ public class TableLayoutManager extends BlockStackingLayoutManager
return iIndents;
}
- /**
- * @see org.apache.fop.layoutmgr.LayoutManager#getNextKnuthElements(org.apache.fop.layoutmgr.LayoutContext, int)
- */
+ /** @see org.apache.fop.layoutmgr.LayoutManager */
public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
- //Body curLM; // currently active LM
+ LinkedList returnList = new LinkedList();
+
+ if (!bBreakBeforeServed) {
+ try {
+ if (addKnuthElementsForBreakBefore(returnList)) {
+ return returnList;
+ }
+ } finally {
+ bBreakBeforeServed = true;
+ }
+ }
referenceIPD = context.getRefIPD();
if (fobj.getInlineProgressionDimension().getOptimum().getEnum() != EN_AUTO) {
@@ -169,7 +177,6 @@ public class TableLayoutManager extends BlockStackingLayoutManager
LinkedList returnedList = null;
LinkedList contentList = new LinkedList();
- LinkedList returnList = new LinkedList();
//Position returnPosition = new NonLeafPosition(this, null);
//Body prevLM = null;
@@ -179,7 +186,9 @@ public class TableLayoutManager extends BlockStackingLayoutManager
stackSize));
childLC.setRefIPD(context.getRefIPD());
- contentLM = new TableContentLayoutManager(this);
+ if (contentLM == null) {
+ contentLM = new TableContentLayoutManager(this);
+ }
returnedList = contentLM.getNextKnuthElements(childLC, alignment);
if (childLC.isKeepWithNextPending()) {
log.debug("TableContentLM signals pending keep-with-next");
@@ -261,6 +270,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager
}
}
wrapPositionElements(contentList, returnList);
+ addKnuthElementsForBreakAfter(returnList);
setFinished(true);
return returnList;
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
index 4b09fce35..2fe38e79a 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
@@ -24,6 +24,8 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.flow.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthBox;
@@ -57,6 +59,7 @@ public class TableStepper {
private int[] borderAfter;
private boolean rowBacktrackForLastStep;
private boolean[] keepWithNextSignals;
+ private boolean[] forcedBreaks;
/**
* Main constructor
@@ -77,9 +80,23 @@ public class TableStepper {
borderBefore = new int[columnCount];
borderAfter = new int[columnCount];
keepWithNextSignals = new boolean[columnCount];
+ forcedBreaks = new boolean[columnCount];
Arrays.fill(end, -1);
}
+ private void clearBreakCondition() {
+ Arrays.fill(forcedBreaks, false);
+ }
+
+ private boolean isBreakCondition() {
+ for (int i = 0; i < forcedBreaks.length; i++) {
+ if (forcedBreaks[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private EffRow getActiveRow() {
return rowGroup[activeRow];
}
@@ -147,6 +164,7 @@ public class TableStepper {
widths[column] = 0;
startRow[column] = activeRow;
keepWithNextSignals[column] = false;
+ forcedBreaks[column] = false;
} else if (gu.isPrimary()) {
PrimaryGridUnit pgu = (PrimaryGridUnit)gu;
boolean makeBoxForWholeRow = false;
@@ -184,6 +202,7 @@ public class TableStepper {
widths[column] = 0;
startRow[column] = activeRow;
keepWithNextSignals[column] = false;
+ forcedBreaks[column] = false;
}
}
@@ -303,6 +322,10 @@ public class TableStepper {
if (signalKeepWithNext || getTableLM().mustKeepTogether()) {
p = KnuthPenalty.INFINITE;
}
+ if (isBreakCondition()) {
+ p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
+ clearBreakCondition();
+ }
returnList.add(new KnuthPenalty(effPenaltyLen, p, false, penaltyPos, false));
log.debug("step=" + step + " (+" + increase + ")"
@@ -321,11 +344,20 @@ public class TableStepper {
//we have to signal the still pending last keep-with-next using the LayoutContext.
context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING);
}
+ if (isBreakCondition()) {
+ ((KnuthPenalty)returnList.getLast()).setP(-KnuthPenalty.INFINITE);
+ }
lastTCPos.setFlag(TableContentPosition.LAST_IN_ROWGROUP, true);
return returnList;
}
private int getNextStep(int lastStep) {
+ //Check for forced break conditions
+ /*
+ if (isBreakCondition()) {
+ return -1;
+ }*/
+
int[] backupWidths = new int[start.length];
System.arraycopy(widths, 0, backupWidths, 0, backupWidths.length);
@@ -349,6 +381,11 @@ public class TableStepper {
if (rowPendingIndicator == 0) {
if (activeRow < rowGroup.length - 1) {
+ TableRow rowFO = getActiveRow().getTableRow();
+ if (rowFO != null && rowFO.getBreakAfter() != Constants.EN_AUTO) {
+ log.warn("break-after ignored on table-row because of row spanning "
+ + "in progress (See XSL 1.0, 7.19.1)");
+ }
activeRow++;
log.debug("===> new row: " + activeRow);
initializeElementLists();
@@ -357,6 +394,11 @@ public class TableStepper {
backupWidths[i] = 0;
}
}
+ rowFO = getActiveRow().getTableRow();
+ if (rowFO != null && rowFO.getBreakBefore() != Constants.EN_AUTO) {
+ log.warn("break-before ignored on table-row because of row spanning "
+ + "in progress (See XSL 1.0, 7.19.2)");
+ }
}
}
@@ -370,7 +412,11 @@ public class TableStepper {
end[i]++;
KnuthElement el = (KnuthElement)elementLists[i].get(end[i]);
if (el.isPenalty()) {
- if (el.getP() < KnuthElement.INFINITE) {
+ if (el.getP() <= -KnuthElement.INFINITE) {
+ log.warn("FORCED break encountered!");
+ forcedBreaks[i] = true;
+ break;
+ } else if (el.getP() < KnuthElement.INFINITE) {
//First legal break point
break;
}