Also added one disabled-testcase for a remaining issue with page-level keeps in multi-column layout. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@807014 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_0
@@ -23,8 +23,7 @@ import java.util.Iterator; | |||
import java.util.List; | |||
import org.apache.fop.fo.Constants; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.table.TableRowIterator; | |||
import org.apache.fop.traits.MinOptMax; | |||
import org.apache.fop.util.BreakUtil; | |||
@@ -170,20 +169,19 @@ public class EffRow { | |||
* | |||
* @return the strength of the keep-with-previous constraint | |||
*/ | |||
public int getKeepWithPreviousStrength() { | |||
int strength = BlockLevelLayoutManager.KEEP_AUTO; | |||
public Keep getKeepWithPrevious() { | |||
Keep keep = Keep.KEEP_AUTO; | |||
TableRow row = getTableRow(); | |||
if (row != null) { | |||
strength = Math.max(strength, | |||
KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithPrevious())); | |||
keep = Keep.getKeep(row.getKeepWithPrevious()); | |||
} | |||
for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { | |||
GridUnit gu = (GridUnit) iter.next(); | |||
if (gu.isPrimary()) { | |||
strength = Math.max(strength, gu.getPrimary().getKeepWithPreviousStrength()); | |||
keep = keep.compare(gu.getPrimary().getKeepWithPrevious()); | |||
} | |||
} | |||
return strength; | |||
return keep; | |||
} | |||
/** | |||
@@ -192,20 +190,19 @@ public class EffRow { | |||
* | |||
* @return the strength of the keep-with-next constraint | |||
*/ | |||
public int getKeepWithNextStrength() { | |||
int strength = BlockLevelLayoutManager.KEEP_AUTO; | |||
public Keep getKeepWithNext() { | |||
Keep keep = Keep.KEEP_AUTO; | |||
TableRow row = getTableRow(); | |||
if (row != null) { | |||
strength = Math.max(strength, | |||
KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithNext())); | |||
keep = Keep.getKeep(row.getKeepWithNext()); | |||
} | |||
for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { | |||
GridUnit gu = (GridUnit) iter.next(); | |||
if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) { | |||
strength = Math.max(strength, gu.getPrimary().getKeepWithNextStrength()); | |||
keep = keep.compare(gu.getPrimary().getKeepWithNext()); | |||
} | |||
} | |||
return strength; | |||
return keep; | |||
} | |||
/** | |||
@@ -213,16 +210,13 @@ public class EffRow { | |||
* not take the parent table's keeps into account! | |||
* @return the keep-together strength | |||
*/ | |||
public int getKeepTogetherStrength() { | |||
public Keep getKeepTogether() { | |||
TableRow row = getTableRow(); | |||
int strength = BlockLevelLayoutManager.KEEP_AUTO; | |||
Keep keep = Keep.KEEP_AUTO; | |||
if (row != null) { | |||
strength = Math.max(strength, KeepUtil.getKeepStrength( | |||
row.getKeepTogether().getWithinPage())); | |||
strength = Math.max(strength, KeepUtil.getKeepStrength( | |||
row.getKeepTogether().getWithinColumn())); | |||
keep = Keep.getKeep(row.getKeepTogether()); | |||
} | |||
return strength; | |||
return keep; | |||
} | |||
/** |
@@ -19,14 +19,13 @@ | |||
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.FONode; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.layoutmgr.ElementListUtils; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.table.TableCellLayoutManager; | |||
/** | |||
@@ -54,8 +53,8 @@ public class PrimaryGridUnit extends GridUnit { | |||
private boolean isSeparateBorderModel; | |||
private int halfBorderSeparationBPD; | |||
private int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; | |||
private int keepWithNext = BlockLevelLayoutManager.KEEP_AUTO; | |||
private Keep keepWithPrevious = Keep.KEEP_AUTO; | |||
private Keep keepWithNext = Keep.KEEP_AUTO; | |||
private int breakBefore = Constants.EN_AUTO; | |||
private int breakAfter = Constants.EN_AUTO; | |||
@@ -334,16 +333,16 @@ public class PrimaryGridUnit extends GridUnit { | |||
* | |||
* @return the keep-with-previous strength | |||
*/ | |||
public int getKeepWithPreviousStrength() { | |||
public Keep getKeepWithPrevious() { | |||
return keepWithPrevious; | |||
} | |||
/** | |||
* Don't use, reserved for TableCellLM. TODO | |||
* @param strength the keep strength | |||
* @param keep the keep strength | |||
*/ | |||
public void setKeepWithPreviousStrength(int strength) { | |||
this.keepWithPrevious = strength; | |||
public void setKeepWithPrevious(Keep keep) { | |||
this.keepWithPrevious = keep; | |||
} | |||
/** | |||
@@ -352,16 +351,16 @@ public class PrimaryGridUnit extends GridUnit { | |||
* | |||
* @return the keep-with-next strength | |||
*/ | |||
public int getKeepWithNextStrength() { | |||
public Keep getKeepWithNext() { | |||
return keepWithNext; | |||
} | |||
/** | |||
* Don't use, reserved for TableCellLM. TODO | |||
* @param strength the keep strength | |||
* @param keep the keep strength | |||
*/ | |||
public void setKeepWithNextStrength(int strength) { | |||
this.keepWithNext = strength; | |||
public void setKeepWithNext(Keep keep) { | |||
this.keepWithNext = keep; | |||
} | |||
/** |
@@ -37,6 +37,7 @@ import org.apache.fop.datatypes.FODimension; | |||
import org.apache.fop.datatypes.Length; | |||
import org.apache.fop.fo.flow.BlockContainer; | |||
import org.apache.fop.fo.properties.CommonAbsolutePosition; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.traits.MinOptMax; | |||
import org.apache.fop.traits.SpaceVal; | |||
import org.apache.fop.util.ListUtil; | |||
@@ -261,7 +262,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager | |||
if (!firstVisibleMarkServed) { | |||
addKnuthElementsForSpaceBefore(returnList, alignment); | |||
context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); | |||
context.updateKeepWithPreviousPending(getKeepWithPrevious()); | |||
} | |||
addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); | |||
@@ -271,9 +272,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager | |||
//Spaces, border and padding to be repeated at each break | |||
addPendingMarks(context); | |||
BlockLevelLayoutManager curLM; // currently active LM | |||
BlockLevelLayoutManager prevLM = null; // previously active LM | |||
while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { | |||
LayoutManager curLM; // currently active LM | |||
LayoutManager prevLM = null; // previously active LM | |||
while ((curLM = getChildLM()) != null) { | |||
LayoutContext childLC = new LayoutContext(0); | |||
childLC.copyPendingMarksFrom(context); | |||
// curLM is a ? | |||
@@ -323,8 +324,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager | |||
//Avoid NoSuchElementException below (happens with empty blocks) | |||
continue; | |||
} | |||
if (((ListElement) ListUtil.getLast(returnedList)) | |||
.isForcedBreak()) { | |||
if (ElementListUtils.endsWithForcedBreak(returnedList)) { | |||
// a descendant of this block has break-after | |||
if (curLM.isFinished()) { | |||
// there is no other content in this block; | |||
@@ -391,7 +391,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager | |||
context.clearPendingMarks(); | |||
addKnuthElementsForBreakAfter(returnList, context); | |||
context.updateKeepWithNextPending(getKeepWithNextStrength()); | |||
context.updateKeepWithNextPending(getKeepWithNext()); | |||
setFinished(true); | |||
return returnList; | |||
@@ -1011,23 +1011,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getBlockContainerFO().getKeepTogether()); | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
public KeepProperty getKeepTogetherProperty() { | |||
return getBlockContainerFO().getKeepTogether(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getBlockContainerFO().getKeepWithNext()); | |||
public KeepProperty getKeepWithPreviousProperty() { | |||
return getBlockContainerFO().getKeepWithPrevious(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getBlockContainerFO().getKeepWithPrevious()); | |||
public KeepProperty getKeepWithNextProperty() { | |||
return getBlockContainerFO().getKeepWithNext(); | |||
} | |||
/** |
@@ -207,21 +207,18 @@ public class BlockLayoutManager extends BlockStackingLayoutManager | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
KeepProperty keep = getBlockFO().getKeepTogether(); | |||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength(keep); | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
public KeepProperty getKeepTogetherProperty() { | |||
return getBlockFO().getKeepTogether(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithNext()); | |||
public KeepProperty getKeepWithPreviousProperty() { | |||
return getBlockFO().getKeepWithPrevious(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithPrevious()); | |||
public KeepProperty getKeepWithNextProperty() { | |||
return getBlockFO().getKeepWithNext(); | |||
} | |||
/** {@inheritDoc} */ |
@@ -19,6 +19,8 @@ | |||
package org.apache.fop.layoutmgr; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
/** | |||
* The interface for LayoutManagers which generate block areas | |||
*/ | |||
@@ -35,11 +37,6 @@ public interface BlockLevelLayoutManager extends LayoutManager { | |||
/** Adjustment class: adjustment for line height */ | |||
int LINE_HEIGHT_ADJUSTMENT = 3; | |||
/** The integer value for "auto" keep strength */ | |||
int KEEP_AUTO = Integer.MIN_VALUE; | |||
/** The integer value for "always" keep strength */ | |||
int KEEP_ALWAYS = Integer.MAX_VALUE; | |||
int negotiateBPDAdjustment(int adj, KnuthElement lastElement); | |||
void discardSpace(KnuthGlue spaceGlue); | |||
@@ -48,7 +45,7 @@ public interface BlockLevelLayoutManager extends LayoutManager { | |||
* Returns the keep-together strength for this element. | |||
* @return the keep-together strength | |||
*/ | |||
int getKeepTogetherStrength(); | |||
Keep getKeepTogether(); | |||
/** | |||
* @return true if this element must be kept together | |||
@@ -59,7 +56,7 @@ public interface BlockLevelLayoutManager extends LayoutManager { | |||
* Returns the keep-with-previous strength for this element. | |||
* @return the keep-with-previous strength | |||
*/ | |||
int getKeepWithPreviousStrength(); | |||
Keep getKeepWithPrevious(); | |||
/** | |||
* @return true if this element must be kept with the previous element. | |||
@@ -70,11 +67,28 @@ public interface BlockLevelLayoutManager extends LayoutManager { | |||
* Returns the keep-with-next strength for this element. | |||
* @return the keep-with-next strength | |||
*/ | |||
int getKeepWithNextStrength(); | |||
Keep getKeepWithNext(); | |||
/** | |||
* @return true if this element must be kept with the next element. | |||
*/ | |||
boolean mustKeepWithNext(); | |||
/** | |||
* Returns the keep-together property specified on the FObj. | |||
* @return the keep-together property | |||
*/ | |||
KeepProperty getKeepTogetherProperty(); | |||
/** | |||
* Returns the keep-with-previous property specified on the FObj. | |||
* @return the keep-together property | |||
*/ | |||
KeepProperty getKeepWithPreviousProperty(); | |||
/** | |||
* Returns the keep-with-next property specified on the FObj. | |||
* @return the keep-together property | |||
*/ | |||
KeepProperty getKeepWithNextProperty(); | |||
} |
@@ -31,9 +31,11 @@ import org.apache.fop.area.Area; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.area.BlockParent; | |||
import org.apache.fop.fo.FObj; | |||
import org.apache.fop.fo.Constants; | |||
import org.apache.fop.fo.properties.BreakPropertySet; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.fo.properties.SpaceProperty; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.layoutmgr.inline.InlineLayoutManager; | |||
import org.apache.fop.layoutmgr.inline.LineLayoutManager; | |||
import org.apache.fop.traits.MinOptMax; | |||
@@ -258,7 +260,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
if (!firstVisibleMarkServed) { | |||
addKnuthElementsForSpaceBefore(elements, alignment); | |||
context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); | |||
context.updateKeepWithPreviousPending(getKeepWithPrevious()); | |||
} | |||
addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed); | |||
@@ -349,7 +351,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
elements.add(forcedBreakAfterLast); | |||
} | |||
context.updateKeepWithNextPending(getKeepWithNextStrength()); | |||
context.updateKeepWithNextPending(getKeepWithNext()); | |||
setFinished(true); | |||
@@ -375,31 +377,31 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
/** | |||
* Adds a break element to the content list between individual child elements. | |||
* @param contentList the content list to populate | |||
* @param context the current layout context | |||
* @param contentList | |||
* @param parentLC | |||
* @param childLC the currently active child layout context | |||
*/ | |||
protected void addInBetweenBreak(List contentList, LayoutContext context, | |||
LayoutContext childLC) { | |||
protected void addInBetweenBreak(List contentList, LayoutContext parentLC, | |||
LayoutContext childLC) { | |||
if (mustKeepTogether() | |||
|| context.isKeepWithNextPending() | |||
|| parentLC.isKeepWithNextPending() | |||
|| childLC.isKeepWithPreviousPending()) { | |||
int strength = getKeepTogetherStrength(); | |||
Keep keep = getKeepTogether(); | |||
//Handle pending keep-with-next | |||
strength = Math.max(strength, context.getKeepWithNextPending()); | |||
context.clearKeepWithNextPending(); | |||
keep = keep.compare(parentLC.getKeepWithNextPending()); | |||
parentLC.clearKeepWithNextPending(); | |||
//Handle pending keep-with-previous from child LM | |||
strength = Math.max(strength, childLC.getKeepWithPreviousPending()); | |||
keep = keep.compare(childLC.getKeepWithPreviousPending()); | |||
childLC.clearKeepWithPreviousPending(); | |||
int penalty = KeepUtil.getPenaltyForKeep(strength); | |||
// add a penalty to forbid or discourage a break between blocks | |||
contentList.add(new BreakElement( | |||
new Position(this), penalty, context)); | |||
new Position(this), keep.getPenalty(), | |||
keep.getContext(), parentLC)); | |||
return; | |||
} | |||
@@ -430,7 +432,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
// add a null penalty to allow a break between blocks | |||
contentList.add(new BreakElement( | |||
new Position(this), 0, context)); | |||
new Position(this), 0, Constants.EN_AUTO, parentLC)); | |||
} | |||
} | |||
@@ -766,33 +768,77 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager | |||
* Retrieves and returns the keep-together strength from the parent element. | |||
* @return the keep-together strength | |||
*/ | |||
protected int getParentKeepTogetherStrength() { | |||
int strength = KEEP_AUTO; | |||
protected Keep getParentKeepTogether() { | |||
Keep keep = Keep.KEEP_AUTO; | |||
if (getParent() instanceof BlockLevelLayoutManager) { | |||
strength = ((BlockLevelLayoutManager)getParent()).getKeepTogetherStrength(); | |||
keep = ((BlockLevelLayoutManager)getParent()).getKeepTogether(); | |||
} else if (getParent() instanceof InlineLayoutManager) { | |||
if (((InlineLayoutManager) getParent()).mustKeepTogether()) { | |||
strength = KEEP_ALWAYS; | |||
keep = Keep.KEEP_ALWAYS; | |||
} | |||
//TODO Fix me | |||
//strength = ((InlineLayoutManager) getParent()).getKeepTogetherStrength(); | |||
} | |||
return strength; | |||
return keep; | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean mustKeepTogether() { | |||
return getKeepTogetherStrength() > KEEP_AUTO; | |||
return !getKeepTogether().isAuto(); | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean mustKeepWithPrevious() { | |||
return getKeepWithPreviousStrength() > KEEP_AUTO; | |||
return !getKeepWithPrevious().isAuto(); | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean mustKeepWithNext() { | |||
return getKeepWithNextStrength() > KEEP_AUTO; | |||
return !getKeepWithNext().isAuto(); | |||
} | |||
/** {@inheritDoc} */ | |||
public Keep getKeepTogether() { | |||
Keep keep = Keep.getKeep(getKeepTogetherProperty()); | |||
keep = keep.compare(getParentKeepTogether()); | |||
return keep; | |||
} | |||
/** {@inheritDoc} */ | |||
public Keep getKeepWithPrevious() { | |||
return Keep.getKeep(getKeepWithPreviousProperty()); | |||
} | |||
/** {@inheritDoc} */ | |||
public Keep getKeepWithNext() { | |||
return Keep.getKeep(getKeepWithNextProperty()); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
* Default implementation throws {@code IllegalStateException} | |||
* Must be implemented by the subclass, if applicable. | |||
*/ | |||
public KeepProperty getKeepTogetherProperty() { | |||
throw new IllegalStateException(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
* Default implementation throws {@code IllegalStateException} | |||
* Must be implemented by the subclass, if applicable. | |||
*/ | |||
public KeepProperty getKeepWithPreviousProperty() { | |||
throw new IllegalStateException(); | |||
} | |||
/** | |||
* {@inheritDoc} | |||
* Default implementation throws {@code IllegalStateException} | |||
* Must be implemented by the subclass, if applicable. | |||
*/ | |||
public KeepProperty getKeepWithNextProperty() { | |||
throw new IllegalStateException(); | |||
} | |||
/** |
@@ -41,7 +41,22 @@ public class BreakElement extends UnresolvedListElement { | |||
* @param context the layout context which contains the pending conditional elements | |||
*/ | |||
public BreakElement(Position position, int penaltyValue, LayoutContext context) { | |||
this(position, 0, penaltyValue, -1, context); | |||
this(position, penaltyValue, -1, context); | |||
} | |||
/** | |||
* Create a new BreakElement for the given {@code position}, {@code penaltyValue} | |||
* and {@code breakClass}. (Used principally to generate break-possibilities in | |||
* ranges of content that must be kept together within the context corresponding | |||
* to the {@code breakClass}; expected to be one of {@link Constants#EN_AUTO}, | |||
* {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or {@link Constants#EN_PAGE}) | |||
* @param position the corresponding {@link Position} | |||
* @param penaltyValue the penalty value | |||
* @param breakClass the break class | |||
* @param context the {@link LayoutContext} | |||
*/ | |||
public BreakElement(Position position, int penaltyValue, int breakClass, LayoutContext context) { | |||
this(position, 0, penaltyValue, breakClass, context); | |||
} | |||
/** | |||
@@ -65,6 +80,10 @@ public class BreakElement extends UnresolvedListElement { | |||
this.pendingAfterMarks = context.getPendingAfterMarks(); | |||
} | |||
private static String getBreakClassName(int breakClass) { | |||
return AbstractBreaker.getBreakClassName(breakClass); | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean isConditional() { | |||
return false; //Does not really apply here | |||
@@ -143,27 +162,17 @@ public class BreakElement extends UnresolvedListElement { | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(); | |||
StringBuffer sb = new StringBuffer(64); | |||
sb.append("BreakPossibility[p:"); | |||
sb.append(this.penaltyValue); | |||
sb.append(KnuthPenalty.valueOf(this.penaltyValue)); | |||
if (isForcedBreak()) { | |||
sb.append(" (forced break"); | |||
switch (getBreakClass()) { | |||
case Constants.EN_PAGE: | |||
sb.append(", page"); | |||
break; | |||
case Constants.EN_COLUMN: | |||
sb.append(", column"); | |||
break; | |||
case Constants.EN_EVEN_PAGE: | |||
sb.append(", even page"); | |||
break; | |||
case Constants.EN_ODD_PAGE: | |||
sb.append(", odd page"); | |||
break; | |||
default: | |||
} | |||
sb.append(")"); | |||
sb.append(" (forced break, ") | |||
.append(getBreakClassName(this.breakClass)) | |||
.append(")"); | |||
} else if (this.penaltyValue >= 0 && this.breakClass != -1) { | |||
sb.append(" (keep constraint, ") | |||
.append(getBreakClassName(this.breakClass)) | |||
.append(")"); | |||
} | |||
sb.append("; w:"); | |||
sb.append(penaltyWidth); |
@@ -610,6 +610,14 @@ public abstract class BreakingAlgorithm { | |||
best.getNode(fitness)); | |||
} | |||
/** | |||
* Return the last node that yielded a too short line. | |||
* @return the node corresponding to the last too short line | |||
*/ | |||
protected final KnuthNode getLastTooShort() { | |||
return this.lastTooShort; | |||
} | |||
/** | |||
* Generic handler for a {@link KnuthElement} at the given {@code position}, | |||
* taking into account whether the preceding element was a box, and which | |||
@@ -647,7 +655,7 @@ public abstract class BreakingAlgorithm { | |||
/** | |||
* Handle a {@link KnuthBox}. | |||
* <em>Note: default implementation just adds the box's width | |||
* <br/><em>Note: default implementation just adds the box's width | |||
* to the total content width. Subclasses that do not keep track | |||
* of this themselves, but override this method, should remember | |||
* to call {@code super.handleBox(box)} to avoid unwanted side-effects.</em> | |||
@@ -808,14 +816,16 @@ public abstract class BreakingAlgorithm { | |||
lastDeactivated = null; | |||
lastTooLong = null; | |||
for (int line = startLine; line < endLine; line++) { | |||
if (!elementCanEndLine(element, line)) { | |||
continue; | |||
} | |||
for (KnuthNode node = getNode(line); node != null; node = node.next) { | |||
if (node.position == elementIdx) { | |||
continue; | |||
} | |||
int difference = computeDifference(node, element, elementIdx); | |||
if (!elementCanEndLine(element, endLine, difference)) { | |||
log.trace("Skipping legal break"); | |||
break; | |||
} | |||
double r = computeAdjustmentRatio(node, difference); | |||
int availableShrink = totalShrink - node.totalShrink; | |||
int availableStretch = totalStretch - node.totalStretch; | |||
@@ -854,9 +864,10 @@ public abstract class BreakingAlgorithm { | |||
* number. | |||
* @param element the element | |||
* @param line the line number | |||
* @param difference | |||
* @return {@code true} if the element can end the line | |||
*/ | |||
protected boolean elementCanEndLine(KnuthElement element, int line) { | |||
protected boolean elementCanEndLine(KnuthElement element, int line, int difference) { | |||
return (!element.isPenalty() | |||
|| element.getP() < KnuthElement.INFINITE); | |||
} |
@@ -181,18 +181,18 @@ public class FlowLayoutManager extends BlockStackingLayoutManager | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepTogether() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithNext() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithPrevious() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ |
@@ -92,18 +92,18 @@ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
return getParentKeepTogetherStrength(); | |||
public Keep getKeepTogether() { | |||
return getParentKeepTogether(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithNext() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithPrevious() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
} |
@@ -0,0 +1,152 @@ | |||
/* | |||
* 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.layoutmgr; | |||
import org.apache.fop.fo.Constants; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.fo.properties.Property; | |||
/** | |||
* Object representing a keep constraint, corresponding | |||
* to the XSL-FO <a href="http://www.w3.org/TR/xsl/#d0e26492">keep properties</a>. | |||
*/ | |||
public class Keep { | |||
/** The integer value for "auto" keep strength. */ | |||
private static final int STRENGTH_AUTO = Integer.MIN_VALUE; | |||
/** The integer value for "always" keep strength. */ | |||
private static final int STRENGTH_ALWAYS = Integer.MAX_VALUE; | |||
public static final Keep KEEP_AUTO = new Keep(STRENGTH_AUTO, Constants.EN_AUTO); | |||
public static final Keep KEEP_ALWAYS = new Keep(STRENGTH_ALWAYS, Constants.EN_LINE); | |||
private int strength; | |||
private int context; | |||
private Keep(int strength, int context) { | |||
this.strength = strength; | |||
this.context = context; | |||
} | |||
private static int getKeepStrength(Property keep) { | |||
if (keep.isAuto()) { | |||
return STRENGTH_AUTO; | |||
} else if (keep.getEnum() == Constants.EN_ALWAYS) { | |||
return STRENGTH_ALWAYS; | |||
} else { | |||
return keep.getNumber().intValue(); | |||
} | |||
} | |||
/** | |||
* Obtain a Keep instance corresponding to the given {@link KeepProperty} | |||
* | |||
* @param keepProperty the {@link KeepProperty} | |||
* @return a new instance corresponding to the given property | |||
*/ | |||
public static Keep getKeep(KeepProperty keepProperty) { | |||
Keep keep = new Keep(STRENGTH_AUTO, Constants.EN_AUTO); | |||
keep.update(keepProperty.getWithinPage(), Constants.EN_PAGE); | |||
keep.update(keepProperty.getWithinColumn(), Constants.EN_COLUMN); | |||
keep.update(keepProperty.getWithinLine(), Constants.EN_LINE); | |||
return keep; | |||
} | |||
private void update(Property keep, int context) { | |||
if (!keep.isAuto()) { | |||
this.strength = getKeepStrength(keep); | |||
this.context = context; | |||
} | |||
} | |||
/** @return {@code true} if the keep property was specified as "auto" */ | |||
public boolean isAuto() { | |||
return strength == STRENGTH_AUTO; | |||
} | |||
/** | |||
* Returns the context of this keep. | |||
* | |||
* @return one of {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or | |||
* {@link Constants#EN_PAGE} | |||
*/ | |||
public int getContext() { | |||
return context; | |||
} | |||
/** @return the penalty value corresponding to the strength of this Keep */ | |||
public int getPenalty() { | |||
if (strength == STRENGTH_AUTO) { | |||
return 0; | |||
} else if (strength == STRENGTH_ALWAYS) { | |||
return KnuthElement.INFINITE; | |||
} else { | |||
return KnuthElement.INFINITE - 1; | |||
} | |||
} | |||
private static int getKeepContextPriority(int context) { | |||
switch (context) { | |||
case Constants.EN_LINE: return 0; | |||
case Constants.EN_COLUMN: return 1; | |||
case Constants.EN_PAGE: return 2; | |||
case Constants.EN_AUTO: return 3; | |||
default: throw new IllegalArgumentException(); | |||
} | |||
} | |||
/** | |||
* Compare this Keep instance to another one, and return the | |||
* stronger one if the context is the same | |||
* | |||
* @param other the instance to compare to | |||
* @return the winning Keep instance | |||
*/ | |||
public Keep compare(Keep other) { | |||
/* check strength "always" first, regardless of priority */ | |||
if (this.strength == STRENGTH_ALWAYS | |||
&& this.strength > other.strength) { | |||
return this; | |||
} else if (other.strength == STRENGTH_ALWAYS | |||
&& other.strength > this.strength) { | |||
return other; | |||
} | |||
int pThis = getKeepContextPriority(this.context); | |||
int pOther = getKeepContextPriority(other.context); | |||
/* equal priority: strongest wins */ | |||
if (pThis == pOther) { | |||
return (strength >= other.strength) ? this : other; | |||
} | |||
/* different priority: lowest priority wins */ | |||
return (pThis < pOther) ? this : other; | |||
} | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
return (strength == STRENGTH_AUTO) ? "auto" | |||
: (strength == STRENGTH_ALWAYS) ? "always" | |||
: Integer.toString(strength); | |||
} | |||
} |
@@ -1,109 +0,0 @@ | |||
/* | |||
* 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.layoutmgr; | |||
import org.apache.fop.fo.Constants; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.fo.properties.Property; | |||
/** | |||
* Utility class for working with keeps. | |||
*/ | |||
public class KeepUtil { | |||
/** | |||
* Converts a keep property into an integer value. | |||
* <p> | |||
* Note: The conversion restricts the effectively available integer range by two values. | |||
* Integer.MIN_VALUE is used to represent the value "auto" and | |||
* Integer.MAX_VALUE is used to represebt the value "always". | |||
* @param keep the keep property | |||
* @return the keep value as an integer | |||
*/ | |||
public static int getKeepStrength(Property keep) { | |||
if (keep.isAuto()) { | |||
return BlockLevelLayoutManager.KEEP_AUTO; | |||
} else if (keep.getEnum() == Constants.EN_ALWAYS) { | |||
return BlockLevelLayoutManager.KEEP_ALWAYS; | |||
} else { | |||
return keep.getNumber().intValue(); | |||
} | |||
} | |||
/** | |||
* Returns the combined block-level keep strength from a keep property. | |||
* <p> | |||
* Note: This is a temporary method to be used until it is possible to differentiate between | |||
* page and column keeps! | |||
* @param keep the keep property | |||
* @return the combined keep strength | |||
*/ | |||
public static int getCombinedBlockLevelKeepStrength(KeepProperty keep) { | |||
return Math.max( | |||
getKeepStrength(keep.getWithinPage()), | |||
getKeepStrength(keep.getWithinColumn())); | |||
} | |||
/** | |||
* Indicates whether a keep strength indicates a keep constraint. | |||
* @param strength the keep strength | |||
* @return true if the keep is not "auto" | |||
*/ | |||
public static boolean hasKeep(int strength) { | |||
return strength > BlockLevelLayoutManager.KEEP_AUTO; | |||
} | |||
/** | |||
* Returns the penalty value to be used for a certain keep strength. | |||
* <ul> | |||
* <li>"auto": returns 0</li> | |||
* <li>"always": returns KnuthElement.INFINITE</li> | |||
* <li>otherwise: returns KnuthElement.INFINITE - 1</li> | |||
* </ul> | |||
* @param keepStrength the keep strength | |||
* @return the penalty value | |||
*/ | |||
public static int getPenaltyForKeep(int keepStrength) { | |||
if (keepStrength == BlockLevelLayoutManager.KEEP_AUTO) { | |||
return 0; | |||
} | |||
int penalty = KnuthElement.INFINITE; | |||
if (keepStrength < BlockLevelLayoutManager.KEEP_ALWAYS) { | |||
penalty--; | |||
} | |||
return penalty; | |||
} | |||
/** | |||
* Returns a string representation of a keep strength value. | |||
* @param keepStrength the keep strength | |||
* @return the string representation | |||
*/ | |||
public static String keepStrengthToString(int keepStrength) { | |||
if (keepStrength == BlockLevelLayoutManager.KEEP_AUTO) { | |||
return "auto"; | |||
} else if (keepStrength == BlockLevelLayoutManager.KEEP_ALWAYS) { | |||
return "always"; | |||
} else { | |||
return Integer.toString(keepStrength); | |||
} | |||
} | |||
} |
@@ -45,7 +45,7 @@ public class KnuthPenalty extends KnuthElement { | |||
public static final int FLAGGED_PENALTY = 50; | |||
private int penalty; | |||
private boolean bFlagged; | |||
private boolean isFlagged; | |||
private int breakClass = -1; | |||
/** | |||
@@ -55,12 +55,12 @@ public class KnuthPenalty extends KnuthElement { | |||
* @param p the penalty value of this penalty | |||
* @param f is this penalty flagged? | |||
* @param pos the Position stored in this penalty | |||
* @param bAux is this penalty auxiliary? | |||
* @param isAuxiliary is this penalty auxiliary? | |||
*/ | |||
public KnuthPenalty(int w, int p, boolean f, Position pos, boolean bAux) { | |||
super(w, pos, bAux); | |||
public KnuthPenalty(int w, int p, boolean f, Position pos, boolean isAuxiliary) { | |||
super(w, pos, isAuxiliary); | |||
penalty = p; | |||
bFlagged = f; | |||
isFlagged = f; | |||
} | |||
/** | |||
@@ -69,18 +69,37 @@ public class KnuthPenalty extends KnuthElement { | |||
* @param w the width of this penalty | |||
* @param p the penalty value of this penalty | |||
* @param f is this penalty flagged? | |||
* @param iBreakClass the break class of this penalty (one of | |||
* @param breakClass the break class of this penalty (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 pos the Position stored in this penalty | |||
* @param bAux is this penalty auxiliary? | |||
* @param isAuxiliary is this penalty auxiliary? | |||
*/ | |||
public KnuthPenalty(int w, int p, boolean f, | |||
int iBreakClass, Position pos, boolean bAux) { | |||
super(w, pos, bAux); | |||
penalty = p; | |||
bFlagged = f; | |||
breakClass = iBreakClass; | |||
int breakClass, Position pos, boolean isAuxiliary) { | |||
this(w, p, f, pos, isAuxiliary); | |||
this.breakClass = breakClass; | |||
} | |||
private static String getBreakClassName(int breakClass) { | |||
return AbstractBreaker.getBreakClassName(breakClass); | |||
} | |||
/** | |||
* Get the penalty's value as a {@code java.lang.String}. | |||
* (Mainly used in {@code toString()} methods, to improve readability | |||
* of the trace logs.) | |||
* | |||
* @param penaltyValue the penalty value | |||
* @return the penalty value as a {@code java.lang.String} | |||
*/ | |||
protected static String valueOf(int penaltyValue) { | |||
String result = (penaltyValue < 0) ? "-" : ""; | |||
int tmpValue = Math.abs(penaltyValue); | |||
result += (tmpValue == KnuthElement.INFINITE) | |||
? "INFINITE" | |||
: String.valueOf(tmpValue); | |||
return result; | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -105,7 +124,7 @@ public class KnuthPenalty extends KnuthElement { | |||
/** @return true is this penalty is a flagged one. */ | |||
public boolean isFlagged() { | |||
return bFlagged; | |||
return isFlagged; | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -121,14 +140,6 @@ public class KnuthPenalty extends KnuthElement { | |||
return breakClass; | |||
} | |||
/** | |||
* Sets the break class for this penalty. | |||
* @param cl the break class (EN_AUTO, EN_COLUMN, EN_PAGE, EN_EVEN_PAGE, EN_ODD_PAGE) | |||
*/ | |||
public void setBreakClass(int cl) { | |||
this.breakClass = cl; | |||
} | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
StringBuffer sb = new StringBuffer(64); | |||
@@ -137,39 +148,22 @@ public class KnuthPenalty extends KnuthElement { | |||
} | |||
sb.append("penalty"); | |||
sb.append(" p="); | |||
if (getP() < 0) { | |||
sb.append("-"); | |||
} | |||
if (Math.abs(getP()) == INFINITE) { | |||
sb.append("INFINITE"); | |||
} else { | |||
sb.append(getP()); | |||
} | |||
if (isFlagged()) { | |||
sb.append(valueOf(this.penalty)); | |||
if (this.isFlagged) { | |||
sb.append(" [flagged]"); | |||
} | |||
sb.append(" w="); | |||
sb.append(getW()); | |||
if (isForcedBreak()) { | |||
sb.append(" (forced break"); | |||
switch (getBreakClass()) { | |||
case Constants.EN_PAGE: | |||
sb.append(", page"); | |||
break; | |||
case Constants.EN_COLUMN: | |||
sb.append(", column"); | |||
break; | |||
case Constants.EN_EVEN_PAGE: | |||
sb.append(", even page"); | |||
break; | |||
case Constants.EN_ODD_PAGE: | |||
sb.append(", odd page"); | |||
break; | |||
default: | |||
} | |||
sb.append(")"); | |||
sb.append(" (forced break, ") | |||
.append(getBreakClassName(this.breakClass)) | |||
.append(")"); | |||
} else if (this.penalty >= 0 && this.breakClass != -1) { | |||
//penalty corresponding to a keep constraint | |||
sb.append(" (keep constraint, ") | |||
.append(getBreakClassName(this.breakClass)) | |||
.append(")"); | |||
} | |||
return sb.toString(); | |||
} | |||
} |
@@ -136,8 +136,8 @@ public class LayoutContext { | |||
private int breakBefore; | |||
private int breakAfter; | |||
private int pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO; | |||
private int pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; | |||
private Keep pendingKeepWithNext = Keep.KEEP_AUTO; | |||
private Keep pendingKeepWithPrevious = Keep.KEEP_AUTO; | |||
private int disableColumnBalancing; | |||
@@ -227,7 +227,7 @@ public class LayoutContext { | |||
* Returns the strength of a keep-with-next currently pending. | |||
* @return the keep-with-next strength | |||
*/ | |||
public int getKeepWithNextPending() { | |||
public Keep getKeepWithNextPending() { | |||
return this.pendingKeepWithNext; | |||
} | |||
@@ -235,7 +235,7 @@ public class LayoutContext { | |||
* Returns the strength of a keep-with-previous currently pending. | |||
* @return the keep-with-previous strength | |||
*/ | |||
public int getKeepWithPreviousPending() { | |||
public Keep getKeepWithPreviousPending() { | |||
return this.pendingKeepWithPrevious; | |||
} | |||
@@ -243,14 +243,14 @@ public class LayoutContext { | |||
* Clears any pending keep-with-next strength. | |||
*/ | |||
public void clearKeepWithNextPending() { | |||
this.pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO; | |||
this.pendingKeepWithNext = Keep.KEEP_AUTO; | |||
} | |||
/** | |||
* Clears any pending keep-with-previous strength. | |||
*/ | |||
public void clearKeepWithPreviousPending() { | |||
this.pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; | |||
this.pendingKeepWithPrevious = Keep.KEEP_AUTO; | |||
} | |||
/** | |||
@@ -263,18 +263,18 @@ public class LayoutContext { | |||
/** | |||
* Updates the currently pending keep-with-next strength. | |||
* @param strength the new strength to consider | |||
* @param keep the new strength to consider | |||
*/ | |||
public void updateKeepWithNextPending(int strength) { | |||
this.pendingKeepWithNext = Math.max(this.pendingKeepWithNext, strength); | |||
public void updateKeepWithNextPending(Keep keep) { | |||
this.pendingKeepWithNext = this.pendingKeepWithNext.compare(keep); | |||
} | |||
/** | |||
* Updates the currently pending keep-with-previous strength. | |||
* @param strength the new strength to consider | |||
* @param keep the new strength to consider | |||
*/ | |||
public void updateKeepWithPreviousPending(int strength) { | |||
this.pendingKeepWithPrevious = Math.max(this.pendingKeepWithPrevious, strength); | |||
public void updateKeepWithPreviousPending(Keep keep) { | |||
this.pendingKeepWithPrevious = this.pendingKeepWithPrevious.compare(keep); | |||
} | |||
/** | |||
@@ -282,7 +282,7 @@ public class LayoutContext { | |||
* @return true if a keep-with-next constraint is pending | |||
*/ | |||
public boolean isKeepWithNextPending() { | |||
return getKeepWithNextPending() != BlockLevelLayoutManager.KEEP_AUTO; | |||
return !getKeepWithNextPending().isAuto(); | |||
} | |||
/** | |||
@@ -290,7 +290,7 @@ public class LayoutContext { | |||
* @return true if a keep-with-previous constraint is pending | |||
*/ | |||
public boolean isKeepWithPreviousPending() { | |||
return getKeepWithPreviousPending() != BlockLevelLayoutManager.KEEP_AUTO; | |||
return !getKeepWithPreviousPending().isAuto(); | |||
} | |||
public void setLeadingSpace(SpaceSpecifier space) { | |||
@@ -640,9 +640,8 @@ public class LayoutContext { | |||
+ "\nStarts New Area: \t" + startsNewArea() | |||
+ "\nIs Last Area: \t" + isLastArea() | |||
+ "\nTry Hyphenate: \t" + tryHyphenate() | |||
+ "\nKeeps: \t[keep-with-next=" + KeepUtil.keepStrengthToString(getKeepWithNextPending()) | |||
+ "][keep-with-previous=" | |||
+ KeepUtil.keepStrengthToString(getKeepWithPreviousPending()) + "] pending" | |||
+ "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending() | |||
+ "][keep-with-previous=" + getKeepWithPreviousPending() + "] pending" | |||
+ "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" | |||
+ (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]"; | |||
} |
@@ -451,9 +451,7 @@ public class PageBreaker extends AbstractBreaker { | |||
pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished(); | |||
} | |||
/** | |||
* @return the current child flow layout manager | |||
*/ | |||
/** @return the current child flow layout manager */ | |||
protected LayoutManager getCurrentChildLM() { | |||
return childFLM; | |||
} | |||
@@ -472,44 +470,51 @@ public class PageBreaker extends AbstractBreaker { | |||
*/ | |||
private void handleBreakTrait(int breakVal) { | |||
Page curPage = pslm.getCurrentPage(); | |||
if (breakVal == Constants.EN_ALL) { | |||
switch (breakVal) { | |||
case Constants.EN_ALL: | |||
//break due to span change in multi-column layout | |||
curPage.getPageViewport().createSpan(true); | |||
return; | |||
} else if (breakVal == Constants.EN_NONE) { | |||
case Constants.EN_NONE: | |||
curPage.getPageViewport().createSpan(false); | |||
return; | |||
} else if (breakVal == Constants.EN_COLUMN | |||
|| breakVal <= 0 | |||
|| breakVal == Constants.EN_AUTO) { | |||
case Constants.EN_COLUMN: | |||
case Constants.EN_AUTO: | |||
case Constants.EN_PAGE: | |||
case -1: | |||
PageViewport pv = curPage.getPageViewport(); | |||
//Check if previous page was spanned | |||
boolean forceNewPageWithSpan = false; | |||
RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion( | |||
Constants.FO_REGION_BODY); | |||
if (rb.getColumnCount() > 1 | |||
&& pv.getCurrentSpan().getColumnCount() == 1) { | |||
forceNewPageWithSpan = true; | |||
} | |||
forceNewPageWithSpan | |||
= (rb.getColumnCount() > 1 | |||
&& pv.getCurrentSpan().getColumnCount() == 1); | |||
if (forceNewPageWithSpan) { | |||
log.trace("Forcing new page with span"); | |||
curPage = pslm.makeNewPage(false, false); | |||
curPage.getPageViewport().createSpan(true); | |||
} else if (pv.getCurrentSpan().hasMoreFlows()) { | |||
log.trace("Moving to next flow"); | |||
pv.getCurrentSpan().moveToNextFlow(); | |||
} else { | |||
curPage = pslm.makeNewPage(false, false); | |||
log.trace("Making new page"); | |||
/*curPage = */pslm.makeNewPage(false, false); | |||
} | |||
return; | |||
} | |||
log.debug("handling break-before after page " + pslm.getCurrentPageNum() | |||
+ " breakVal=" + getBreakClassName(breakVal)); | |||
if (needBlankPageBeforeNew(breakVal)) { | |||
curPage = pslm.makeNewPage(true, false); | |||
} | |||
if (needNewPage(breakVal)) { | |||
curPage = pslm.makeNewPage(false, false); | |||
default: | |||
log.debug("handling break-before after page " + pslm.getCurrentPageNum() | |||
+ " breakVal=" + getBreakClassName(breakVal)); | |||
if (needBlankPageBeforeNew(breakVal)) { | |||
log.trace("Inserting blank page"); | |||
/*curPage = */pslm.makeNewPage(true, false); | |||
} | |||
if (needNewPage(breakVal)) { | |||
log.trace("Making new page"); | |||
/*curPage = */pslm.makeNewPage(false, false); | |||
} | |||
} | |||
} | |||
@@ -96,6 +96,11 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
//Controls whether a single part should be forced if possible (ex. block-container) | |||
private boolean favorSinglePart = false; | |||
//Used to keep track of switches in keep-context | |||
private int currentKeepContext = Constants.EN_AUTO; | |||
private KnuthNode lastBeforeKeepContextSwitch; | |||
public PageBreakingAlgorithm(LayoutManager topLevelLM, | |||
PageProvider pageProvider, | |||
PageBreakingLayoutListener layoutListener, | |||
@@ -190,6 +195,72 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
footnoteElementIndex = -1; | |||
} | |||
/** | |||
* {@inheritDoc} | |||
* Overridden to defer a part to the next page, if it | |||
* must be kept within one page, but is too large to fit in | |||
* the last column. | |||
*/ | |||
protected KnuthNode recoverFromTooLong(KnuthNode lastTooLong) { | |||
if (log.isDebugEnabled()) { | |||
log.debug("Recovering from too long: " + lastTooLong); | |||
log.debug("\tlastTooShort = " + getLastTooShort()); | |||
log.debug("\tlastBeforeKeepContextSwitch = " + lastBeforeKeepContextSwitch); | |||
log.debug("\tcurrentKeepContext = " + AbstractBreaker.getBreakClassName(currentKeepContext)); | |||
} | |||
if (lastBeforeKeepContextSwitch == null | |||
|| currentKeepContext == Constants.EN_AUTO) { | |||
return super.recoverFromTooLong(lastTooLong); | |||
} | |||
KnuthNode node = lastBeforeKeepContextSwitch; | |||
lastBeforeKeepContextSwitch = null; | |||
// content would overflow, insert empty page/column(s) and try again | |||
while (!pageProvider.endPage(node.line - 1)) { | |||
log.trace("Adding node for empty column"); | |||
node = createNode( | |||
node.position, | |||
node.line + 1, 1, | |||
0, 0, 0, | |||
0, 0, 0, | |||
0, 0, node); | |||
} | |||
return node; | |||
} | |||
/** | |||
* Compare two KnuthNodes and return the node with the least demerit. | |||
* | |||
* @param node1 The first knuth node. | |||
* @param node2 The other knuth node. | |||
* @return the node with the least demerit. | |||
*/ | |||
protected KnuthNode compareNodes(KnuthNode node1, KnuthNode node2) { | |||
/* if either node is null, return the other one */ | |||
if (node1 == null || node2 == null) { | |||
return (node1 == null) ? node2 : node1; | |||
} | |||
/* if either one of the nodes corresponds to a mere column-break, | |||
* and the other one corresponds to a page-break, return the page-break node | |||
*/ | |||
if (pageProvider != null) { | |||
if (pageProvider.endPage(node1.line - 1) | |||
&& !pageProvider.endPage(node2.line - 1)) { | |||
return node1; | |||
} else if (pageProvider.endPage(node2.line - 1) | |||
&& !pageProvider.endPage(node1.line - 1)) { | |||
return node2; | |||
} | |||
} | |||
/* all other cases: use superclass implementation */ | |||
return super.compareNodes(node1, node2); | |||
} | |||
/** {@inheritDoc} */ | |||
protected KnuthNode createNode(int position, int line, int fitness, | |||
int totalWidth, int totalStretch, int totalShrink, | |||
@@ -233,6 +304,28 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
} | |||
} | |||
/** | |||
* {@inheritDoc} | |||
* Overridden to consider penalties with value {@link KnuthElement#INFINITE} | |||
* as legal break-points, if the current keep-context allows this | |||
* (a keep-*.within-page="always" constraint still permits column-breaks) | |||
*/ | |||
protected void handlePenaltyAt(KnuthPenalty penalty, int position, | |||
int allowedBreaks) { | |||
super.handlePenaltyAt(penalty, position, allowedBreaks); | |||
/* if the penalty had value INFINITE, default implementation | |||
* will not have considered it a legal break, but it could still | |||
* be one. | |||
*/ | |||
if (penalty.getP() == KnuthPenalty.INFINITE) { | |||
int breakClass = penalty.getBreakClass(); | |||
if (breakClass == Constants.EN_PAGE | |||
|| breakClass == Constants.EN_COLUMN) { | |||
considerLegalBreak(penalty, position); | |||
} | |||
} | |||
} | |||
/** | |||
* Handles the footnotes cited inside a block-level box. Updates footnotesList and the | |||
* value of totalFootnotesLength with the lengths of the given footnotes. | |||
@@ -317,10 +410,66 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
/** {@inheritDoc} */ | |||
protected void considerLegalBreak(KnuthElement element, int elementIdx) { | |||
if (element.isPenalty()) { | |||
int breakClass = ((KnuthPenalty) element).getBreakClass(); | |||
switch (breakClass) { | |||
case Constants.EN_PAGE: | |||
if (this.currentKeepContext != breakClass) { | |||
this.lastBeforeKeepContextSwitch = getLastTooShort(); | |||
} | |||
this.currentKeepContext = breakClass; | |||
break; | |||
case Constants.EN_COLUMN: | |||
if (this.currentKeepContext != breakClass) { | |||
this.lastBeforeKeepContextSwitch = getLastTooShort(); | |||
} | |||
this.currentKeepContext = breakClass; | |||
break; | |||
case Constants.EN_AUTO: | |||
this.currentKeepContext = breakClass; | |||
break; | |||
default: | |||
//nop | |||
} | |||
} | |||
super.considerLegalBreak(element, elementIdx); | |||
newFootnotes = false; | |||
} | |||
/** {@inheritDoc} */ | |||
protected boolean elementCanEndLine(KnuthElement element, int line, int difference) { | |||
if (!(element.isPenalty()) || pageProvider == null) { | |||
return true; | |||
} else { | |||
KnuthPenalty p = (KnuthPenalty) element; | |||
if (p.getP() <= 0) { | |||
return true; | |||
} else { | |||
int context = p.getBreakClass(); | |||
switch (context) { | |||
case Constants.EN_LINE: | |||
case Constants.EN_COLUMN: | |||
return p.getP() < KnuthPenalty.INFINITE; | |||
case Constants.EN_PAGE: | |||
return p.getP() < KnuthPenalty.INFINITE | |||
|| !pageProvider.endPage(line - 1); | |||
//|| (deferPart && difference < 0); | |||
case Constants.EN_AUTO: | |||
log.warn("keep is not auto but context is"); | |||
return true; | |||
default: | |||
if (p.getP() < KnuthPenalty.INFINITE) { | |||
log.warn("Non recognized keep context:" + context); | |||
return true; | |||
} else { | |||
return false; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
protected int computeDifference(KnuthNode activeNode, KnuthElement element, | |||
int elementIndex) { | |||
KnuthPageNode pageNode = (KnuthPageNode) activeNode; |
@@ -146,6 +146,49 @@ public class PageProvider implements Constants { | |||
return this.lastReportedBPD; | |||
} | |||
// Wish there were a more elegant way to do this in Java | |||
private int[] getColIndexAndColCount(int index) { | |||
int columnCount = 0; | |||
int colIndex = startColumnOfCurrentElementList + index; | |||
int pageIndex = -1; | |||
do { | |||
colIndex -= columnCount; | |||
pageIndex++; | |||
Page page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST); | |||
columnCount = page.getPageViewport().getCurrentSpan().getColumnCount(); | |||
} while (colIndex >= columnCount); | |||
return new int[] {colIndex, columnCount}; | |||
} | |||
/** | |||
* Checks if a break at the passed index would start a new page | |||
* @param index the index of the element before the break | |||
* @return {@code true} if the break starts a new page | |||
*/ | |||
boolean startPage(int index) { | |||
return getColIndexAndColCount(index)[0] == 0; | |||
} | |||
/** | |||
* Checks if a break at the passed index would end a page | |||
* @param index the index of the element before the break | |||
* @return {@code true} if the break ends a page | |||
*/ | |||
boolean endPage(int index) { | |||
int[] colIndexAndColCount = getColIndexAndColCount(index); | |||
return colIndexAndColCount[0] == colIndexAndColCount[1] - 1; | |||
} | |||
/** | |||
* Obtain the applicable column-count for the element at the | |||
* passed index | |||
* @param index the index of the element | |||
* @return the number of columns | |||
*/ | |||
int getColumnCount(int index) { | |||
return getColIndexAndColCount(index)[1]; | |||
} | |||
/** | |||
* Returns the part index (0<x<partCount) which denotes the first part on the last page | |||
* generated by the current element list. | |||
@@ -272,4 +315,4 @@ public class PageProvider implements Constants { | |||
return page; | |||
} | |||
} | |||
} |
@@ -314,18 +314,18 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepTogether() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithNext() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithPrevious() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
} |
@@ -36,6 +36,7 @@ import org.apache.fop.datatypes.Numeric; | |||
import org.apache.fop.fo.Constants; | |||
import org.apache.fop.fo.flow.Block; | |||
import org.apache.fop.fo.properties.CommonHyphenation; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.fonts.Font; | |||
import org.apache.fop.fonts.FontInfo; | |||
import org.apache.fop.fonts.FontTriplet; | |||
@@ -46,7 +47,7 @@ import org.apache.fop.layoutmgr.BreakElement; | |||
import org.apache.fop.layoutmgr.BreakingAlgorithm; | |||
import org.apache.fop.layoutmgr.ElementListObserver; | |||
import org.apache.fop.layoutmgr.InlineKnuthSequence; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.KnuthBlockBox; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
@@ -876,12 +877,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager | |||
for (int p = 0; p < knuthParagraphs.size(); p++) { | |||
// penalty between paragraphs | |||
if (p > 0) { | |||
int strength = getKeepTogetherStrength(); | |||
int penalty = KeepUtil.getPenaltyForKeep(strength); | |||
if (penalty < KnuthElement.INFINITE) { | |||
returnList.add(new BreakElement( | |||
new Position(this), penalty, context)); | |||
} | |||
Keep keep = getKeepTogether(); | |||
returnList.add(new BreakElement( | |||
new Position(this), | |||
keep.getPenalty(), | |||
keep.getContext(), | |||
context)); | |||
} | |||
LineLayoutPossibilities llPoss; | |||
@@ -920,12 +921,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager | |||
&& i >= fobj.getOrphans() | |||
&& i <= llPoss.getChosenLineCount() - fobj.getWidows()) { | |||
// penalty allowing a page break between lines | |||
int strength = getKeepTogetherStrength(); | |||
int penalty = KeepUtil.getPenaltyForKeep(strength); | |||
if (penalty < KnuthElement.INFINITE) { | |||
returnList.add(new BreakElement( | |||
returnPosition, penalty, context)); | |||
} | |||
Keep keep = getKeepTogether(); | |||
returnList.add(new BreakElement( | |||
new Position(this), | |||
keep.getPenalty(), | |||
keep.getContext(), | |||
context)); | |||
} | |||
int endIndex | |||
= ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos(); | |||
@@ -1104,28 +1105,43 @@ public class LineLayoutManager extends InlineStackingLayoutManager | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
return ((BlockLevelLayoutManager) getParent()).getKeepTogetherStrength(); | |||
public KeepProperty getKeepTogetherProperty() { | |||
return ((BlockLevelLayoutManager) getParent()).getKeepTogetherProperty(); | |||
} | |||
/** {@inheritDoc} */ | |||
public KeepProperty getKeepWithPreviousProperty() { | |||
return ((BlockLevelLayoutManager) getParent()).getKeepWithPreviousProperty(); | |||
} | |||
/** {@inheritDoc} */ | |||
public KeepProperty getKeepWithNextProperty() { | |||
return ((BlockLevelLayoutManager) getParent()).getKeepWithNextProperty(); | |||
} | |||
/** {@inheritDoc} */ | |||
public Keep getKeepTogether() { | |||
return ((BlockLevelLayoutManager) getParent()).getKeepTogether(); | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean mustKeepWithPrevious() { | |||
return getKeepWithPreviousStrength() > KEEP_AUTO; | |||
return !getKeepWithPrevious().isAuto(); | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean mustKeepWithNext() { | |||
return getKeepWithNextStrength() > KEEP_AUTO; | |||
return !getKeepWithNext().isAuto(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithNext() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithPrevious() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -1230,6 +1246,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager | |||
break; | |||
} | |||
//TODO Something's not right here. See block_hyphenation_linefeed_preserve.xml | |||
//for more info: see also https://issues.apache.org/bugzilla/show_bug.cgi?id=38264 | |||
// collect word fragments, ignoring auxiliary elements; | |||
// each word fragment was created by a different TextLM |
@@ -29,10 +29,10 @@ import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.area.Area; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.fo.flow.ListBlock; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | |||
import org.apache.fop.layoutmgr.ConditionalElementListener; | |||
import org.apache.fop.layoutmgr.ElementListUtils; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.LayoutContext; | |||
import org.apache.fop.layoutmgr.LayoutManager; | |||
import org.apache.fop.layoutmgr.NonLeafPosition; | |||
@@ -279,21 +279,18 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getListBlockFO().getKeepTogether()); | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
public KeepProperty getKeepTogetherProperty() { | |||
return getListBlockFO().getKeepTogether(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithNext()); | |||
public KeepProperty getKeepWithPreviousProperty() { | |||
return getListBlockFO().getKeepWithPrevious(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithPrevious()); | |||
public KeepProperty getKeepWithNextProperty() { | |||
return getListBlockFO().getKeepWithNext(); | |||
} | |||
/** {@inheritDoc} */ |
@@ -28,8 +28,9 @@ import org.apache.fop.area.Block; | |||
import org.apache.fop.fo.flow.AbstractListItemPart; | |||
import org.apache.fop.fo.flow.ListItemBody; | |||
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.KeepUtil; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.LayoutContext; | |||
import org.apache.fop.layoutmgr.LayoutManager; | |||
import org.apache.fop.layoutmgr.NonLeafPosition; | |||
@@ -221,20 +222,18 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getPartFO().getKeepTogether()); | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
public KeepProperty getKeepTogetherProperty() { | |||
return getPartFO().getKeepTogether(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithNext() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithPrevious() { | |||
return Keep.KEEP_AUTO; | |||
} | |||
} |
@@ -32,13 +32,13 @@ import org.apache.fop.area.Block; | |||
import org.apache.fop.fo.flow.ListItem; | |||
import org.apache.fop.fo.flow.ListItemBody; | |||
import org.apache.fop.fo.flow.ListItemLabel; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | |||
import org.apache.fop.layoutmgr.BreakElement; | |||
import org.apache.fop.layoutmgr.ConditionalElementListener; | |||
import org.apache.fop.layoutmgr.ElementListObserver; | |||
import org.apache.fop.layoutmgr.ElementListUtils; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.KnuthBlockBox; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
@@ -83,8 +83,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
private MinOptMax effSpaceBefore; | |||
private MinOptMax effSpaceAfter; | |||
private int keepWithNextPendingOnLabel; | |||
private int keepWithNextPendingOnBody; | |||
private Keep keepWithNextPendingOnLabel; | |||
private Keep keepWithNextPendingOnBody; | |||
private int listItemHeight; | |||
@@ -254,8 +254,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel); | |||
context.updateKeepWithNextPending(this.keepWithNextPendingOnBody); | |||
context.updateKeepWithNextPending(getKeepWithNextStrength()); | |||
context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); | |||
context.updateKeepWithNextPending(getKeepWithNext()); | |||
context.updateKeepWithPreviousPending(getKeepWithPrevious()); | |||
setFinished(true); | |||
resetSpaces(); | |||
@@ -276,16 +276,16 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
int totalHeight = Math.max(fullHeights[0], fullHeights[1]); | |||
int step; | |||
int addedBoxHeight = 0; | |||
int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO; | |||
Keep keepWithNextActive = Keep.KEEP_AUTO; | |||
LinkedList returnList = new LinkedList(); | |||
while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { | |||
if (end[0] + 1 == elementLists[0].size()) { | |||
keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel); | |||
keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnLabel); | |||
} | |||
if (end[1] + 1 == elementLists[1].size()) { | |||
keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnBody); | |||
keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnBody); | |||
} | |||
// compute penalty height and box height | |||
@@ -339,14 +339,13 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
} | |||
if (addedBoxHeight < totalHeight) { | |||
int strength = BlockLevelLayoutManager.KEEP_AUTO; | |||
strength = Math.max(strength, keepWithNextActive); | |||
strength = Math.max(strength, getKeepTogetherStrength()); | |||
Keep keep = keepWithNextActive.compare(getKeepTogether()); | |||
int p = stepPenalty; | |||
if (p > -KnuthElement.INFINITE) { | |||
p = Math.max(p, KeepUtil.getPenaltyForKeep(strength)); | |||
p = Math.max(p, keep.getPenalty()); | |||
} | |||
returnList.add(new BreakElement(stepPosition, penaltyHeight, p, -1, context)); | |||
returnList.add(new BreakElement(stepPosition, penaltyHeight, p, keep.getContext(), | |||
context)); | |||
} | |||
} | |||
@@ -644,21 +643,18 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getListItemFO().getKeepTogether()); | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
public KeepProperty getKeepTogetherProperty() { | |||
return getListItemFO().getKeepTogether(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithNext()); | |||
public KeepProperty getKeepWithPreviousProperty() { | |||
return getListItemFO().getKeepWithPrevious(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithPrevious()); | |||
public KeepProperty getKeepWithNextProperty() { | |||
return getListItemFO().getKeepWithNext(); | |||
} | |||
/** {@inheritDoc} */ |
@@ -32,8 +32,8 @@ import org.apache.fop.fo.flow.table.ConditionalBorder; | |||
import org.apache.fop.fo.flow.table.EffRow; | |||
import org.apache.fop.fo.flow.table.PrimaryGridUnit; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.layoutmgr.ElementListUtils; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.KnuthBlockBox; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
@@ -75,7 +75,7 @@ class ActiveCell { | |||
/** True if the next CellPart that will be created will be the last one for this cell. */ | |||
private boolean lastCellPart; | |||
private int keepWithNextStrength; | |||
private Keep keepWithNext; | |||
private int spanIndex = 0; | |||
@@ -218,7 +218,7 @@ class ActiveCell { | |||
includedLength = -1; // Avoid troubles with cells having content of zero length | |||
totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); | |||
endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1; | |||
keepWithNextStrength = BlockLevelLayoutManager.KEEP_AUTO; | |||
keepWithNext = Keep.KEEP_AUTO; | |||
remainingLength = totalLength - previousRowsLength; | |||
afterNextStep = new Step(previousRowsLength); | |||
@@ -314,7 +314,11 @@ class ActiveCell { | |||
KnuthElement el = (KnuthElement) knuthIter.next(); | |||
if (el.isPenalty()) { | |||
prevIsBox = false; | |||
if (el.getP() < KnuthElement.INFINITE) { | |||
if (el.getP() < KnuthElement.INFINITE | |||
|| ((KnuthPenalty) el).getBreakClass() == Constants.EN_PAGE) { | |||
// TODO too much is being done in that test, only to handle | |||
// keep.within-column properly. | |||
// First legal break point | |||
breakFound = true; | |||
KnuthPenalty p = (KnuthPenalty) el; | |||
@@ -533,7 +537,7 @@ class ActiveCell { | |||
*/ | |||
CellPart createCellPart() { | |||
if (nextStep.end + 1 == elementList.size()) { | |||
keepWithNextStrength = pgu.getKeepWithNextStrength(); | |||
keepWithNext = pgu.getKeepWithNext(); | |||
// TODO if keep-with-next is set on the row, must every cell of the row | |||
// contribute some content from children blocks? | |||
// see http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200802.mbox/ | |||
@@ -576,8 +580,8 @@ class ActiveCell { | |||
} | |||
} | |||
int getKeepWithNextStrength() { | |||
return keepWithNextStrength; | |||
Keep getKeepWithNext() { | |||
return keepWithNext; | |||
} | |||
int getPenaltyValue() { |
@@ -60,8 +60,8 @@ class RowGroupLayoutManager { | |||
LinkedList returnList = new LinkedList(); | |||
createElementsForRowGroup(context, alignment, bodyType, returnList); | |||
context.updateKeepWithPreviousPending(rowGroup[0].getKeepWithPreviousStrength()); | |||
context.updateKeepWithNextPending(rowGroup[rowGroup.length - 1].getKeepWithNextStrength()); | |||
context.updateKeepWithPreviousPending(rowGroup[0].getKeepWithPrevious()); | |||
context.updateKeepWithNextPending(rowGroup[rowGroup.length - 1].getKeepWithNext()); | |||
int breakBefore = Constants.EN_AUTO; | |||
TableRow firstRow = rowGroup[0].getTableRow(); |
@@ -23,6 +23,7 @@ import org.apache.fop.area.Area; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.fo.flow.table.TableAndCaption; | |||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.LayoutContext; | |||
import org.apache.fop.layoutmgr.PositionIterator; | |||
@@ -201,19 +202,8 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
int strength = KEEP_AUTO; | |||
/* TODO Complete me! | |||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getTableAndCaptionFO().getKeepTogether()); | |||
*/ | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithNext() { | |||
return Keep.KEEP_AUTO; | |||
/* TODO Complete me! | |||
return KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getTableAndCaptionFO().getKeepWithNext()); | |||
@@ -221,12 +211,12 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithPrevious() { | |||
return Keep.KEEP_AUTO; | |||
/* TODO Complete me! | |||
return KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getTableAndCaptionFO().getKeepWithPrevious()); | |||
*/ | |||
} | |||
} | |||
} |
@@ -23,6 +23,7 @@ import org.apache.fop.area.Area; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.fo.flow.table.TableCaption; | |||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.LayoutContext; | |||
import org.apache.fop.layoutmgr.PositionIterator; | |||
@@ -197,21 +198,8 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
int strength = KEEP_AUTO; | |||
/* TODO Complete me! | |||
strength = Math.max(strength, KeepUtil.getKeepStrength( | |||
getTableCaptionFO().getKeepTogether().getWithinPage())); | |||
strength = Math.max(strength, KeepUtil.getKeepStrength( | |||
getTableCaptionFO().getKeepTogether().getWithinColumn())); | |||
*/ | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithNext() { | |||
return Keep.KEEP_AUTO; | |||
/* TODO Complete me! | |||
return KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getTableCaptionFO().getKeepWithNext()); | |||
@@ -219,8 +207,8 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KEEP_AUTO; | |||
public Keep getKeepWithPrevious() { | |||
return Keep.KEEP_AUTO; | |||
/* TODO Complete me! | |||
return KeepUtil.getCombinedBlockLevelKeepStrength( | |||
getTableCaptionFO().getKeepWithPrevious()); |
@@ -24,6 +24,7 @@ import java.util.List; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.area.Area; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.area.Trait; | |||
@@ -31,21 +32,23 @@ import org.apache.fop.fo.flow.table.ConditionalBorder; | |||
import org.apache.fop.fo.flow.table.GridUnit; | |||
import org.apache.fop.fo.flow.table.PrimaryGridUnit; | |||
import org.apache.fop.fo.flow.table.Table; | |||
import org.apache.fop.fo.flow.table.TablePart; | |||
import org.apache.fop.fo.flow.table.TableCell; | |||
import org.apache.fop.fo.flow.table.TableColumn; | |||
import org.apache.fop.fo.flow.table.TablePart; | |||
import org.apache.fop.fo.flow.table.TableRow; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; | |||
import org.apache.fop.layoutmgr.AreaAdditionUtil; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.ElementListUtils; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
import org.apache.fop.layoutmgr.KnuthGlue; | |||
import org.apache.fop.layoutmgr.KnuthPenalty; | |||
import org.apache.fop.layoutmgr.LayoutContext; | |||
import org.apache.fop.layoutmgr.LayoutManager; | |||
import org.apache.fop.layoutmgr.Position; | |||
import org.apache.fop.layoutmgr.PositionIterator; | |||
import org.apache.fop.layoutmgr.SpaceResolver; | |||
@@ -138,9 +141,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager | |||
List contentList = new LinkedList(); | |||
List returnList = new LinkedList(); | |||
BlockLevelLayoutManager curLM; // currently active LM | |||
BlockLevelLayoutManager prevLM = null; // previously active LM | |||
while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { | |||
LayoutManager curLM; // currently active LM | |||
LayoutManager prevLM = null; // previously active LM | |||
while ((curLM = getChildLM()) != null) { | |||
LayoutContext childLC = new LayoutContext(0); | |||
// curLM is a ? | |||
childLC.setStackLimitBP(MinOptMax.subtract(context | |||
@@ -153,11 +156,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager | |||
log.debug("child LM signals pending keep with next"); | |||
} | |||
if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { | |||
primaryGridUnit.setKeepWithPreviousStrength(childLC.getKeepWithPreviousPending()); | |||
primaryGridUnit.setKeepWithPrevious(childLC.getKeepWithPreviousPending()); | |||
childLC.clearKeepWithPreviousPending(); | |||
} | |||
if (prevLM != null) { | |||
if (prevLM != null | |||
&& !ElementListUtils.endsWithForcedBreak(contentList)) { | |||
// there is a block handled by prevLM | |||
// before the one handled by curLM | |||
addInBetweenBreak(contentList, context, childLC); | |||
@@ -174,7 +178,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager | |||
} | |||
prevLM = curLM; | |||
} | |||
primaryGridUnit.setKeepWithNextStrength(context.getKeepWithNextPending()); | |||
primaryGridUnit.setKeepWithNext(context.getKeepWithNextPending()); | |||
returnedList = new LinkedList(); | |||
if (!contentList.isEmpty()) { | |||
@@ -195,7 +199,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager | |||
} | |||
final KnuthElement lastItem = (KnuthElement) ListUtil | |||
.getLast(returnList); | |||
if (((KnuthElement) lastItem).isForcedBreak()) { | |||
if (lastItem.isForcedBreak()) { | |||
KnuthPenalty p = (KnuthPenalty) lastItem; | |||
primaryGridUnit.setBreakAfter(p.getBreakClass()); | |||
p.setP(0); | |||
@@ -556,26 +560,23 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
int strength = KEEP_AUTO; | |||
public Keep getKeepTogether() { | |||
Keep keep = Keep.KEEP_AUTO; | |||
if (primaryGridUnit.getRow() != null) { | |||
strength = Math.max(strength, KeepUtil.getKeepStrength( | |||
primaryGridUnit.getRow().getKeepTogether().getWithinPage())); | |||
strength = Math.max(strength, KeepUtil.getKeepStrength( | |||
primaryGridUnit.getRow().getKeepTogether().getWithinColumn())); | |||
keep = Keep.getKeep(primaryGridUnit.getRow().getKeepTogether()); | |||
} | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
keep = keep.compare(getParentKeepTogether()); | |||
return keep; | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-next!) | |||
public Keep getKeepWithNext() { | |||
return Keep.KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-next!) | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!) | |||
public Keep getKeepWithPrevious() { | |||
return Keep.KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!) | |||
} | |||
// --------- Property Resolution related functions --------- // |
@@ -35,10 +35,9 @@ import org.apache.fop.fo.flow.table.EffRow; | |||
import org.apache.fop.fo.flow.table.PrimaryGridUnit; | |||
import org.apache.fop.fo.flow.table.Table; | |||
import org.apache.fop.fo.flow.table.TablePart; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.layoutmgr.BreakElement; | |||
import org.apache.fop.layoutmgr.ElementListUtils; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
import org.apache.fop.layoutmgr.KnuthGlue; | |||
@@ -213,13 +212,13 @@ public class TableContentLayoutManager implements PercentBaseContext { | |||
context.clearKeepsPending(); | |||
context.setBreakBefore(Constants.EN_AUTO); | |||
context.setBreakAfter(Constants.EN_AUTO); | |||
int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; | |||
Keep keepWithPrevious = Keep.KEEP_AUTO; | |||
int breakBefore = Constants.EN_AUTO; | |||
if (rowGroup != null) { | |||
RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, | |||
stepper); | |||
List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); | |||
keepWithPrevious = Math.max(keepWithPrevious, context.getKeepWithPreviousPending()); | |||
keepWithPrevious = keepWithPrevious.compare(context.getKeepWithPreviousPending()); | |||
breakBefore = context.getBreakBefore(); | |||
int breakBetween = context.getBreakAfter(); | |||
returnList.addAll(nextRowGroupElems); | |||
@@ -228,7 +227,7 @@ public class TableContentLayoutManager implements PercentBaseContext { | |||
//Note previous pending keep-with-next and clear the strength | |||
//(as the layout context is reused) | |||
int keepWithNextPending = context.getKeepWithNextPending(); | |||
Keep keepWithNextPending = context.getKeepWithNextPending(); | |||
context.clearKeepWithNextPending(); | |||
//Get elements for next row group | |||
@@ -246,17 +245,17 @@ public class TableContentLayoutManager implements PercentBaseContext { | |||
*/ | |||
//Determine keep constraints | |||
int penaltyStrength = BlockLevelLayoutManager.KEEP_AUTO; | |||
penaltyStrength = Math.max(penaltyStrength, keepWithNextPending); | |||
penaltyStrength = Math.max(penaltyStrength, context.getKeepWithPreviousPending()); | |||
Keep keep = keepWithNextPending.compare(context.getKeepWithPreviousPending()); | |||
context.clearKeepWithPreviousPending(); | |||
penaltyStrength = Math.max(penaltyStrength, getTableLM().getKeepTogetherStrength()); | |||
int penaltyValue = KeepUtil.getPenaltyForKeep(penaltyStrength); | |||
keep = keep.compare(getTableLM().getKeepTogether()); | |||
int penaltyValue = keep.getPenalty(); | |||
int breakClass = keep.getContext(); | |||
breakBetween = BreakUtil.compareBreakClasses(breakBetween, | |||
context.getBreakBefore()); | |||
if (breakBetween != Constants.EN_AUTO) { | |||
penaltyValue = -KnuthElement.INFINITE; | |||
breakClass = breakBetween; | |||
} | |||
BreakElement breakElement; | |||
ListIterator elemIter = returnList.listIterator(returnList.size()); | |||
@@ -267,7 +266,7 @@ public class TableContentLayoutManager implements PercentBaseContext { | |||
breakElement = (BreakElement) elem; | |||
} | |||
breakElement.setPenaltyValue(penaltyValue); | |||
breakElement.setBreakClass(breakBetween); | |||
breakElement.setBreakClass(breakClass); | |||
returnList.addAll(nextRowGroupElems); | |||
breakBetween = context.getBreakAfter(); | |||
} |
@@ -35,11 +35,11 @@ import org.apache.fop.fo.FONode; | |||
import org.apache.fop.fo.FObj; | |||
import org.apache.fop.fo.flow.table.Table; | |||
import org.apache.fop.fo.flow.table.TableColumn; | |||
import org.apache.fop.fo.properties.KeepProperty; | |||
import org.apache.fop.layoutmgr.BlockLevelEventProducer; | |||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | |||
import org.apache.fop.layoutmgr.BreakElement; | |||
import org.apache.fop.layoutmgr.ConditionalElementListener; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
import org.apache.fop.layoutmgr.KnuthGlue; | |||
import org.apache.fop.layoutmgr.LayoutContext; | |||
@@ -256,10 +256,10 @@ public class TableLayoutManager extends BlockStackingLayoutManager | |||
log.debug(contentKnuthElements); | |||
wrapPositionElements(contentKnuthElements, returnList); | |||
context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); | |||
context.updateKeepWithPreviousPending(getKeepWithPrevious()); | |||
context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); | |||
context.updateKeepWithNextPending(getKeepWithNextStrength()); | |||
context.updateKeepWithNextPending(getKeepWithNext()); | |||
context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); | |||
if (getTable().isSeparateBorderModel()) { | |||
@@ -448,20 +448,18 @@ public class TableLayoutManager extends BlockStackingLayoutManager | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepTogetherStrength() { | |||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepTogether()); | |||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||
return strength; | |||
public KeepProperty getKeepTogetherProperty() { | |||
return getTable().getKeepTogether(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithNextStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithNext()); | |||
public KeepProperty getKeepWithPreviousProperty() { | |||
return getTable().getKeepWithPrevious(); | |||
} | |||
/** {@inheritDoc} */ | |||
public int getKeepWithPreviousStrength() { | |||
return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithPrevious()); | |||
public KeepProperty getKeepWithNextProperty() { | |||
return getTable().getKeepWithNext(); | |||
} | |||
// --------- Property Resolution related functions --------- // |
@@ -30,12 +30,10 @@ import org.apache.fop.fo.Constants; | |||
import org.apache.fop.fo.flow.table.EffRow; | |||
import org.apache.fop.fo.flow.table.GridUnit; | |||
import org.apache.fop.fo.flow.table.PrimaryGridUnit; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.layoutmgr.BreakElement; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.Keep; | |||
import org.apache.fop.layoutmgr.KnuthBlockBox; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
import org.apache.fop.layoutmgr.KnuthGlue; | |||
import org.apache.fop.layoutmgr.KnuthPenalty; | |||
import org.apache.fop.layoutmgr.LayoutContext; | |||
@@ -241,40 +239,38 @@ public class TableStepper { | |||
} | |||
} | |||
int strength = BlockLevelLayoutManager.KEEP_AUTO; | |||
Keep keep = Keep.KEEP_AUTO; | |||
int stepPenalty = 0; | |||
for (Iterator iter = activeCells.iterator(); iter.hasNext();) { | |||
ActiveCell activeCell = (ActiveCell) iter.next(); | |||
strength = Math.max(strength, activeCell.getKeepWithNextStrength()); | |||
keep = keep.compare(activeCell.getKeepWithNext()); | |||
stepPenalty = Math.max(stepPenalty, activeCell.getPenaltyValue()); | |||
} | |||
if (!rowFinished) { | |||
strength = Math.max(strength, rowGroup[activeRowIndex].getKeepTogetherStrength()); | |||
keep = keep.compare(rowGroup[activeRowIndex].getKeepTogether()); | |||
//The above call doesn't take the penalty from the table into account, so... | |||
strength = Math.max(strength, getTableLM().getKeepTogetherStrength()); | |||
keep = keep.compare(getTableLM().getKeepTogether()); | |||
} else if (activeRowIndex < rowGroup.length - 1) { | |||
strength = Math.max(strength, | |||
rowGroup[activeRowIndex].getKeepWithNextStrength()); | |||
strength = Math.max(strength, | |||
rowGroup[activeRowIndex + 1].getKeepWithPreviousStrength()); | |||
keep = keep.compare(rowGroup[activeRowIndex].getKeepWithNext()); | |||
keep = keep.compare(rowGroup[activeRowIndex + 1].getKeepWithPrevious()); | |||
nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass, | |||
rowGroup[activeRowIndex].getBreakAfter()); | |||
nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass, | |||
rowGroup[activeRowIndex + 1].getBreakBefore()); | |||
} | |||
int p = KeepUtil.getPenaltyForKeep(strength); | |||
int p = keep.getPenalty(); | |||
if (rowHeightSmallerThanFirstStep) { | |||
rowHeightSmallerThanFirstStep = false; | |||
p = KnuthPenalty.INFINITE; | |||
} | |||
if (p > -KnuthElement.INFINITE) { | |||
p = Math.max(p, stepPenalty); | |||
} | |||
p = Math.max(p, stepPenalty); | |||
int breakClass = keep.getContext(); | |||
if (nextBreakClass != Constants.EN_AUTO) { | |||
log.trace("Forced break encountered"); | |||
p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0) | |||
breakClass = nextBreakClass; | |||
} | |||
returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, nextBreakClass, context)); | |||
returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context)); | |||
if (penaltyOrGlueLen < 0) { | |||
returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true)); | |||
} |
@@ -58,6 +58,9 @@ | |||
documents. Example: the fix of marks layering will be such a case when it's done. | |||
--> | |||
<release version="FOP Trunk" date="TBD"> | |||
<action context="Renderers" dev="AD" type="add" fixes-bug="46905"> | |||
Added basic implementation for column-keeps. | |||
</action> | |||
<action context="Renderers" dev="AD" type="fix" fixes-bug="46883"> | |||
Hotspot in AbstractGraphicsDrawingOrderContainer. Reduced time spent in the method | |||
by introducing a member variable to hold the data-length. |
@@ -216,4 +216,10 @@ | |||
<description>A soft hyphen should be a preferred as break compared to a | |||
normal hyphenation point but is not.</description> | |||
</testcase> | |||
<testcase> | |||
<name>Page-keep not respected in multi-column layout</name> | |||
<file>keep_within-page_multi-column_overflow.xml</file> | |||
<description>The block should cause overflow in the | |||
last column on the page, rather than be broken.</description> | |||
</testcase> | |||
</disabled-testcases> |
@@ -52,16 +52,15 @@ | |||
<skip>5</skip> | |||
<!-- penalty between blocks b11 and b12, set by InlineLM in b1 --> | |||
<penalty w="0" p="0"/> | |||
<skip>6</skip> | |||
<skip>5</skip> | |||
<!-- penalty between blocks b21 and b22, set by InlineLM in b2 --> | |||
<!-- keep-together.within-page="always" --> | |||
<penalty w="0" p="1000"/> | |||
<skip>6</skip> | |||
<skip>3</skip> | |||
<!-- penalty between blocks b31 and b32, set by InlineLM in b3 --> | |||
<!-- keep-with-next.within-page="always" --> | |||
<penalty w="0" p="1000"/> | |||
<skip>5</skip> | |||
<skip>3</skip> | |||
<skip>14</skip> | |||
</element-list> | |||
</checks> | |||
</testcase> |
@@ -0,0 +1,155 @@ | |||
<?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 whether keeps within-column are respected. | |||
</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-width="400pt" page-height="70pt"> | |||
<fo:region-body column-count="5" /> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="page" font-size="10pt"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block break-before="page"> | |||
<!-- simple test: keep the second block together within | |||
one column, breaking the preceding block early | |||
if necessary --> | |||
<fo:block id="block-1"> | |||
[BOB-1] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-1] | |||
</fo:block> | |||
<fo:block id="block-2" keep-together.within-column="always"> | |||
[BOB-2] foo bar foo bar foo bar foo bar foo [EOB-2] | |||
</fo:block> | |||
</fo:block> | |||
<fo:block break-before="page"> | |||
<!-- same as the first, but now a nested block | |||
with a higher integer value, and some content | |||
following --> | |||
<fo:block id="block-3" keep-together.within-column="5"> | |||
[BOB-3] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
<fo:block font-weight="bold" id="block-3a" keep-together.within-column="always"> | |||
[BOB-3a] foo bar foo bar foo bar foo bar foo [EOB-3a] | |||
</fo:block> | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-3] | |||
</fo:block> | |||
</fo:block> | |||
<fo:block break-before="page"> | |||
<!-- nested block must be kept together within the same | |||
page, while the outer block may be broken, if necessary --> | |||
<fo:block font-style="italic" id="block-4" keep-together.within-column="5"> | |||
[BOB-4] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
<fo:block id="block-4a" keep-together.within-page="always"> | |||
[BOB-4a] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-4a] | |||
</fo:block> | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-4] | |||
</fo:block> | |||
</fo:block> | |||
<fo:block break-before="page"> | |||
<!-- test keep-with-next in conjunction with keep-together | |||
respecting the default value for widows/orphans --> | |||
<fo:block id="block-5"> | |||
<fo:block id="block-5a"> | |||
[BOB-5a] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-5a] | |||
</fo:block> | |||
<fo:block id="block-5b" keep-with-next.within-column="always"> | |||
[BOB-5b] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-5b] | |||
</fo:block> | |||
<fo:block id="block-5c" keep-together.within-column="always"> | |||
[BOB-5c] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-5c] | |||
</fo:block> | |||
</fo:block> | |||
</fo:block> | |||
<fo:block break-before="page"> | |||
<!-- test keep-together in conjunction with keep-with-previous --> | |||
<fo:block id="block-6"> | |||
<fo:block id="block-6a"> | |||
[BOB-6a] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-6a] | |||
</fo:block> | |||
<fo:block id="block-6b" keep-together.within-column="always"> | |||
[BOB-6b] foo bar foo bar foo bar foo bar foo bar [EOB-6b] | |||
</fo:block> | |||
<fo:block id="block-6c" keep-with-previous.within-column="always"> | |||
[BOB-6c] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-6c] | |||
</fo:block> | |||
</fo:block> | |||
</fo:block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> | |||
</fo> | |||
<checks> | |||
<!-- check total page-count --> | |||
<eval expected="10" xpath="count(//page)" /> | |||
<!-- block-2 should end up in its own column, column 4 --> | |||
<eval expected="1" xpath="count(//block[@prod-id='block-2']/ancestor::flow)" /> | |||
<eval expected="3" xpath="count(//block[@prod-id='block-2']/ancestor::flow/preceding-sibling::flow)" /> | |||
<!-- block-3a should end up in its own column, column 5 --> | |||
<eval expected="1" xpath="count(//block[@prod-id='block-3a']/ancestor::flow)" /> | |||
<eval expected="4" xpath="count(//block[@prod-id='block-3a']/ancestor::flow/preceding-sibling::flow)" /> | |||
<!-- block-4a should end up in its own page --> | |||
<eval expected="1" xpath="count(//block[@prod-id='block-4a']/ancestor::page)" /> | |||
<!-- block 5c should end up in its own column, with two preceding lines from block 5b --> | |||
<eval expected="1" xpath="count(//block[@prod-id='block-5c']/ancestor::flow)" /> | |||
<eval expected="2" xpath="count(//block[@prod-id='block-5c']/preceding-sibling::block/lineArea)" /> | |||
<!-- block 6b should end up in its own column, with two following lines from block 6c --> | |||
<eval expected="1" xpath="count(//block[@prod-id='block-6b']/ancestor::flow)" /> | |||
<eval expected="2" xpath="count(//block[@prod-id='block-6b']/following-sibling::block/lineArea)" /> | |||
</checks> | |||
</testcase> | |||
@@ -0,0 +1,58 @@ | |||
<?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 for a remaining issue after adding support | |||
for keep-*.within column (see Bugzilla 46905). | |||
keep-together.within-page does not work as expected in multi-column | |||
layout. If the part does not fit into one page, it will ultimately | |||
still be broken. | |||
</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-width="400pt" page-height="70pt"> | |||
<fo:region-body column-count="5" /> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="page" font-size="10pt"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<!-- block must be kept together within the same page --> | |||
<fo:block id="block-4a" keep-together.within-page="always"> | |||
[BOB-4a] foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar foo bar | |||
foo bar foo bar foo bar foo bar foo bar [EOB-4a] | |||
</fo:block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> | |||
</fo> | |||
<checks> | |||
<eval expected="1" xpath="count(//pageViewport)" /> | |||
</checks> | |||
</testcase> |
@@ -64,10 +64,10 @@ | |||
<element-list category="breaker" index="0"> | |||
<box w="14400"/> | |||
<penalty w="0" p="0"/> | |||
<box w="28800"/> | |||
<penalty w="0" p="0"/> | |||
<box w="14400"/> | |||
<skip>3</skip> | |||
<penalty w="0" p="INF"/> | |||
<box w="14400"/> | |||
<skip>5</skip> | |||
</element-list> | |||
</checks> | |||
</testcase> |
@@ -101,7 +101,9 @@ | |||
<element-list category="breaker" index="0"> | |||
<box w="14400"/> | |||
<penalty w="0" p="0"/> | |||
<box w="28800"/> | |||
<box w="14400"/> | |||
<penalty w="0" p="INF"/> | |||
<box w="14400"/> | |||
<penalty w="0" p="INF"/> | |||
<box w="14400"/> | |||
<penalty w="0" p="0"/> |