aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop
diff options
context:
space:
mode:
authorVincent Hennebert <vhennebert@apache.org>2008-02-13 18:11:06 +0000
committerVincent Hennebert <vhennebert@apache.org>2008-02-13 18:11:06 +0000
commit71ecb950fba8d7134c912acda3a75845930099cb (patch)
treeed9a24ff0a999ae534c2757f3845bb8bc8d41ac6 /src/java/org/apache/fop
parentea691f9d34c8b1757f36f2dcecf520b3ffe3e27e (diff)
downloadxmlgraphics-fop-71ecb950fba8d7134c912acda3a75845930099cb.tar.gz
xmlgraphics-fop-71ecb950fba8d7134c912acda3a75845930099cb.zip
Added support for breaks before and after table cells
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@627553 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop')
-rw-r--r--src/java/org/apache/fop/fo/flow/table/EffRow.java47
-rw-r--r--src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java2
-rw-r--r--src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java42
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/ActiveCell.java20
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java14
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/RowPainter.java15
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java12
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java15
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableStepper.java36
-rw-r--r--src/java/org/apache/fop/util/BreakUtil.java65
10 files changed, 208 insertions, 60 deletions
diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java
index fb2162e55..ac99a1d37 100644
--- a/src/java/org/apache/fop/fo/flow/table/EffRow.java
+++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java
@@ -22,8 +22,10 @@ package org.apache.fop.fo.flow.table;
import java.util.Iterator;
import java.util.List;
+import org.apache.fop.fo.Constants;
import org.apache.fop.layoutmgr.table.TableRowIterator;
import org.apache.fop.traits.MinOptMax;
+import org.apache.fop.util.BreakUtil;
/**
* This class represents an effective row in a table and holds a list of grid units occupying
@@ -159,7 +161,50 @@ public class EffRow {
throw new IllegalArgumentException("Illegal flag queried: " + which);
}
}
-
+
+
+ /**
+ * Returns the break class for this row. This is a combination of break-before set on
+ * the first children of any cells starting on this row.
+ * <p><strong>Note:</strong> this works only after getNextKuthElements on the
+ * corresponding TableCellLM have been called!</p>
+ *
+ * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
+ * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
+ */
+ public int getBreakBefore() {
+ int breakBefore = Constants.EN_AUTO;
+ for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
+ GridUnit gu = (GridUnit) iter.next();
+ if (gu.isPrimary()) {
+ breakBefore = BreakUtil.compareBreakClasses(breakBefore,
+ gu.getPrimary().getBreakBefore());
+ }
+ }
+ return breakBefore;
+ }
+
+ /**
+ * Returns the break class for this row. This is a combination of break-after set on
+ * the last children of any cells ending on this row.
+ * <p><strong>Note:</strong> this works only after getNextKuthElements on the
+ * corresponding TableCellLM have been called!</p>
+ *
+ * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
+ * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
+ */
+ public int getBreakAfter() {
+ int breakAfter = Constants.EN_AUTO;
+ for (Iterator iter = gridUnits.iterator(); iter.hasNext();) {
+ GridUnit gu = (GridUnit) iter.next();
+ if (gu.isPrimary()) {
+ breakAfter = BreakUtil.compareBreakClasses(breakAfter,
+ gu.getPrimary().getBreakAfter());
+ }
+ }
+ return breakAfter;
+ }
+
/** {@inheritDoc} */
public String toString() {
StringBuffer sb = new StringBuffer("EffRow {");
diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
index ac793f889..583abcaa3 100644
--- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
@@ -52,7 +52,7 @@ public class EmptyGridUnit extends GridUnit {
/** {@inheritDoc} */
public boolean isPrimary() {
- return true;
+ return false;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
index cff3c2ac1..c95f3f8c3 100644
--- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
@@ -22,6 +22,7 @@ package org.apache.fop.fo.flow.table;
import java.util.LinkedList;
import java.util.List;
+import org.apache.fop.fo.Constants;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.table.TableCellLayoutManager;
@@ -51,6 +52,9 @@ public class PrimaryGridUnit extends GridUnit {
private boolean isSeparateBorderModel;
private int halfBorderSeparationBPD;
+ private int breakBefore = Constants.EN_AUTO;
+ private int breakAfter = Constants.EN_AUTO;
+
/**
* Creates a new primary grid unit.
*
@@ -320,4 +324,42 @@ public class PrimaryGridUnit extends GridUnit {
cellLM = new TableCellLayoutManager(cell, this);
}
+ /**
+ * Returns the class of the before break for the first child element of this cell.
+ *
+ * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
+ * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
+ */
+ public int getBreakBefore() {
+ return breakBefore;
+ }
+
+ /**
+ * Don't use, reserved for TableCellLM. TODO
+ *
+ * @param breakBefore the breakBefore to set
+ */
+ public void setBreakBefore(int breakBefore) {
+ this.breakBefore = breakBefore;
+ }
+
+ /**
+ * Returns the class of the before after for the last child element of this cell.
+ *
+ * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link
+ * Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
+ */
+ public int getBreakAfter() {
+ return breakAfter;
+ }
+
+ /**
+ * Don't use, reserved for TableCellLM. TODO
+ *
+ * @param breakAfter the breakAfter to set
+ */
+ public void setBreakAfter(int breakAfter) {
+ this.breakAfter = breakAfter;
+ }
+
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
index 485c63ea2..d89f43370 100644
--- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
+++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
@@ -335,6 +335,7 @@ class ActiveCell {
} else {
nextStep.set(afterNextStep);
nextStep.start = previousStep.end + 1;
+ afterNextStep.start = nextStep.start;
if (afterNextStep.end < elementList.size() - 1) {
gotoNextLegalBreak();
}
@@ -406,17 +407,6 @@ class ActiveCell {
}
/**
- * Returns true if some content of this cell is part of the chosen next step.
- *
- * @return true if this cell's next step is inferior or equal to the next minimal step
- */
- boolean contributesContent() {
- // return includedInLastStep() && the cell hasn't finished yet, otherwise there's
- // nothing more to contribute
- return includedInLastStep() && nextStep.end >= nextStep.start;
- }
-
- /**
* Returns true if this cell would be finished after the given step. That is, it would
* be included in the step and the end of its content would be reached.
*
@@ -469,14 +459,6 @@ class ActiveCell {
}
}
- boolean isLastForcedBreak() {
- return ((KnuthElement)elementList.get(nextStep.end)).isForcedBreak();
- }
-
- int getLastBreakClass() {
- return ((KnuthPenalty)elementList.get(nextStep.end)).getBreakClass();
- }
-
boolean keepWithNextSignal() {
return keepWithNextSignal;
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
index 6d66da097..0127f4d81 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
@@ -40,6 +40,7 @@ import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.MinOptMaxUtil;
import org.apache.fop.traits.MinOptMax;
+import org.apache.fop.util.BreakUtil;
class RowGroupLayoutManager {
@@ -66,11 +67,13 @@ class RowGroupLayoutManager {
*/
int getBreakBefore() {
TableRow rowFO = rowGroup[0].getTableRow();
+ int breakBefore;
if (rowFO == null) {
- return Constants.EN_AUTO;
+ breakBefore = Constants.EN_AUTO;
} else {
- return rowFO.getBreakBefore();
+ breakBefore = rowFO.getBreakBefore();
}
+ return BreakUtil.compareBreakClasses(breakBefore, rowGroup[0].getBreakBefore());
}
/**
@@ -81,11 +84,14 @@ class RowGroupLayoutManager {
*/
int getBreakAfter() {
TableRow rowFO = rowGroup[rowGroup.length - 1].getTableRow();
+ int breakAfter;
if (rowFO == null) {
- return Constants.EN_AUTO;
+ breakAfter = Constants.EN_AUTO;
} else {
- return rowFO.getBreakAfter();
+ breakAfter = rowFO.getBreakAfter();
}
+ return BreakUtil.compareBreakClasses(breakAfter,
+ rowGroup[rowGroup.length - 1].getBreakAfter());
}
public LinkedList getNextKnuthElements(LayoutContext context, int alignment, int bodyType) {
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
index 26880faea..022ff0589 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
@@ -160,7 +160,17 @@ class RowPainter {
for (int i = 0; i < colCount; i++) {
GridUnit currentGU = currentRow.getGridUnit(i);
if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0
- && (lastInPart || currentGU.isLastGridUnitRowSpan())) {
+ && (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);
@@ -177,7 +187,8 @@ class RowPainter {
for (int i = 0; i < colCount; i++) {
GridUnit currentGU = currentRow.getGridUnit(i);
if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0
- && (lastInPart || currentGU.isLastGridUnitRowSpan())) {
+ && (lastInPart || currentGU.isLastGridUnitRowSpan())
+ && firstCellParts[i] != null) {
assert firstCellParts[i].pgu == currentGU.getPrimary();
int borderBeforeWhich;
if (firstCellParts[i].start == 0) {
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
index 9469a1121..fbc118723 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
@@ -210,7 +210,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
// 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));
@@ -246,6 +246,16 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
}
//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());
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
index baf1bd369..c09b9b076 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
@@ -48,6 +48,7 @@ import org.apache.fop.layoutmgr.Position;
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.
@@ -212,10 +213,14 @@ public class TableContentLayoutManager implements PercentBaseContext {
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();
@@ -226,7 +231,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
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
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
index 4eff1e931..0b494bf2d 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java
@@ -37,6 +37,7 @@ 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.
@@ -243,6 +244,12 @@ public class TableStepper {
if (signalKeepWithNext || getTableLM().mustKeepTogether()) {
p = KnuthPenalty.INFINITE;
}
+ if (rowFinished && activeRowIndex < rowGroup.length - 1) {
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ rowGroup[activeRowIndex].getBreakAfter());
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ rowGroup[activeRowIndex + 1].getBreakBefore());
+ }
if (nextBreakClass != Constants.EN_AUTO) {
log.trace("Forced break encountered");
p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0)
@@ -381,33 +388,8 @@ public class TableStepper {
nextBreakClass = Constants.EN_AUTO;
for (Iterator iter = activeCells.iterator(); iter.hasNext();) {
ActiveCell activeCell = (ActiveCell) iter.next();
- nextBreakClass = compareBreakClasses(nextBreakClass, activeCell.signalNextStep(step));
- }
- }
-
- // TODO replace that with a proper 1.5 enumeration ASAP
- // TODO this has nothing to do here
- private static int getBreakClassPriority(int breakClass) {
- switch (breakClass) {
- case Constants.EN_AUTO: return 0;
- case Constants.EN_COLUMN: return 1;
- case Constants.EN_PAGE: return 2;
- case Constants.EN_EVEN_PAGE: return 3;
- case Constants.EN_ODD_PAGE: return 3;
- default: throw new IllegalArgumentException();
- }
- }
-
- // TODO even-page and odd-page can't be compared to each other and instead create a
- // conflict situation. For now the first encountered break will win, but eventually
- // some warning message should be sent to the user.
- private static int compareBreakClasses(int b1, int b2) {
- int p1 = getBreakClassPriority(b1);
- int p2 = getBreakClassPriority(b2);
- if (p1 < p2) {
- return b2;
- } else {
- return b1;
+ nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass,
+ activeCell.signalNextStep(step));
}
}
diff --git a/src/java/org/apache/fop/util/BreakUtil.java b/src/java/org/apache/fop/util/BreakUtil.java
new file mode 100644
index 000000000..c0528464d
--- /dev/null
+++ b/src/java/org/apache/fop/util/BreakUtil.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.util;
+
+import org.apache.fop.fo.Constants;
+
+/**
+ * A utility class for manipulating break classes (the break-before and break-after properties).
+ */
+public final class BreakUtil {
+
+ private BreakUtil() { }
+
+ // TODO replace that with a proper 1.5 enumeration ASAP
+ private static int getBreakClassPriority(int breakClass) {
+ switch (breakClass) {
+ case Constants.EN_AUTO: return 0;
+ case Constants.EN_COLUMN: return 1;
+ case Constants.EN_PAGE: return 2;
+ case Constants.EN_EVEN_PAGE: return 3;
+ case Constants.EN_ODD_PAGE: return 3;
+ default: throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Compares the given break classes and return the one that wins. even-page and
+ * odd-page win over page, which wins over column, which wins over auto. If even-page
+ * and odd-page are compared to each other, which one will be returned is undefined.
+ *
+ * @param break1 a break class, one of {@link Constants#EN_AUTO},
+ * {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE},
+ * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}
+ * @param break2 another break class
+ * @return the break class that wins the comparison
+ */
+ public static int compareBreakClasses(int break1, int break2) {
+ // TODO implement some warning mechanism if even-page and odd-page are being compared
+ int p1 = getBreakClassPriority(break1);
+ int p2 = getBreakClassPriority(break2);
+ if (p1 < p2) {
+ return break2;
+ } else {
+ return break1;
+ }
+ }
+
+}