From 6309a4f57e2dd731c1db0844d2f8f4ff4a059468 Mon Sep 17 00:00:00 2001 From: Vincent Hennebert Date: Mon, 30 Apr 2007 16:30:49 +0000 Subject: [PATCH] Bugfixes: - NPE when break-before is set on the first row of a table with headers - NPE when break-after is set on the last row of a table with headers or footers - Invalid break class exception when break-after is set on the last block of a cell in the last row of a table - double page break when break-before is set both on a table and its first row git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@533789 13f79535-47bb-0310-9956-ffa450edef68 --- .../table/TableContentLayoutManager.java | 18 +++- .../layoutmgr/table/TableLayoutManager.java | 92 ++++++------------- .../fop/layoutmgr/table/TableStepper.java | 4 +- .../table-cell_break-after_last-block.xml | 66 +++++++++++++ .../table-row_break-after_last-row-footer.xml | 74 +++++++++++++++ .../table-row_break-after_last-row-header.xml | 74 +++++++++++++++ ...able-row_break-before_first-row-header.xml | 74 +++++++++++++++ .../table_table-row_break-before.xml | 76 +++++++++++++++ 8 files changed, 412 insertions(+), 66 deletions(-) create mode 100644 test/layoutengine/standard-testcases/table-cell_break-after_last-block.xml create mode 100644 test/layoutengine/standard-testcases/table-row_break-after_last-row-footer.xml create mode 100644 test/layoutengine/standard-testcases/table-row_break-after_last-row-header.xml create mode 100644 test/layoutengine/standard-testcases/table-row_break-before_first-row-header.xml create mode 100644 test/layoutengine/standard-testcases/table_table-row_break-before.xml diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 9794c7310..8abe1a3e8 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -179,12 +179,24 @@ public class TableContentLayoutManager implements PercentBaseContext { LinkedList returnList = getKnuthElementsForRowIterator( bodyIter, context, alignment, TableRowIterator.BODY); if (headerAsFirst != null) { - returnList.add(0, headerAsFirst); + int insertionPoint = 0; + if (returnList.size() > 0 && ((ListElement)returnList.getFirst()).isForcedBreak()) { + insertionPoint++; + } + returnList.add(insertionPoint, headerAsFirst); } else if (headerAsSecondToLast != null) { - returnList.add(headerAsSecondToLast); + int insertionPoint = returnList.size(); + if (returnList.size() > 0 && ((ListElement)returnList.getLast()).isForcedBreak()) { + insertionPoint--; + } + returnList.add(insertionPoint, headerAsSecondToLast); } if (footerAsLast != null) { - returnList.add(footerAsLast); + int insertionPoint = returnList.size(); + if (returnList.size() > 0 && ((ListElement)returnList.getLast()).isForcedBreak()) { + insertionPoint--; + } + returnList.add(insertionPoint, footerAsLast); } return returnList; } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 2d305d5fa..155111ac4 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -29,6 +29,7 @@ import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.ListElement; +import org.apache.fop.layoutmgr.NonLeafPosition; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.RelSide; @@ -248,7 +249,34 @@ public class TableLayoutManager extends BlockStackingLayoutManager log.debug("TableContentLM signals pending keep-with-previous"); context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); } - + + // Check if the table's content starts/ends with a forced break + // TODO this is hacky and will need to be handled better eventually + if (contentKnuthElements.size() > 0) { + ListElement element = (ListElement)contentKnuthElements.getFirst(); + if (element.isForcedBreak()) { + // The first row of the table(-body), or (the content of) one of its cells + // has a forced break-before + int breakBeforeTable = ((Table) fobj).getBreakBefore(); + if (breakBeforeTable == EN_PAGE + || breakBeforeTable == EN_COLUMN + || breakBeforeTable == EN_EVEN_PAGE + || breakBeforeTable == EN_ODD_PAGE) { + // There is already a forced break before the table; remove this one + // to prevent a double break + contentKnuthElements.removeFirst(); + } else { + element.setPosition(new NonLeafPosition(this, null)); + } + } + element = (ListElement)contentKnuthElements.getLast(); + if (element.isForcedBreak()) { + // The last row of the table(-body), or (the content of) one of its cells + // has a forced break-after + element.setPosition(new NonLeafPosition(this, null)); + } + } + //Set index values on elements coming from the content LM Iterator iter = contentKnuthElements.iterator(); while (iter.hasNext()) { @@ -256,67 +284,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager notifyPos(el.getPosition()); } log.debug(contentKnuthElements); - - if (contentKnuthElements.size() == 1 - && ((ListElement)contentKnuthElements.getFirst()).isForcedBreak()) { - // a descendant of this block has break-before - if (returnList.size() == 0) { - // the first child (or its first child ...) has - // break-before; - // all this block, including space before, will be put in - // the - // following page - //FIX ME - //bSpaceBeforeServed = false; - } - contentList.addAll(contentKnuthElements); - - // "wrap" the Position inside each element - // moving the elements from contentList to returnList - contentKnuthElements = new LinkedList(); - wrapPositionElements(contentList, returnList); - - return returnList; - } else { - /* - if (prevLM != null) { - // there is a block handled by prevLM - // before the one handled by curLM - if (mustKeepTogether() - || prevLM.mustKeepWithNext() - || curLM.mustKeepWithPrevious()) { - // add an infinite penalty to forbid a break between - // blocks - contentList.add(new KnuthPenalty(0, - KnuthElement.INFINITE, false, - new Position(this), false)); - } else if (!((KnuthElement) contentList.getLast()).isGlue()) { - // add a null penalty to allow a break between blocks - contentList.add(new KnuthPenalty(0, 0, false, - new Position(this), false)); - } else { - // the last element in contentList is a glue; - // it is a feasible breakpoint, there is no need to add - // a penalty - } - }*/ - contentList.addAll(contentKnuthElements); - if (contentKnuthElements.size() > 0) { - if (((ListElement)contentKnuthElements.getLast()).isForcedBreak()) { - // a descendant of this block has break-after - if (false /*curLM.isFinished()*/) { - // there is no other content in this block; - // it's useless to add space after before a page break - setFinished(true); - } - - contentKnuthElements = new LinkedList(); - wrapPositionElements(contentList, returnList); - - return returnList; - } - } - } + contentList.addAll(contentKnuthElements); wrapPositionElements(contentList, returnList); if (getTable().isSeparateBorderModel()) { addKnuthElementsForBorderPaddingAfter(returnList, true); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 2c676ae0b..60ccf2b0a 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -299,6 +299,7 @@ public class TableStepper { addedBoxLen += boxLen; boolean forcedBreak = false; + int breakClass = -1; //Put all involved grid units into a list List gridUnitParts = new java.util.ArrayList(maxColumnCount); for (int i = 0; i < columnCount; i++) { @@ -314,6 +315,7 @@ public class TableStepper { gridUnitParts.add(new GridUnitPart(pgu, start[i], end[i])); if (((KnuthElement)elementLists[i].get(end[i])).isForcedBreak()) { forcedBreak = true; + breakClass = ((KnuthPenalty)elementLists[i].get(end[i])).getBreakClass(); } } if (end[i] + 1 == elementLists[i].size()) { @@ -410,7 +412,7 @@ public class TableStepper { } p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0) } - returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, -1, context)); + returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context)); if (log.isDebugEnabled()) { log.debug("step=" + step + " (+" + increase + ")" diff --git a/test/layoutengine/standard-testcases/table-cell_break-after_last-block.xml b/test/layoutengine/standard-testcases/table-cell_break-after_last-block.xml new file mode 100644 index 000000000..d48321813 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-cell_break-after_last-block.xml @@ -0,0 +1,66 @@ + + + + + +

+ This test checks that break-after on the last block child of a cell in the last row of a table + without headers nor footers works properly. +

+
+ + + + + + + + + + Before the table + + + + + + Cell 1.1 + + + Cell 1.2 Line 1 + Cell 1.2 Line 2 + + + + + After the table + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/standard-testcases/table-row_break-after_last-row-footer.xml b/test/layoutengine/standard-testcases/table-row_break-after_last-row-footer.xml new file mode 100644 index 000000000..41e7369df --- /dev/null +++ b/test/layoutengine/standard-testcases/table-row_break-after_last-row-footer.xml @@ -0,0 +1,74 @@ + + + + + +

+ This test checks that break-after on the last row of a table with footers works properly. +

+
+ + + + + + + + + + Before the table + + + + + + Footer 1 + + + Footer 2 + + + + + + + Cell 1.1 + + + Cell 1.2 + + + + + After the table + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/standard-testcases/table-row_break-after_last-row-header.xml b/test/layoutengine/standard-testcases/table-row_break-after_last-row-header.xml new file mode 100644 index 000000000..b23ec7292 --- /dev/null +++ b/test/layoutengine/standard-testcases/table-row_break-after_last-row-header.xml @@ -0,0 +1,74 @@ + + + + + +

+ This test checks that break-after on the last row of a table with headers works properly. +

+
+ + + + + + + + + + Before the table + + + + + + Header 1 + + + Header 2 + + + + + + + Cell 1.1 + + + Cell 1.2 + + + + + After the table + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/standard-testcases/table-row_break-before_first-row-header.xml b/test/layoutengine/standard-testcases/table-row_break-before_first-row-header.xml new file mode 100644 index 000000000..f05f0096d --- /dev/null +++ b/test/layoutengine/standard-testcases/table-row_break-before_first-row-header.xml @@ -0,0 +1,74 @@ + + + + + +

+ This test checks that break-before on the first row of a table with headers works properly. +

+
+ + + + + + + + + + Before the table + + + + + + Header 1 + + + Header 2 + + + + + + + Cell 1.1 + + + Cell 1.2 + + + + + After the table + + + + + + + + + + + + + + +
diff --git a/test/layoutengine/standard-testcases/table_table-row_break-before.xml b/test/layoutengine/standard-testcases/table_table-row_break-before.xml new file mode 100644 index 000000000..e77ec4f65 --- /dev/null +++ b/test/layoutengine/standard-testcases/table_table-row_break-before.xml @@ -0,0 +1,76 @@ + + + + + +

+ This test checks that there is only one page break when break-before is specified both on a + table and its first row. +

+
+ + + + + + + + + + Before the table + + + + + + Header 1 + + + Header 2 + + + + + + + Cell 1.1 + + + Cell 1.2 + + + + + After the table + + + + + + + + + + + + + + +
-- 2.39.5