return true;
}
+ /**
+ * @return true if one a single part should be produced if possible (ex. for block-containers)
+ */
+ protected boolean isSinglePartFavored() {
+ return false;
+ }
+
/**
* Returns the PageProvider if any. PageBreaker overrides this method because each
* page may have a different available BPD which needs to be accessible to the breaking
PageBreakingAlgorithm alg = new PageBreakingAlgorithm(getTopLevelLM(),
getPageProvider(),
alignment, alignmentLast, footnoteSeparatorLength,
- isPartOverflowRecoveryActivated(), autoHeight);
+ isPartOverflowRecoveryActivated(), autoHeight, isSinglePartFavored());
int iOptPageCount;
BlockSequence effectiveList;
boolean partOverflowRecovery,\r
int columnCount) {\r
super(topLevelLM, pageProvider, alignment, alignmentLast, \r
- footnoteSeparatorLength, partOverflowRecovery, false);\r
+ footnoteSeparatorLength, partOverflowRecovery, false, false);\r
this.columnCount = columnCount;\r
this.considerTooShort = true; //This is important!\r
}\r
return false;
}
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker#isSinglePartFavored() */
+ protected boolean isSinglePartFavored() {
+ return true;
+ }
+
public int getDifferenceOfFirstPart() {
PageBreakPosition pbp = (PageBreakPosition)this.deferredAlg.getPageBreaks().getFirst();
return pbp.difference;
*/
public abstract class BreakingAlgorithm {
- /** the logger */
- protected static Log log = LogFactory.getLog(BreakingAlgorithm.class);
+ /** the logger for the class */
+ protected static Log classLog = LogFactory.getLog(BreakingAlgorithm.class);
+
+ /** the logger for the instance */
+ protected Log log = classLog;
protected static final int INFINITE_RATIO = 1000;
protected void considerLegalBreak(KnuthElement element, int elementIdx) {
if (log.isTraceEnabled()) {
- log.trace("Feasible breakpoint at " + par.indexOf(element) + " " + totalWidth + "+" + totalStretch + "-" + totalShrink);
+ log.trace("considerLegalBreak() at " + elementIdx
+ + " (" + totalWidth + "+" + totalStretch + "-" + totalShrink + "), parts/lines: "+ startLine + "-" + endLine);
log.trace("\tCurrent active node list: " + activeNodeCount + " " + this.toString("\t"));
}
// the nodes in activeList must be ordered
// by line number and position;
if (log.isTraceEnabled()) {
- log.trace("\tInsert new break in list of " + activeNodeCount);
+ log.trace("\tInsert new break in list of " + activeNodeCount
+ + " from fitness class " + i);
}
KnuthNode newNode = createNode(elementIdx, line + 1, i,
newWidth, newStretch, newShrink);
/*
- * Copyright 2004-2005 The Apache Software Foundation.
+ * Copyright 2004-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import java.util.LinkedList;
import java.util.ListIterator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition;
class PageBreakingAlgorithm extends BreakingAlgorithm {
+ /** the logger for the class */
+ protected static Log classLog = LogFactory.getLog(PageBreakingAlgorithm.class);
+
private LayoutManager topLevelLM;
private PageSequenceLayoutManager.PageProvider pageProvider;
private LinkedList pageBreaks = null;
//Controls whether overflows should be warned about or not
private boolean autoHeight = false;
+ //Controls whether a single part should be forced if possible (ex. block-container)
+ private boolean favorSinglePart = false;
+
public PageBreakingAlgorithm(LayoutManager topLevelLM,
PageSequenceLayoutManager.PageProvider pageProvider,
int alignment, int alignmentLast,
MinOptMax footnoteSeparatorLength,
- boolean partOverflowRecovery, boolean autoHeight) {
+ boolean partOverflowRecovery, boolean autoHeight,
+ boolean favorSinglePart) {
super(alignment, alignmentLast, true, partOverflowRecovery, 0);
+ this.log = classLog;
this.topLevelLM = topLevelLM;
this.pageProvider = pageProvider;
best = new BestPageRecords();
footnoteSeparatorLength.max += 10000;
}
this.autoHeight = autoHeight;
+ this.favorSinglePart = favorSinglePart;
}
/**
if (footnotesPending) {
if (footnoteListIndex < footnotesList.size() - 1) {
// add demerits for the deferred footnotes
- demerits += (footnotesList.size() - 1 - footnoteListIndex) * deferredFootnoteDemerits;
+ demerits += (footnotesList.size() - 1 - footnoteListIndex)
+ * deferredFootnoteDemerits;
}
- if (footnoteElementIndex < ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1) {
+ if (footnoteElementIndex
+ < ((LinkedList) footnotesList.get(footnoteListIndex)).size() - 1) {
// add demerits for the footnote split between pages
demerits += splitFootnoteDemerits;
}
KnuthNode bestActiveNode = null;
for (int i = startLine; i < endLine; i++) {
for (KnuthNode node = getNode(i); node != null; node = node.next) {
- bestActiveNode = compareNodes(bestActiveNode, node);
+ if (favorSinglePart
+ && node.line > 1
+ && bestActiveNode != null
+ && Math.abs(bestActiveNode.difference) < bestActiveNode.availableShrink) {
+ //favor current best node, so just skip the current node because it would
+ //result in more than one part
+ } else {
+ bestActiveNode = compareNodes(bestActiveNode, node);
+ }
if (node != bestActiveNode) {
removeNode(i, node);
}
getPageProvider(),
alg.getAlignment(), alg.getAlignmentLast(),
footnoteSeparatorLength,
- isPartOverflowRecoveryActivated(), false);
+ isPartOverflowRecoveryActivated(), false, false);
//alg.setConstantLineWidth(flowBPD);
int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
newStartPos,
<changes>
<release version="FOP Trunk">
+ <action context="Code" dev="JM" type="update">
+ Content in block-containers makes better use of shrink to fit content vertically
+ into the available area. This can be used indirectly to justify content vertically
+ in a block-container.
+ </action>
<action context="Code" dev="JM" type="fix">
Bugfix: basic-links with internal destinations in documents with multiple
page-sequences sometimes pointed at the wrong page.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2006 The Apache Software Foundation
+
+ Licensed 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 if content is properly squeezed (spaces reduced) inside block-containers to fit content in the box if possible.
+ </p>
+ <p>
+ Note: if there are no break points and the content would overflow, the content may be squeezed by more than the available shrink.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in" margin="20pt">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="normal" text-align="justify">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block-container id="bc" height="10em" background-color="yellow">
+ <fo:block id="b1" space-after.optimum="3em" space-after.minimum="0pt">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam hendrerit posuere nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque placerat semper nulla.</fo:block>
+ <fo:block id="b2">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam hendrerit posuere nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque placerat semper nulla.</fo:block>
+ </fo:block-container>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="62400" xpath="//block[@prod-id = 'b1']/@bpda"/>
+ <eval expected="57600" xpath="//block[@prod-id = 'b2']/@bpda"/>
+ <eval expected="120000" xpath="//block[@prod-id = 'bc' and @is-reference-area = 'true']/@bpd"/>
+ <true xpath="//block[@prod-id = 'bc' and @is-reference-area = 'true']/@bpd = (//block[@prod-id = 'b1']/@bpda + //block[@prod-id = 'b2']/@bpda)"/>
+ <eval expected="4800" xpath="//block[@prod-id = 'b1']/@space-after"/>
+ </checks>
+</testcase>