ListElement lastBreakElement = effectiveList.getElement(endElementIndex);
if (lastBreakElement.isPenalty()) {
KnuthPenalty pen = (KnuthPenalty)lastBreakElement;
- lastBreakClass = pen.getBreakClass();
+ if (pen.getPenalty() == KnuthPenalty.INFINITE) {
+ /**
+ * That means that there was a keep.within-page="always", but that
+ * it's OK to break at a column. TODO The break class is being
+ * abused to implement keep.within-column and keep.within-page.
+ * This is very misleading and must be revised.
+ */
+ lastBreakClass = Constants.EN_COLUMN;
+ } else {
+ lastBreakClass = pen.getBreakClass();
+ }
} else {
lastBreakClass = Constants.EN_COLUMN;
}
return true;
}
- public int getBreakBefore() {
- return BreakOpportunityHelper.getBreakBefore(this);
- }
-
}
return true;
}
- public int getBreakBefore() {
- return BreakOpportunityHelper.getBreakBefore(this);
- }
-
}
* @return true if an element has been added due to a break-before.
*/
protected boolean addKnuthElementsForBreakBefore(List returnList, LayoutContext context) {
- int breakBefore = BreakOpportunityHelper.getBreakBefore(this);
+ int breakBefore = getBreakBefore();
if (breakBefore == EN_PAGE
|| breakBefore == EN_COLUMN
|| breakBefore == EN_EVEN_PAGE
}
}
+ /**
+ * Returns the highest priority break-before value on this layout manager or its
+ * relevant descendants.
+ *
+ * @return the break-before value (Constants.EN_*)
+ * @see BreakOpportunity#getBreakBefore()
+ */
+ public int getBreakBefore() {
+ return BreakOpportunityHelper.getBreakBefore(this);
+ }
+
/**
* Creates Knuth elements for break-after and adds them to the return list.
* @param returnList return list to add the additional elements to
return;
case Constants.EN_COLUMN:
case Constants.EN_AUTO:
- case Constants.EN_PAGE:
case -1:
PageViewport pv = curPage.getPageViewport();
/*curPage = */pslm.makeNewPage(false);
}
return;
+ case Constants.EN_PAGE:
default:
log.debug("handling break-before after page " + pslm.getCurrentPageNum()
+ " breakVal=" + getBreakClassName(breakVal));
}
/**
- * Check if a blank page is needed to accomodate
+ * Check if a blank page is needed to accommodate
* desired even or odd page number.
* @param breakVal - value of break-before or break-after trait.
*/
package org.apache.fop.layoutmgr.list;
import java.util.LinkedList;
+import java.util.List;
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.fo.flow.ListItemLabel;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.BreakOpportunity;
import org.apache.fop.layoutmgr.Keep;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
/**
* LayoutManager for a list-item-label or list-item-body FO.
*/
-public class ListItemContentLayoutManager extends BlockStackingLayoutManager {
+public class ListItemContentLayoutManager extends BlockStackingLayoutManager implements BreakOpportunity {
private Block curBlockArea;
public Keep getKeepWithPrevious() {
return Keep.KEEP_AUTO;
}
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) {
+ List<ListElement> elements = new LinkedList<ListElement>();
+ do {
+ elements.addAll(super.getNextKnuthElements(context, alignment));
+ } while (!isFinished());
+ return elements;
+ }
+
}
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
+import org.apache.fop.layoutmgr.BreakOpportunity;
+import org.apache.fop.layoutmgr.BreakOpportunityHelper;
import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.ElementListObserver;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
+import org.apache.fop.util.BreakUtil;
/**
* LayoutManager for a list-item FO.
* The list item contains a list item label and a list item body.
*/
-public class ListItemLayoutManager extends BlockStackingLayoutManager
- implements ConditionalElementListener {
+public class ListItemLayoutManager extends BlockStackingLayoutManager implements ConditionalElementListener,
+ BreakOpportunity {
/** logging instance */
private static Log log = LogFactory.getLog(ListItemLayoutManager.class);
// label
childLC = makeChildLayoutContext(context);
+ childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
label.initialize();
labelList = label.getNextKnuthElements(childLC, alignment);
// body
childLC = makeChildLayoutContext(context);
+ childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
body.initialize();
bodyList = body.getNextKnuthElements(childLC, alignment);
//Additional penalty height from penalties in the source lists
int additionalPenaltyHeight = 0;
int stepPenalty = 0;
+ int breakClass = EN_AUTO;
KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]);
if (endEl instanceof KnuthPenalty) {
additionalPenaltyHeight = endEl.getWidth();
- stepPenalty = Math.max(stepPenalty, endEl.getPenalty());
+ stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math
+ .max(stepPenalty, endEl.getPenalty());
+ breakClass = BreakUtil.compareBreakClasses(breakClass,
+ ((KnuthPenalty) endEl).getBreakClass());
}
endEl = (KnuthElement)elementLists[1].get(end[1]);
if (endEl instanceof KnuthPenalty) {
additionalPenaltyHeight = Math.max(
additionalPenaltyHeight, endEl.getWidth());
- stepPenalty = Math.max(stepPenalty, endEl.getPenalty());
+ stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math
+ .max(stepPenalty, endEl.getPenalty());
+ breakClass = BreakUtil.compareBreakClasses(breakClass,
+ ((KnuthPenalty) endEl).getBreakClass());
}
int boxHeight = step - addedBoxHeight - penaltyHeight;
int p = stepPenalty;
if (p > -KnuthElement.INFINITE) {
p = Math.max(p, keep.getPenalty());
+ breakClass = keep.getContext();
}
- returnList.add(new BreakElement(stepPosition, penaltyHeight, p, keep.getContext(),
- context));
+ returnList.add(new BreakElement(stepPosition, penaltyHeight, p, breakClass, context));
}
}
body.reset();
}
+ @Override
+ public int getBreakBefore() {
+ int breakBefore = BreakOpportunityHelper.getBreakBefore(this);
+ breakBefore = BreakUtil.compareBreakClasses(breakBefore, label.getBreakBefore());
+ breakBefore = BreakUtil.compareBreakClasses(breakBefore, body.getBreakBefore());
+ return breakBefore;
+ }
}
documents. Example: the fix of marks layering will be such a case when it's done.
-->
<release version="FOP Trunk" date="TBD">
+ <action context="Layout" dev="VH" type="fix">
+ An IllegalArgumentException was thrown when break-before was used inside a list.
+ </action>
<action context="Layout" dev="VH" type="fix">
When restarting layout for the last page, discard glues and penalties at the beginning of
the restarted Knuth sequence.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<testcase>
+ <info>
+ <p>This test checks basic breaks in list bodies.</p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master margin="5pt" page-width="11cm" page-height="3cm"
+ master-name="page">
+ <fo:region-body />
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:list-block provisional-distance-between-starts="20pt"
+ provisional-label-separation="5pt">
+ <fo:list-item>
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>(a)</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ This content starts on page 1 and overflows to page 2. This content starts on page 1 and
+ overflows to page 2. This content starts on page 1 and overflows to page 2. This content
+ starts on page 1 and overflows to page 2. This content starts on page 1 and overflows to
+ page 2. This content starts on page 1 and overflows to page 2. This content starts on page 1
+ and overflows to page 2.
+ <fo:block break-before="page" />
+ This content is on page 3.
+ <fo:block break-before="page" />
+ This content is on page 4.
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item>
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>(b)</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ <fo:block break-before="page" />
+ This content is on page 5.
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item>
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>(c)</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block break-before="page">
+ This content is on page 6.
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ <fo:list-item break-before="page">
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>(d)</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ This content is on page 7.
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </fo:list-block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="3" xpath="//lineArea[starts-with(., 'This content is on page 3.')]/ancestor::pageViewport/@nr" />
+ <eval expected="4" xpath="//lineArea[starts-with(., 'This content is on page 4.')]/ancestor::pageViewport/@nr" />
+ <eval expected="5" xpath="//lineArea[starts-with(., '(b)')]/ancestor::pageViewport/@nr" />
+ <eval expected="6" xpath="//lineArea[starts-with(., '(c)')]/ancestor::pageViewport/@nr" />
+ <eval expected="7" xpath="//lineArea[starts-with(., '(d)')]/ancestor::pageViewport/@nr" />
+ </checks>
+</testcase>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<testcase>
+ <info>
+ <p>This test checks basic breaks in list bodies.</p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master margin="2cm" page-width="15.0cm" page-height="7.0cm"
+ master-name="page">
+ <fo:region-body column-count="2" />
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:list-block provisional-distance-between-starts="20pt" provisional-label-separation="5pt">
+ <fo:list-item>
+ <fo:list-item-label end-indent="label-end()">
+ <fo:block>(a)</fo:block>
+ </fo:list-item-label>
+ <fo:list-item-body start-indent="body-start()">
+ <fo:block>
+ On first page, first column
+ <fo:block id="block-3" break-before="page" />
+ On second page, first column, NOT first page, first column NEITHER first page, second column.
+ </fo:block>
+ </fo:list-item-body>
+ </fo:list-item>
+ </fo:list-block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="1" xpath="//lineArea[starts-with(., 'On first page')]/ancestor::pageViewport/@nr" />
+ <eval expected="2" xpath="//lineArea[starts-with(., 'On second page')]/ancestor::pageViewport/@nr" />
+ <eval expected="1" xpath="count(//block[@prod-id='block-3']/ancestor::flow)" />
+ </checks>
+</testcase>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<testcase>
+ <info>
+ <p>When layout is re-started for the last page, the space-before on the first element to appear
+ on that page must be discarded.</p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="40pt" page-width="110pt" margin="5pt">
+ <fo:region-body background-color="#F0F0F0"/>
+ </fo:simple-page-master>
+ <fo:page-sequence-master master-name="pages">
+ <fo:repeatable-page-master-alternatives>
+ <fo:conditional-page-master-reference master-reference="page" page-position="last"/>
+ <fo:conditional-page-master-reference master-reference="page" page-position="any"/>
+ </fo:repeatable-page-master-alternatives>
+ </fo:page-sequence-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="pages" font-size="8pt" line-height="10pt">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block-container height="30pt">
+ <fo:block>Filler 1</fo:block>
+ <fo:block>Filler 2</fo:block>
+ <fo:block>Filler 3</fo:block>
+ </fo:block-container>
+ <fo:block-container height="20pt" keep-with-next.within-page="always">
+ <fo:block>Before line 1</fo:block>
+ </fo:block-container>
+ <fo:block>Before the page break</fo:block>
+ <fo:block space-before="10pt">After the page break</fo:block>
+ <fo:block>After line 1</fo:block>
+ <fo:block>After line 2</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="3" xpath="count(//pageViewport)"/>
+ </checks>
+</testcase>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<testcase>
+ <info>
+ <p>This test checks basic breaks in table cells.</p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master margin="2cm" page-width="21.0cm" page-height="29.7cm"
+ master-name="A4-portrait">
+ <fo:region-body column-count="2" />
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="A4-portrait">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:table>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell>
+ <fo:block>Page 1, Column 1, Cell 1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell>
+ <fo:block>Page 1, Column 1, Cell 2</fo:block>
+ </fo:table-cell>
+ <fo:table-cell>
+ <fo:block>Page 1, Column 1, Cell 3</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ <fo:table-row>
+ <fo:table-cell>
+ <fo:block id="block-4">Page 2, Column 1, Cell 1</fo:block>
+ </fo:table-cell>
+ <fo:table-cell>
+ <fo:block break-before="page">Page 2, Column 1, Cell 2</fo:block>
+ </fo:table-cell>
+ <fo:table-cell>
+ <fo:block>Page 2, Column 1, Cell 3</fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="1" xpath="//lineArea[starts-with(., 'Page 1')]/ancestor::pageViewport/@nr" />
+ <eval expected="2" xpath="//lineArea[starts-with(., 'Page 2')]/ancestor::pageViewport/@nr" />
+ <eval expected="1" xpath="count(//block[@prod-id='block-4']/ancestor::flow)" />
+ </checks>
+</testcase>
\ No newline at end of file