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
import java.util.List; | import java.util.List; | ||||
import org.apache.fop.fo.Constants; | 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.layoutmgr.table.TableRowIterator; | ||||
import org.apache.fop.traits.MinOptMax; | import org.apache.fop.traits.MinOptMax; | ||||
import org.apache.fop.util.BreakUtil; | import org.apache.fop.util.BreakUtil; | ||||
* | * | ||||
* @return the strength of the keep-with-previous constraint | * @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(); | TableRow row = getTableRow(); | ||||
if (row != null) { | if (row != null) { | ||||
strength = Math.max(strength, | |||||
KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithPrevious())); | |||||
keep = Keep.getKeep(row.getKeepWithPrevious()); | |||||
} | } | ||||
for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { | for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { | ||||
GridUnit gu = (GridUnit) iter.next(); | GridUnit gu = (GridUnit) iter.next(); | ||||
if (gu.isPrimary()) { | if (gu.isPrimary()) { | ||||
strength = Math.max(strength, gu.getPrimary().getKeepWithPreviousStrength()); | |||||
keep = keep.compare(gu.getPrimary().getKeepWithPrevious()); | |||||
} | } | ||||
} | } | ||||
return strength; | |||||
return keep; | |||||
} | } | ||||
/** | /** | ||||
* | * | ||||
* @return the strength of the keep-with-next constraint | * @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(); | TableRow row = getTableRow(); | ||||
if (row != null) { | if (row != null) { | ||||
strength = Math.max(strength, | |||||
KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithNext())); | |||||
keep = Keep.getKeep(row.getKeepWithNext()); | |||||
} | } | ||||
for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { | for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { | ||||
GridUnit gu = (GridUnit) iter.next(); | GridUnit gu = (GridUnit) iter.next(); | ||||
if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) { | 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; | |||||
} | } | ||||
/** | /** | ||||
* not take the parent table's keeps into account! | * not take the parent table's keeps into account! | ||||
* @return the keep-together strength | * @return the keep-together strength | ||||
*/ | */ | ||||
public int getKeepTogetherStrength() { | |||||
public Keep getKeepTogether() { | |||||
TableRow row = getTableRow(); | TableRow row = getTableRow(); | ||||
int strength = BlockLevelLayoutManager.KEEP_AUTO; | |||||
Keep keep = Keep.KEEP_AUTO; | |||||
if (row != null) { | 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; | |||||
} | } | ||||
/** | /** |
package org.apache.fop.fo.flow.table; | package org.apache.fop.fo.flow.table; | ||||
import java.util.LinkedList; | |||||
import java.util.List; | import java.util.List; | ||||
import org.apache.fop.fo.Constants; | import org.apache.fop.fo.Constants; | ||||
import org.apache.fop.fo.FONode; | import org.apache.fop.fo.FONode; | ||||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | ||||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||||
import org.apache.fop.layoutmgr.ElementListUtils; | import org.apache.fop.layoutmgr.ElementListUtils; | ||||
import org.apache.fop.layoutmgr.Keep; | |||||
import org.apache.fop.layoutmgr.table.TableCellLayoutManager; | import org.apache.fop.layoutmgr.table.TableCellLayoutManager; | ||||
/** | /** | ||||
private boolean isSeparateBorderModel; | private boolean isSeparateBorderModel; | ||||
private int halfBorderSeparationBPD; | 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 breakBefore = Constants.EN_AUTO; | ||||
private int breakAfter = Constants.EN_AUTO; | private int breakAfter = Constants.EN_AUTO; | ||||
* | * | ||||
* @return the keep-with-previous strength | * @return the keep-with-previous strength | ||||
*/ | */ | ||||
public int getKeepWithPreviousStrength() { | |||||
public Keep getKeepWithPrevious() { | |||||
return keepWithPrevious; | return keepWithPrevious; | ||||
} | } | ||||
/** | /** | ||||
* Don't use, reserved for TableCellLM. TODO | * 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; | |||||
} | } | ||||
/** | /** | ||||
* | * | ||||
* @return the keep-with-next strength | * @return the keep-with-next strength | ||||
*/ | */ | ||||
public int getKeepWithNextStrength() { | |||||
public Keep getKeepWithNext() { | |||||
return keepWithNext; | return keepWithNext; | ||||
} | } | ||||
/** | /** | ||||
* Don't use, reserved for TableCellLM. TODO | * 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; | |||||
} | } | ||||
/** | /** |
import org.apache.fop.datatypes.Length; | import org.apache.fop.datatypes.Length; | ||||
import org.apache.fop.fo.flow.BlockContainer; | import org.apache.fop.fo.flow.BlockContainer; | ||||
import org.apache.fop.fo.properties.CommonAbsolutePosition; | 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.MinOptMax; | ||||
import org.apache.fop.traits.SpaceVal; | import org.apache.fop.traits.SpaceVal; | ||||
import org.apache.fop.util.ListUtil; | import org.apache.fop.util.ListUtil; | ||||
if (!firstVisibleMarkServed) { | if (!firstVisibleMarkServed) { | ||||
addKnuthElementsForSpaceBefore(returnList, alignment); | addKnuthElementsForSpaceBefore(returnList, alignment); | ||||
context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); | |||||
context.updateKeepWithPreviousPending(getKeepWithPrevious()); | |||||
} | } | ||||
addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); | addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); | ||||
//Spaces, border and padding to be repeated at each break | //Spaces, border and padding to be repeated at each break | ||||
addPendingMarks(context); | 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); | LayoutContext childLC = new LayoutContext(0); | ||||
childLC.copyPendingMarksFrom(context); | childLC.copyPendingMarksFrom(context); | ||||
// curLM is a ? | // curLM is a ? | ||||
//Avoid NoSuchElementException below (happens with empty blocks) | //Avoid NoSuchElementException below (happens with empty blocks) | ||||
continue; | continue; | ||||
} | } | ||||
if (((ListElement) ListUtil.getLast(returnedList)) | |||||
.isForcedBreak()) { | |||||
if (ElementListUtils.endsWithForcedBreak(returnedList)) { | |||||
// a descendant of this block has break-after | // a descendant of this block has break-after | ||||
if (curLM.isFinished()) { | if (curLM.isFinished()) { | ||||
// there is no other content in this block; | // there is no other content in this block; | ||||
context.clearPendingMarks(); | context.clearPendingMarks(); | ||||
addKnuthElementsForBreakAfter(returnList, context); | addKnuthElementsForBreakAfter(returnList, context); | ||||
context.updateKeepWithNextPending(getKeepWithNextStrength()); | |||||
context.updateKeepWithNextPending(getKeepWithNext()); | |||||
setFinished(true); | setFinished(true); | ||||
return returnList; | return returnList; | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength( | |||||
getBlockContainerFO().getKeepTogether()); | |||||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||||
return strength; | |||||
public KeepProperty getKeepTogetherProperty() { | |||||
return getBlockContainerFO().getKeepTogether(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength( | |||||
getBlockContainerFO().getKeepWithNext()); | |||||
public KeepProperty getKeepWithPreviousProperty() { | |||||
return getBlockContainerFO().getKeepWithPrevious(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength( | |||||
getBlockContainerFO().getKeepWithPrevious()); | |||||
public KeepProperty getKeepWithNextProperty() { | |||||
return getBlockContainerFO().getKeepWithNext(); | |||||
} | } | ||||
/** | /** |
} | } | ||||
/** {@inheritDoc} */ | /** {@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} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithNext()); | |||||
public KeepProperty getKeepWithPreviousProperty() { | |||||
return getBlockFO().getKeepWithPrevious(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithPrevious()); | |||||
public KeepProperty getKeepWithNextProperty() { | |||||
return getBlockFO().getKeepWithNext(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ |
package org.apache.fop.layoutmgr; | package org.apache.fop.layoutmgr; | ||||
import org.apache.fop.fo.properties.KeepProperty; | |||||
/** | /** | ||||
* The interface for LayoutManagers which generate block areas | * The interface for LayoutManagers which generate block areas | ||||
*/ | */ | ||||
/** Adjustment class: adjustment for line height */ | /** Adjustment class: adjustment for line height */ | ||||
int LINE_HEIGHT_ADJUSTMENT = 3; | 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); | int negotiateBPDAdjustment(int adj, KnuthElement lastElement); | ||||
void discardSpace(KnuthGlue spaceGlue); | void discardSpace(KnuthGlue spaceGlue); | ||||
* Returns the keep-together strength for this element. | * Returns the keep-together strength for this element. | ||||
* @return the keep-together strength | * @return the keep-together strength | ||||
*/ | */ | ||||
int getKeepTogetherStrength(); | |||||
Keep getKeepTogether(); | |||||
/** | /** | ||||
* @return true if this element must be kept together | * @return true if this element must be kept together | ||||
* Returns the keep-with-previous strength for this element. | * Returns the keep-with-previous strength for this element. | ||||
* @return the keep-with-previous strength | * @return the keep-with-previous strength | ||||
*/ | */ | ||||
int getKeepWithPreviousStrength(); | |||||
Keep getKeepWithPrevious(); | |||||
/** | /** | ||||
* @return true if this element must be kept with the previous element. | * @return true if this element must be kept with the previous element. | ||||
* Returns the keep-with-next strength for this element. | * Returns the keep-with-next strength for this element. | ||||
* @return the keep-with-next strength | * @return the keep-with-next strength | ||||
*/ | */ | ||||
int getKeepWithNextStrength(); | |||||
Keep getKeepWithNext(); | |||||
/** | /** | ||||
* @return true if this element must be kept with the next element. | * @return true if this element must be kept with the next element. | ||||
*/ | */ | ||||
boolean mustKeepWithNext(); | 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(); | |||||
} | } |
import org.apache.fop.area.Block; | import org.apache.fop.area.Block; | ||||
import org.apache.fop.area.BlockParent; | import org.apache.fop.area.BlockParent; | ||||
import org.apache.fop.fo.FObj; | 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.BreakPropertySet; | ||||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | ||||
import org.apache.fop.fo.properties.SpaceProperty; | 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.InlineLayoutManager; | ||||
import org.apache.fop.layoutmgr.inline.LineLayoutManager; | import org.apache.fop.layoutmgr.inline.LineLayoutManager; | ||||
import org.apache.fop.traits.MinOptMax; | import org.apache.fop.traits.MinOptMax; | ||||
if (!firstVisibleMarkServed) { | if (!firstVisibleMarkServed) { | ||||
addKnuthElementsForSpaceBefore(elements, alignment); | addKnuthElementsForSpaceBefore(elements, alignment); | ||||
context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); | |||||
context.updateKeepWithPreviousPending(getKeepWithPrevious()); | |||||
} | } | ||||
addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed); | addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed); | ||||
elements.add(forcedBreakAfterLast); | elements.add(forcedBreakAfterLast); | ||||
} | } | ||||
context.updateKeepWithNextPending(getKeepWithNextStrength()); | |||||
context.updateKeepWithNextPending(getKeepWithNext()); | |||||
setFinished(true); | setFinished(true); | ||||
/** | /** | ||||
* Adds a break element to the content list between individual child elements. | * 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 | * @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() | if (mustKeepTogether() | ||||
|| context.isKeepWithNextPending() | |||||
|| parentLC.isKeepWithNextPending() | |||||
|| childLC.isKeepWithPreviousPending()) { | || childLC.isKeepWithPreviousPending()) { | ||||
int strength = getKeepTogetherStrength(); | |||||
Keep keep = getKeepTogether(); | |||||
//Handle pending keep-with-next | //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 | //Handle pending keep-with-previous from child LM | ||||
strength = Math.max(strength, childLC.getKeepWithPreviousPending()); | |||||
keep = keep.compare(childLC.getKeepWithPreviousPending()); | |||||
childLC.clearKeepWithPreviousPending(); | childLC.clearKeepWithPreviousPending(); | ||||
int penalty = KeepUtil.getPenaltyForKeep(strength); | |||||
// add a penalty to forbid or discourage a break between blocks | // add a penalty to forbid or discourage a break between blocks | ||||
contentList.add(new BreakElement( | contentList.add(new BreakElement( | ||||
new Position(this), penalty, context)); | |||||
new Position(this), keep.getPenalty(), | |||||
keep.getContext(), parentLC)); | |||||
return; | return; | ||||
} | } | ||||
// add a null penalty to allow a break between blocks | // add a null penalty to allow a break between blocks | ||||
contentList.add(new BreakElement( | contentList.add(new BreakElement( | ||||
new Position(this), 0, context)); | |||||
new Position(this), 0, Constants.EN_AUTO, parentLC)); | |||||
} | } | ||||
} | } | ||||
* Retrieves and returns the keep-together strength from the parent element. | * Retrieves and returns the keep-together strength from the parent element. | ||||
* @return the keep-together strength | * @return the keep-together strength | ||||
*/ | */ | ||||
protected int getParentKeepTogetherStrength() { | |||||
int strength = KEEP_AUTO; | |||||
protected Keep getParentKeepTogether() { | |||||
Keep keep = Keep.KEEP_AUTO; | |||||
if (getParent() instanceof BlockLevelLayoutManager) { | if (getParent() instanceof BlockLevelLayoutManager) { | ||||
strength = ((BlockLevelLayoutManager)getParent()).getKeepTogetherStrength(); | |||||
keep = ((BlockLevelLayoutManager)getParent()).getKeepTogether(); | |||||
} else if (getParent() instanceof InlineLayoutManager) { | } else if (getParent() instanceof InlineLayoutManager) { | ||||
if (((InlineLayoutManager) getParent()).mustKeepTogether()) { | if (((InlineLayoutManager) getParent()).mustKeepTogether()) { | ||||
strength = KEEP_ALWAYS; | |||||
keep = Keep.KEEP_ALWAYS; | |||||
} | } | ||||
//TODO Fix me | //TODO Fix me | ||||
//strength = ((InlineLayoutManager) getParent()).getKeepTogetherStrength(); | //strength = ((InlineLayoutManager) getParent()).getKeepTogetherStrength(); | ||||
} | } | ||||
return strength; | |||||
return keep; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public boolean mustKeepTogether() { | public boolean mustKeepTogether() { | ||||
return getKeepTogetherStrength() > KEEP_AUTO; | |||||
return !getKeepTogether().isAuto(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public boolean mustKeepWithPrevious() { | public boolean mustKeepWithPrevious() { | ||||
return getKeepWithPreviousStrength() > KEEP_AUTO; | |||||
return !getKeepWithPrevious().isAuto(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public boolean mustKeepWithNext() { | 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(); | |||||
} | } | ||||
/** | /** |
* @param context the layout context which contains the pending conditional elements | * @param context the layout context which contains the pending conditional elements | ||||
*/ | */ | ||||
public BreakElement(Position position, int penaltyValue, LayoutContext context) { | 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); | |||||
} | } | ||||
/** | /** | ||||
this.pendingAfterMarks = context.getPendingAfterMarks(); | this.pendingAfterMarks = context.getPendingAfterMarks(); | ||||
} | } | ||||
private static String getBreakClassName(int breakClass) { | |||||
return AbstractBreaker.getBreakClassName(breakClass); | |||||
} | |||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public boolean isConditional() { | public boolean isConditional() { | ||||
return false; //Does not really apply here | return false; //Does not really apply here | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public String toString() { | public String toString() { | ||||
StringBuffer sb = new StringBuffer(); | |||||
StringBuffer sb = new StringBuffer(64); | |||||
sb.append("BreakPossibility[p:"); | sb.append("BreakPossibility[p:"); | ||||
sb.append(this.penaltyValue); | |||||
sb.append(KnuthPenalty.valueOf(this.penaltyValue)); | |||||
if (isForcedBreak()) { | 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("; w:"); | ||||
sb.append(penaltyWidth); | sb.append(penaltyWidth); |
best.getNode(fitness)); | 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}, | * Generic handler for a {@link KnuthElement} at the given {@code position}, | ||||
* taking into account whether the preceding element was a box, and which | * taking into account whether the preceding element was a box, and which | ||||
/** | /** | ||||
* Handle a {@link KnuthBox}. | * 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 | * to the total content width. Subclasses that do not keep track | ||||
* of this themselves, but override this method, should remember | * of this themselves, but override this method, should remember | ||||
* to call {@code super.handleBox(box)} to avoid unwanted side-effects.</em> | * to call {@code super.handleBox(box)} to avoid unwanted side-effects.</em> | ||||
lastDeactivated = null; | lastDeactivated = null; | ||||
lastTooLong = null; | lastTooLong = null; | ||||
for (int line = startLine; line < endLine; line++) { | for (int line = startLine; line < endLine; line++) { | ||||
if (!elementCanEndLine(element, line)) { | |||||
continue; | |||||
} | |||||
for (KnuthNode node = getNode(line); node != null; node = node.next) { | for (KnuthNode node = getNode(line); node != null; node = node.next) { | ||||
if (node.position == elementIdx) { | if (node.position == elementIdx) { | ||||
continue; | continue; | ||||
} | } | ||||
int difference = computeDifference(node, element, elementIdx); | int difference = computeDifference(node, element, elementIdx); | ||||
if (!elementCanEndLine(element, endLine, difference)) { | |||||
log.trace("Skipping legal break"); | |||||
break; | |||||
} | |||||
double r = computeAdjustmentRatio(node, difference); | double r = computeAdjustmentRatio(node, difference); | ||||
int availableShrink = totalShrink - node.totalShrink; | int availableShrink = totalShrink - node.totalShrink; | ||||
int availableStretch = totalStretch - node.totalStretch; | int availableStretch = totalStretch - node.totalStretch; | ||||
* number. | * number. | ||||
* @param element the element | * @param element the element | ||||
* @param line the line number | * @param line the line number | ||||
* @param difference | |||||
* @return {@code true} if the element can end the line | * @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() | return (!element.isPenalty() | ||||
|| element.getP() < KnuthElement.INFINITE); | || element.getP() < KnuthElement.INFINITE); | ||||
} | } |
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepTogether() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithNext() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithPrevious() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ |
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
return getParentKeepTogetherStrength(); | |||||
public Keep getKeepTogether() { | |||||
return getParentKeepTogether(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithNext() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithPrevious() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
} | } |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} | |||||
} |
public static final int FLAGGED_PENALTY = 50; | public static final int FLAGGED_PENALTY = 50; | ||||
private int penalty; | private int penalty; | ||||
private boolean bFlagged; | |||||
private boolean isFlagged; | |||||
private int breakClass = -1; | private int breakClass = -1; | ||||
/** | /** | ||||
* @param p the penalty value of this penalty | * @param p the penalty value of this penalty | ||||
* @param f is this penalty flagged? | * @param f is this penalty flagged? | ||||
* @param pos the Position stored in this penalty | * @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; | penalty = p; | ||||
bFlagged = f; | |||||
isFlagged = f; | |||||
} | } | ||||
/** | /** | ||||
* @param w the width of this penalty | * @param w the width of this penalty | ||||
* @param p the penalty value of this penalty | * @param p the penalty value of this penalty | ||||
* @param f is this penalty flagged? | * @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_AUTO}, {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, | ||||
* {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}) | * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}) | ||||
* @param pos the Position stored in this penalty | * @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, | 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} */ | /** {@inheritDoc} */ | ||||
/** @return true is this penalty is a flagged one. */ | /** @return true is this penalty is a flagged one. */ | ||||
public boolean isFlagged() { | public boolean isFlagged() { | ||||
return bFlagged; | |||||
return isFlagged; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
return breakClass; | 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} */ | /** {@inheritDoc} */ | ||||
public String toString() { | public String toString() { | ||||
StringBuffer sb = new StringBuffer(64); | StringBuffer sb = new StringBuffer(64); | ||||
} | } | ||||
sb.append("penalty"); | sb.append("penalty"); | ||||
sb.append(" p="); | 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(" [flagged]"); | ||||
} | } | ||||
sb.append(" w="); | sb.append(" w="); | ||||
sb.append(getW()); | sb.append(getW()); | ||||
if (isForcedBreak()) { | 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(); | return sb.toString(); | ||||
} | } | ||||
} | } |
private int breakBefore; | private int breakBefore; | ||||
private int breakAfter; | 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; | private int disableColumnBalancing; | ||||
* Returns the strength of a keep-with-next currently pending. | * Returns the strength of a keep-with-next currently pending. | ||||
* @return the keep-with-next strength | * @return the keep-with-next strength | ||||
*/ | */ | ||||
public int getKeepWithNextPending() { | |||||
public Keep getKeepWithNextPending() { | |||||
return this.pendingKeepWithNext; | return this.pendingKeepWithNext; | ||||
} | } | ||||
* Returns the strength of a keep-with-previous currently pending. | * Returns the strength of a keep-with-previous currently pending. | ||||
* @return the keep-with-previous strength | * @return the keep-with-previous strength | ||||
*/ | */ | ||||
public int getKeepWithPreviousPending() { | |||||
public Keep getKeepWithPreviousPending() { | |||||
return this.pendingKeepWithPrevious; | return this.pendingKeepWithPrevious; | ||||
} | } | ||||
* Clears any pending keep-with-next strength. | * Clears any pending keep-with-next strength. | ||||
*/ | */ | ||||
public void clearKeepWithNextPending() { | public void clearKeepWithNextPending() { | ||||
this.pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO; | |||||
this.pendingKeepWithNext = Keep.KEEP_AUTO; | |||||
} | } | ||||
/** | /** | ||||
* Clears any pending keep-with-previous strength. | * Clears any pending keep-with-previous strength. | ||||
*/ | */ | ||||
public void clearKeepWithPreviousPending() { | public void clearKeepWithPreviousPending() { | ||||
this.pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; | |||||
this.pendingKeepWithPrevious = Keep.KEEP_AUTO; | |||||
} | } | ||||
/** | /** | ||||
/** | /** | ||||
* Updates the currently pending keep-with-next strength. | * 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. | * 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); | |||||
} | } | ||||
/** | /** | ||||
* @return true if a keep-with-next constraint is pending | * @return true if a keep-with-next constraint is pending | ||||
*/ | */ | ||||
public boolean isKeepWithNextPending() { | public boolean isKeepWithNextPending() { | ||||
return getKeepWithNextPending() != BlockLevelLayoutManager.KEEP_AUTO; | |||||
return !getKeepWithNextPending().isAuto(); | |||||
} | } | ||||
/** | /** | ||||
* @return true if a keep-with-previous constraint is pending | * @return true if a keep-with-previous constraint is pending | ||||
*/ | */ | ||||
public boolean isKeepWithPreviousPending() { | public boolean isKeepWithPreviousPending() { | ||||
return getKeepWithPreviousPending() != BlockLevelLayoutManager.KEEP_AUTO; | |||||
return !getKeepWithPreviousPending().isAuto(); | |||||
} | } | ||||
public void setLeadingSpace(SpaceSpecifier space) { | public void setLeadingSpace(SpaceSpecifier space) { | ||||
+ "\nStarts New Area: \t" + startsNewArea() | + "\nStarts New Area: \t" + startsNewArea() | ||||
+ "\nIs Last Area: \t" + isLastArea() | + "\nIs Last Area: \t" + isLastArea() | ||||
+ "\nTry Hyphenate: \t" + tryHyphenate() | + "\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" : "") + "][" | + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" | ||||
+ (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]"; | + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]"; | ||||
} | } |
pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished(); | pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished(); | ||||
} | } | ||||
/** | |||||
* @return the current child flow layout manager | |||||
*/ | |||||
/** @return the current child flow layout manager */ | |||||
protected LayoutManager getCurrentChildLM() { | protected LayoutManager getCurrentChildLM() { | ||||
return childFLM; | return childFLM; | ||||
} | } | ||||
*/ | */ | ||||
private void handleBreakTrait(int breakVal) { | private void handleBreakTrait(int breakVal) { | ||||
Page curPage = pslm.getCurrentPage(); | Page curPage = pslm.getCurrentPage(); | ||||
if (breakVal == Constants.EN_ALL) { | |||||
switch (breakVal) { | |||||
case Constants.EN_ALL: | |||||
//break due to span change in multi-column layout | //break due to span change in multi-column layout | ||||
curPage.getPageViewport().createSpan(true); | curPage.getPageViewport().createSpan(true); | ||||
return; | return; | ||||
} else if (breakVal == Constants.EN_NONE) { | |||||
case Constants.EN_NONE: | |||||
curPage.getPageViewport().createSpan(false); | curPage.getPageViewport().createSpan(false); | ||||
return; | 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(); | PageViewport pv = curPage.getPageViewport(); | ||||
//Check if previous page was spanned | //Check if previous page was spanned | ||||
boolean forceNewPageWithSpan = false; | boolean forceNewPageWithSpan = false; | ||||
RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion( | RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion( | ||||
Constants.FO_REGION_BODY); | Constants.FO_REGION_BODY); | ||||
if (rb.getColumnCount() > 1 | |||||
&& pv.getCurrentSpan().getColumnCount() == 1) { | |||||
forceNewPageWithSpan = true; | |||||
} | |||||
forceNewPageWithSpan | |||||
= (rb.getColumnCount() > 1 | |||||
&& pv.getCurrentSpan().getColumnCount() == 1); | |||||
if (forceNewPageWithSpan) { | if (forceNewPageWithSpan) { | ||||
log.trace("Forcing new page with span"); | |||||
curPage = pslm.makeNewPage(false, false); | curPage = pslm.makeNewPage(false, false); | ||||
curPage.getPageViewport().createSpan(true); | curPage.getPageViewport().createSpan(true); | ||||
} else if (pv.getCurrentSpan().hasMoreFlows()) { | } else if (pv.getCurrentSpan().hasMoreFlows()) { | ||||
log.trace("Moving to next flow"); | |||||
pv.getCurrentSpan().moveToNextFlow(); | pv.getCurrentSpan().moveToNextFlow(); | ||||
} else { | } else { | ||||
curPage = pslm.makeNewPage(false, false); | |||||
log.trace("Making new page"); | |||||
/*curPage = */pslm.makeNewPage(false, false); | |||||
} | } | ||||
return; | 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); | |||||
} | |||||
} | } | ||||
} | } | ||||
//Controls whether a single part should be forced if possible (ex. block-container) | //Controls whether a single part should be forced if possible (ex. block-container) | ||||
private boolean favorSinglePart = false; | 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, | public PageBreakingAlgorithm(LayoutManager topLevelLM, | ||||
PageProvider pageProvider, | PageProvider pageProvider, | ||||
PageBreakingLayoutListener layoutListener, | PageBreakingLayoutListener layoutListener, | ||||
footnoteElementIndex = -1; | 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} */ | /** {@inheritDoc} */ | ||||
protected KnuthNode createNode(int position, int line, int fitness, | protected KnuthNode createNode(int position, int line, int fitness, | ||||
int totalWidth, int totalStretch, int totalShrink, | int totalWidth, int totalStretch, int totalShrink, | ||||
} | } | ||||
} | } | ||||
/** | |||||
* {@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 | * Handles the footnotes cited inside a block-level box. Updates footnotesList and the | ||||
* value of totalFootnotesLength with the lengths of the given footnotes. | * value of totalFootnotesLength with the lengths of the given footnotes. | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
protected void considerLegalBreak(KnuthElement element, int elementIdx) { | 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); | super.considerLegalBreak(element, elementIdx); | ||||
newFootnotes = false; | 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, | protected int computeDifference(KnuthNode activeNode, KnuthElement element, | ||||
int elementIndex) { | int elementIndex) { | ||||
KnuthPageNode pageNode = (KnuthPageNode) activeNode; | KnuthPageNode pageNode = (KnuthPageNode) activeNode; |
return this.lastReportedBPD; | 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 | * Returns the part index (0<x<partCount) which denotes the first part on the last page | ||||
* generated by the current element list. | * generated by the current element list. | ||||
return page; | return page; | ||||
} | } | ||||
} | |||||
} |
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepTogether() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithNext() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithPrevious() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
} | } |
import org.apache.fop.fo.Constants; | import org.apache.fop.fo.Constants; | ||||
import org.apache.fop.fo.flow.Block; | import org.apache.fop.fo.flow.Block; | ||||
import org.apache.fop.fo.properties.CommonHyphenation; | 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.Font; | ||||
import org.apache.fop.fonts.FontInfo; | import org.apache.fop.fonts.FontInfo; | ||||
import org.apache.fop.fonts.FontTriplet; | import org.apache.fop.fonts.FontTriplet; | ||||
import org.apache.fop.layoutmgr.BreakingAlgorithm; | import org.apache.fop.layoutmgr.BreakingAlgorithm; | ||||
import org.apache.fop.layoutmgr.ElementListObserver; | import org.apache.fop.layoutmgr.ElementListObserver; | ||||
import org.apache.fop.layoutmgr.InlineKnuthSequence; | 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.KnuthBlockBox; | ||||
import org.apache.fop.layoutmgr.KnuthBox; | import org.apache.fop.layoutmgr.KnuthBox; | ||||
import org.apache.fop.layoutmgr.KnuthElement; | import org.apache.fop.layoutmgr.KnuthElement; | ||||
for (int p = 0; p < knuthParagraphs.size(); p++) { | for (int p = 0; p < knuthParagraphs.size(); p++) { | ||||
// penalty between paragraphs | // penalty between paragraphs | ||||
if (p > 0) { | 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; | LineLayoutPossibilities llPoss; | ||||
&& i >= fobj.getOrphans() | && i >= fobj.getOrphans() | ||||
&& i <= llPoss.getChosenLineCount() - fobj.getWidows()) { | && i <= llPoss.getChosenLineCount() - fobj.getWidows()) { | ||||
// penalty allowing a page break between lines | // 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 | int endIndex | ||||
= ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos(); | = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos(); | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@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} */ | /** {@inheritDoc} */ | ||||
public boolean mustKeepWithPrevious() { | public boolean mustKeepWithPrevious() { | ||||
return getKeepWithPreviousStrength() > KEEP_AUTO; | |||||
return !getKeepWithPrevious().isAuto(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public boolean mustKeepWithNext() { | public boolean mustKeepWithNext() { | ||||
return getKeepWithNextStrength() > KEEP_AUTO; | |||||
return !getKeepWithNext().isAuto(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithNext() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithPrevious() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
break; | break; | ||||
} | } | ||||
//TODO Something's not right here. See block_hyphenation_linefeed_preserve.xml | //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; | // collect word fragments, ignoring auxiliary elements; | ||||
// each word fragment was created by a different TextLM | // each word fragment was created by a different TextLM |
import org.apache.fop.area.Area; | import org.apache.fop.area.Area; | ||||
import org.apache.fop.area.Block; | import org.apache.fop.area.Block; | ||||
import org.apache.fop.fo.flow.ListBlock; | 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.BlockStackingLayoutManager; | ||||
import org.apache.fop.layoutmgr.ConditionalElementListener; | import org.apache.fop.layoutmgr.ConditionalElementListener; | ||||
import org.apache.fop.layoutmgr.ElementListUtils; | import org.apache.fop.layoutmgr.ElementListUtils; | ||||
import org.apache.fop.layoutmgr.KeepUtil; | |||||
import org.apache.fop.layoutmgr.LayoutContext; | import org.apache.fop.layoutmgr.LayoutContext; | ||||
import org.apache.fop.layoutmgr.LayoutManager; | import org.apache.fop.layoutmgr.LayoutManager; | ||||
import org.apache.fop.layoutmgr.NonLeafPosition; | import org.apache.fop.layoutmgr.NonLeafPosition; | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength( | |||||
getListBlockFO().getKeepTogether()); | |||||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||||
return strength; | |||||
public KeepProperty getKeepTogetherProperty() { | |||||
return getListBlockFO().getKeepTogether(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithNext()); | |||||
public KeepProperty getKeepWithPreviousProperty() { | |||||
return getListBlockFO().getKeepWithPrevious(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithPrevious()); | |||||
public KeepProperty getKeepWithNextProperty() { | |||||
return getListBlockFO().getKeepWithNext(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ |
import org.apache.fop.fo.flow.AbstractListItemPart; | import org.apache.fop.fo.flow.AbstractListItemPart; | ||||
import org.apache.fop.fo.flow.ListItemBody; | import org.apache.fop.fo.flow.ListItemBody; | ||||
import org.apache.fop.fo.flow.ListItemLabel; | 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.BlockStackingLayoutManager; | ||||
import org.apache.fop.layoutmgr.KeepUtil; | |||||
import org.apache.fop.layoutmgr.Keep; | |||||
import org.apache.fop.layoutmgr.LayoutContext; | import org.apache.fop.layoutmgr.LayoutContext; | ||||
import org.apache.fop.layoutmgr.LayoutManager; | import org.apache.fop.layoutmgr.LayoutManager; | ||||
import org.apache.fop.layoutmgr.NonLeafPosition; | import org.apache.fop.layoutmgr.NonLeafPosition; | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getPartFO().getKeepTogether()); | |||||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||||
return strength; | |||||
public KeepProperty getKeepTogetherProperty() { | |||||
return getPartFO().getKeepTogether(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithNext() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithPrevious() { | |||||
return Keep.KEEP_AUTO; | |||||
} | } | ||||
} | } |
import org.apache.fop.fo.flow.ListItem; | import org.apache.fop.fo.flow.ListItem; | ||||
import org.apache.fop.fo.flow.ListItemBody; | import org.apache.fop.fo.flow.ListItemBody; | ||||
import org.apache.fop.fo.flow.ListItemLabel; | 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.BlockStackingLayoutManager; | ||||
import org.apache.fop.layoutmgr.BreakElement; | import org.apache.fop.layoutmgr.BreakElement; | ||||
import org.apache.fop.layoutmgr.ConditionalElementListener; | import org.apache.fop.layoutmgr.ConditionalElementListener; | ||||
import org.apache.fop.layoutmgr.ElementListObserver; | import org.apache.fop.layoutmgr.ElementListObserver; | ||||
import org.apache.fop.layoutmgr.ElementListUtils; | 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.KnuthBlockBox; | ||||
import org.apache.fop.layoutmgr.KnuthBox; | import org.apache.fop.layoutmgr.KnuthBox; | ||||
import org.apache.fop.layoutmgr.KnuthElement; | import org.apache.fop.layoutmgr.KnuthElement; | ||||
private MinOptMax effSpaceBefore; | private MinOptMax effSpaceBefore; | ||||
private MinOptMax effSpaceAfter; | private MinOptMax effSpaceAfter; | ||||
private int keepWithNextPendingOnLabel; | |||||
private int keepWithNextPendingOnBody; | |||||
private Keep keepWithNextPendingOnLabel; | |||||
private Keep keepWithNextPendingOnBody; | |||||
private int listItemHeight; | private int listItemHeight; | ||||
context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel); | context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel); | ||||
context.updateKeepWithNextPending(this.keepWithNextPendingOnBody); | context.updateKeepWithNextPending(this.keepWithNextPendingOnBody); | ||||
context.updateKeepWithNextPending(getKeepWithNextStrength()); | |||||
context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); | |||||
context.updateKeepWithNextPending(getKeepWithNext()); | |||||
context.updateKeepWithPreviousPending(getKeepWithPrevious()); | |||||
setFinished(true); | setFinished(true); | ||||
resetSpaces(); | resetSpaces(); | ||||
int totalHeight = Math.max(fullHeights[0], fullHeights[1]); | int totalHeight = Math.max(fullHeights[0], fullHeights[1]); | ||||
int step; | int step; | ||||
int addedBoxHeight = 0; | int addedBoxHeight = 0; | ||||
int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO; | |||||
Keep keepWithNextActive = Keep.KEEP_AUTO; | |||||
LinkedList returnList = new LinkedList(); | LinkedList returnList = new LinkedList(); | ||||
while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { | while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { | ||||
if (end[0] + 1 == elementLists[0].size()) { | if (end[0] + 1 == elementLists[0].size()) { | ||||
keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel); | |||||
keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnLabel); | |||||
} | } | ||||
if (end[1] + 1 == elementLists[1].size()) { | if (end[1] + 1 == elementLists[1].size()) { | ||||
keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnBody); | |||||
keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnBody); | |||||
} | } | ||||
// compute penalty height and box height | // compute penalty height and box height | ||||
} | } | ||||
if (addedBoxHeight < totalHeight) { | 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; | int p = stepPenalty; | ||||
if (p > -KnuthElement.INFINITE) { | 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)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength( | |||||
getListItemFO().getKeepTogether()); | |||||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||||
return strength; | |||||
public KeepProperty getKeepTogetherProperty() { | |||||
return getListItemFO().getKeepTogether(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithNext()); | |||||
public KeepProperty getKeepWithPreviousProperty() { | |||||
return getListItemFO().getKeepWithPrevious(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithPrevious()); | |||||
public KeepProperty getKeepWithNextProperty() { | |||||
return getListItemFO().getKeepWithNext(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ |
import org.apache.fop.fo.flow.table.EffRow; | import org.apache.fop.fo.flow.table.EffRow; | ||||
import org.apache.fop.fo.flow.table.PrimaryGridUnit; | import org.apache.fop.fo.flow.table.PrimaryGridUnit; | ||||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | ||||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||||
import org.apache.fop.layoutmgr.ElementListUtils; | import org.apache.fop.layoutmgr.ElementListUtils; | ||||
import org.apache.fop.layoutmgr.Keep; | |||||
import org.apache.fop.layoutmgr.KnuthBlockBox; | import org.apache.fop.layoutmgr.KnuthBlockBox; | ||||
import org.apache.fop.layoutmgr.KnuthBox; | import org.apache.fop.layoutmgr.KnuthBox; | ||||
import org.apache.fop.layoutmgr.KnuthElement; | import org.apache.fop.layoutmgr.KnuthElement; | ||||
/** True if the next CellPart that will be created will be the last one for this cell. */ | /** True if the next CellPart that will be created will be the last one for this cell. */ | ||||
private boolean lastCellPart; | private boolean lastCellPart; | ||||
private int keepWithNextStrength; | |||||
private Keep keepWithNext; | |||||
private int spanIndex = 0; | private int spanIndex = 0; | ||||
includedLength = -1; // Avoid troubles with cells having content of zero length | includedLength = -1; // Avoid troubles with cells having content of zero length | ||||
totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); | totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); | ||||
endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1; | endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1; | ||||
keepWithNextStrength = BlockLevelLayoutManager.KEEP_AUTO; | |||||
keepWithNext = Keep.KEEP_AUTO; | |||||
remainingLength = totalLength - previousRowsLength; | remainingLength = totalLength - previousRowsLength; | ||||
afterNextStep = new Step(previousRowsLength); | afterNextStep = new Step(previousRowsLength); | ||||
KnuthElement el = (KnuthElement) knuthIter.next(); | KnuthElement el = (KnuthElement) knuthIter.next(); | ||||
if (el.isPenalty()) { | if (el.isPenalty()) { | ||||
prevIsBox = false; | 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 | // First legal break point | ||||
breakFound = true; | breakFound = true; | ||||
KnuthPenalty p = (KnuthPenalty) el; | KnuthPenalty p = (KnuthPenalty) el; | ||||
*/ | */ | ||||
CellPart createCellPart() { | CellPart createCellPart() { | ||||
if (nextStep.end + 1 == elementList.size()) { | 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 | // TODO if keep-with-next is set on the row, must every cell of the row | ||||
// contribute some content from children blocks? | // contribute some content from children blocks? | ||||
// see http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200802.mbox/ | // see http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200802.mbox/ | ||||
} | } | ||||
} | } | ||||
int getKeepWithNextStrength() { | |||||
return keepWithNextStrength; | |||||
Keep getKeepWithNext() { | |||||
return keepWithNext; | |||||
} | } | ||||
int getPenaltyValue() { | int getPenaltyValue() { |
LinkedList returnList = new LinkedList(); | LinkedList returnList = new LinkedList(); | ||||
createElementsForRowGroup(context, alignment, bodyType, returnList); | 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; | int breakBefore = Constants.EN_AUTO; | ||||
TableRow firstRow = rowGroup[0].getTableRow(); | TableRow firstRow = rowGroup[0].getTableRow(); |
import org.apache.fop.area.Block; | import org.apache.fop.area.Block; | ||||
import org.apache.fop.fo.flow.table.TableAndCaption; | import org.apache.fop.fo.flow.table.TableAndCaption; | ||||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | ||||
import org.apache.fop.layoutmgr.Keep; | |||||
import org.apache.fop.layoutmgr.LayoutContext; | import org.apache.fop.layoutmgr.LayoutContext; | ||||
import org.apache.fop.layoutmgr.PositionIterator; | import org.apache.fop.layoutmgr.PositionIterator; | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@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! | /* TODO Complete me! | ||||
return KeepUtil.getCombinedBlockLevelKeepStrength( | return KeepUtil.getCombinedBlockLevelKeepStrength( | ||||
getTableAndCaptionFO().getKeepWithNext()); | getTableAndCaptionFO().getKeepWithNext()); | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithPrevious() { | |||||
return Keep.KEEP_AUTO; | |||||
/* TODO Complete me! | /* TODO Complete me! | ||||
return KeepUtil.getCombinedBlockLevelKeepStrength( | return KeepUtil.getCombinedBlockLevelKeepStrength( | ||||
getTableAndCaptionFO().getKeepWithPrevious()); | getTableAndCaptionFO().getKeepWithPrevious()); | ||||
*/ | */ | ||||
} | } | ||||
} | |||||
} |
import org.apache.fop.area.Block; | import org.apache.fop.area.Block; | ||||
import org.apache.fop.fo.flow.table.TableCaption; | import org.apache.fop.fo.flow.table.TableCaption; | ||||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | ||||
import org.apache.fop.layoutmgr.Keep; | |||||
import org.apache.fop.layoutmgr.LayoutContext; | import org.apache.fop.layoutmgr.LayoutContext; | ||||
import org.apache.fop.layoutmgr.PositionIterator; | import org.apache.fop.layoutmgr.PositionIterator; | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@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! | /* TODO Complete me! | ||||
return KeepUtil.getCombinedBlockLevelKeepStrength( | return KeepUtil.getCombinedBlockLevelKeepStrength( | ||||
getTableCaptionFO().getKeepWithNext()); | getTableCaptionFO().getKeepWithNext()); | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KEEP_AUTO; | |||||
public Keep getKeepWithPrevious() { | |||||
return Keep.KEEP_AUTO; | |||||
/* TODO Complete me! | /* TODO Complete me! | ||||
return KeepUtil.getCombinedBlockLevelKeepStrength( | return KeepUtil.getCombinedBlockLevelKeepStrength( | ||||
getTableCaptionFO().getKeepWithPrevious()); | getTableCaptionFO().getKeepWithPrevious()); |
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.fop.area.Area; | import org.apache.fop.area.Area; | ||||
import org.apache.fop.area.Block; | import org.apache.fop.area.Block; | ||||
import org.apache.fop.area.Trait; | import org.apache.fop.area.Trait; | ||||
import org.apache.fop.fo.flow.table.GridUnit; | import org.apache.fop.fo.flow.table.GridUnit; | ||||
import org.apache.fop.fo.flow.table.PrimaryGridUnit; | import org.apache.fop.fo.flow.table.PrimaryGridUnit; | ||||
import org.apache.fop.fo.flow.table.Table; | 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.TableCell; | ||||
import org.apache.fop.fo.flow.table.TableColumn; | 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.flow.table.TableRow; | ||||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | ||||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; | import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; | ||||
import org.apache.fop.layoutmgr.AreaAdditionUtil; | import org.apache.fop.layoutmgr.AreaAdditionUtil; | ||||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | ||||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | 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.KnuthBox; | ||||
import org.apache.fop.layoutmgr.KnuthElement; | import org.apache.fop.layoutmgr.KnuthElement; | ||||
import org.apache.fop.layoutmgr.KnuthGlue; | import org.apache.fop.layoutmgr.KnuthGlue; | ||||
import org.apache.fop.layoutmgr.KnuthPenalty; | import org.apache.fop.layoutmgr.KnuthPenalty; | ||||
import org.apache.fop.layoutmgr.LayoutContext; | import org.apache.fop.layoutmgr.LayoutContext; | ||||
import org.apache.fop.layoutmgr.LayoutManager; | |||||
import org.apache.fop.layoutmgr.Position; | import org.apache.fop.layoutmgr.Position; | ||||
import org.apache.fop.layoutmgr.PositionIterator; | import org.apache.fop.layoutmgr.PositionIterator; | ||||
import org.apache.fop.layoutmgr.SpaceResolver; | import org.apache.fop.layoutmgr.SpaceResolver; | ||||
List contentList = new LinkedList(); | List contentList = new LinkedList(); | ||||
List returnList = 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); | LayoutContext childLC = new LayoutContext(0); | ||||
// curLM is a ? | // curLM is a ? | ||||
childLC.setStackLimitBP(MinOptMax.subtract(context | childLC.setStackLimitBP(MinOptMax.subtract(context | ||||
log.debug("child LM signals pending keep with next"); | log.debug("child LM signals pending keep with next"); | ||||
} | } | ||||
if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { | if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { | ||||
primaryGridUnit.setKeepWithPreviousStrength(childLC.getKeepWithPreviousPending()); | |||||
primaryGridUnit.setKeepWithPrevious(childLC.getKeepWithPreviousPending()); | |||||
childLC.clearKeepWithPreviousPending(); | childLC.clearKeepWithPreviousPending(); | ||||
} | } | ||||
if (prevLM != null) { | |||||
if (prevLM != null | |||||
&& !ElementListUtils.endsWithForcedBreak(contentList)) { | |||||
// there is a block handled by prevLM | // there is a block handled by prevLM | ||||
// before the one handled by curLM | // before the one handled by curLM | ||||
addInBetweenBreak(contentList, context, childLC); | addInBetweenBreak(contentList, context, childLC); | ||||
} | } | ||||
prevLM = curLM; | prevLM = curLM; | ||||
} | } | ||||
primaryGridUnit.setKeepWithNextStrength(context.getKeepWithNextPending()); | |||||
primaryGridUnit.setKeepWithNext(context.getKeepWithNextPending()); | |||||
returnedList = new LinkedList(); | returnedList = new LinkedList(); | ||||
if (!contentList.isEmpty()) { | if (!contentList.isEmpty()) { | ||||
} | } | ||||
final KnuthElement lastItem = (KnuthElement) ListUtil | final KnuthElement lastItem = (KnuthElement) ListUtil | ||||
.getLast(returnList); | .getLast(returnList); | ||||
if (((KnuthElement) lastItem).isForcedBreak()) { | |||||
if (lastItem.isForcedBreak()) { | |||||
KnuthPenalty p = (KnuthPenalty) lastItem; | KnuthPenalty p = (KnuthPenalty) lastItem; | ||||
primaryGridUnit.setBreakAfter(p.getBreakClass()); | primaryGridUnit.setBreakAfter(p.getBreakClass()); | ||||
p.setP(0); | p.setP(0); | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
int strength = KEEP_AUTO; | |||||
public Keep getKeepTogether() { | |||||
Keep keep = Keep.KEEP_AUTO; | |||||
if (primaryGridUnit.getRow() != null) { | 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} */ | /** {@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} */ | /** {@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 --------- // | // --------- Property Resolution related functions --------- // |
import org.apache.fop.fo.flow.table.PrimaryGridUnit; | import org.apache.fop.fo.flow.table.PrimaryGridUnit; | ||||
import org.apache.fop.fo.flow.table.Table; | import org.apache.fop.fo.flow.table.Table; | ||||
import org.apache.fop.fo.flow.table.TablePart; | 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.BreakElement; | ||||
import org.apache.fop.layoutmgr.ElementListUtils; | 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.KnuthBox; | ||||
import org.apache.fop.layoutmgr.KnuthElement; | import org.apache.fop.layoutmgr.KnuthElement; | ||||
import org.apache.fop.layoutmgr.KnuthGlue; | import org.apache.fop.layoutmgr.KnuthGlue; | ||||
context.clearKeepsPending(); | context.clearKeepsPending(); | ||||
context.setBreakBefore(Constants.EN_AUTO); | context.setBreakBefore(Constants.EN_AUTO); | ||||
context.setBreakAfter(Constants.EN_AUTO); | context.setBreakAfter(Constants.EN_AUTO); | ||||
int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; | |||||
Keep keepWithPrevious = Keep.KEEP_AUTO; | |||||
int breakBefore = Constants.EN_AUTO; | int breakBefore = Constants.EN_AUTO; | ||||
if (rowGroup != null) { | if (rowGroup != null) { | ||||
RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, | RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, | ||||
stepper); | stepper); | ||||
List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); | List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); | ||||
keepWithPrevious = Math.max(keepWithPrevious, context.getKeepWithPreviousPending()); | |||||
keepWithPrevious = keepWithPrevious.compare(context.getKeepWithPreviousPending()); | |||||
breakBefore = context.getBreakBefore(); | breakBefore = context.getBreakBefore(); | ||||
int breakBetween = context.getBreakAfter(); | int breakBetween = context.getBreakAfter(); | ||||
returnList.addAll(nextRowGroupElems); | returnList.addAll(nextRowGroupElems); | ||||
//Note previous pending keep-with-next and clear the strength | //Note previous pending keep-with-next and clear the strength | ||||
//(as the layout context is reused) | //(as the layout context is reused) | ||||
int keepWithNextPending = context.getKeepWithNextPending(); | |||||
Keep keepWithNextPending = context.getKeepWithNextPending(); | |||||
context.clearKeepWithNextPending(); | context.clearKeepWithNextPending(); | ||||
//Get elements for next row group | //Get elements for next row group | ||||
*/ | */ | ||||
//Determine keep constraints | //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(); | 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, | breakBetween = BreakUtil.compareBreakClasses(breakBetween, | ||||
context.getBreakBefore()); | context.getBreakBefore()); | ||||
if (breakBetween != Constants.EN_AUTO) { | if (breakBetween != Constants.EN_AUTO) { | ||||
penaltyValue = -KnuthElement.INFINITE; | penaltyValue = -KnuthElement.INFINITE; | ||||
breakClass = breakBetween; | |||||
} | } | ||||
BreakElement breakElement; | BreakElement breakElement; | ||||
ListIterator elemIter = returnList.listIterator(returnList.size()); | ListIterator elemIter = returnList.listIterator(returnList.size()); | ||||
breakElement = (BreakElement) elem; | breakElement = (BreakElement) elem; | ||||
} | } | ||||
breakElement.setPenaltyValue(penaltyValue); | breakElement.setPenaltyValue(penaltyValue); | ||||
breakElement.setBreakClass(breakBetween); | |||||
breakElement.setBreakClass(breakClass); | |||||
returnList.addAll(nextRowGroupElems); | returnList.addAll(nextRowGroupElems); | ||||
breakBetween = context.getBreakAfter(); | breakBetween = context.getBreakAfter(); | ||||
} | } |
import org.apache.fop.fo.FObj; | import org.apache.fop.fo.FObj; | ||||
import org.apache.fop.fo.flow.table.Table; | import org.apache.fop.fo.flow.table.Table; | ||||
import org.apache.fop.fo.flow.table.TableColumn; | 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.BlockLevelEventProducer; | ||||
import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | import org.apache.fop.layoutmgr.BlockStackingLayoutManager; | ||||
import org.apache.fop.layoutmgr.BreakElement; | import org.apache.fop.layoutmgr.BreakElement; | ||||
import org.apache.fop.layoutmgr.ConditionalElementListener; | import org.apache.fop.layoutmgr.ConditionalElementListener; | ||||
import org.apache.fop.layoutmgr.KeepUtil; | |||||
import org.apache.fop.layoutmgr.KnuthElement; | import org.apache.fop.layoutmgr.KnuthElement; | ||||
import org.apache.fop.layoutmgr.KnuthGlue; | import org.apache.fop.layoutmgr.KnuthGlue; | ||||
import org.apache.fop.layoutmgr.LayoutContext; | import org.apache.fop.layoutmgr.LayoutContext; | ||||
log.debug(contentKnuthElements); | log.debug(contentKnuthElements); | ||||
wrapPositionElements(contentKnuthElements, returnList); | wrapPositionElements(contentKnuthElements, returnList); | ||||
context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); | |||||
context.updateKeepWithPreviousPending(getKeepWithPrevious()); | |||||
context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); | context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); | ||||
context.updateKeepWithNextPending(getKeepWithNextStrength()); | |||||
context.updateKeepWithNextPending(getKeepWithNext()); | |||||
context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); | context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); | ||||
if (getTable().isSeparateBorderModel()) { | if (getTable().isSeparateBorderModel()) { | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepTogetherStrength() { | |||||
int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepTogether()); | |||||
strength = Math.max(strength, getParentKeepTogetherStrength()); | |||||
return strength; | |||||
public KeepProperty getKeepTogetherProperty() { | |||||
return getTable().getKeepTogether(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithNextStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithNext()); | |||||
public KeepProperty getKeepWithPreviousProperty() { | |||||
return getTable().getKeepWithPrevious(); | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public int getKeepWithPreviousStrength() { | |||||
return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithPrevious()); | |||||
public KeepProperty getKeepWithNextProperty() { | |||||
return getTable().getKeepWithNext(); | |||||
} | } | ||||
// --------- Property Resolution related functions --------- // | // --------- Property Resolution related functions --------- // |
import org.apache.fop.fo.flow.table.EffRow; | import org.apache.fop.fo.flow.table.EffRow; | ||||
import org.apache.fop.fo.flow.table.GridUnit; | import org.apache.fop.fo.flow.table.GridUnit; | ||||
import org.apache.fop.fo.flow.table.PrimaryGridUnit; | 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.BreakElement; | ||||
import org.apache.fop.layoutmgr.KeepUtil; | |||||
import org.apache.fop.layoutmgr.Keep; | |||||
import org.apache.fop.layoutmgr.KnuthBlockBox; | import org.apache.fop.layoutmgr.KnuthBlockBox; | ||||
import org.apache.fop.layoutmgr.KnuthBox; | import org.apache.fop.layoutmgr.KnuthBox; | ||||
import org.apache.fop.layoutmgr.KnuthElement; | |||||
import org.apache.fop.layoutmgr.KnuthGlue; | import org.apache.fop.layoutmgr.KnuthGlue; | ||||
import org.apache.fop.layoutmgr.KnuthPenalty; | import org.apache.fop.layoutmgr.KnuthPenalty; | ||||
import org.apache.fop.layoutmgr.LayoutContext; | import org.apache.fop.layoutmgr.LayoutContext; | ||||
} | } | ||||
} | } | ||||
int strength = BlockLevelLayoutManager.KEEP_AUTO; | |||||
Keep keep = Keep.KEEP_AUTO; | |||||
int stepPenalty = 0; | int stepPenalty = 0; | ||||
for (Iterator iter = activeCells.iterator(); iter.hasNext();) { | for (Iterator iter = activeCells.iterator(); iter.hasNext();) { | ||||
ActiveCell activeCell = (ActiveCell) iter.next(); | ActiveCell activeCell = (ActiveCell) iter.next(); | ||||
strength = Math.max(strength, activeCell.getKeepWithNextStrength()); | |||||
keep = keep.compare(activeCell.getKeepWithNext()); | |||||
stepPenalty = Math.max(stepPenalty, activeCell.getPenaltyValue()); | stepPenalty = Math.max(stepPenalty, activeCell.getPenaltyValue()); | ||||
} | } | ||||
if (!rowFinished) { | 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... | //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) { | } 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, | nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass, | ||||
rowGroup[activeRowIndex].getBreakAfter()); | rowGroup[activeRowIndex].getBreakAfter()); | ||||
nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass, | nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass, | ||||
rowGroup[activeRowIndex + 1].getBreakBefore()); | rowGroup[activeRowIndex + 1].getBreakBefore()); | ||||
} | } | ||||
int p = KeepUtil.getPenaltyForKeep(strength); | |||||
int p = keep.getPenalty(); | |||||
if (rowHeightSmallerThanFirstStep) { | if (rowHeightSmallerThanFirstStep) { | ||||
rowHeightSmallerThanFirstStep = false; | rowHeightSmallerThanFirstStep = false; | ||||
p = KnuthPenalty.INFINITE; | 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) { | if (nextBreakClass != Constants.EN_AUTO) { | ||||
log.trace("Forced break encountered"); | log.trace("Forced break encountered"); | ||||
p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0) | 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) { | if (penaltyOrGlueLen < 0) { | ||||
returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true)); | returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true)); | ||||
} | } |
documents. Example: the fix of marks layering will be such a case when it's done. | documents. Example: the fix of marks layering will be such a case when it's done. | ||||
--> | --> | ||||
<release version="FOP Trunk" date="TBD"> | <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"> | <action context="Renderers" dev="AD" type="fix" fixes-bug="46883"> | ||||
Hotspot in AbstractGraphicsDrawingOrderContainer. Reduced time spent in the method | Hotspot in AbstractGraphicsDrawingOrderContainer. Reduced time spent in the method | ||||
by introducing a member variable to hold the data-length. | by introducing a member variable to hold the data-length. |
<description>A soft hyphen should be a preferred as break compared to a | <description>A soft hyphen should be a preferred as break compared to a | ||||
normal hyphenation point but is not.</description> | normal hyphenation point but is not.</description> | ||||
</testcase> | </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> | </disabled-testcases> |
<skip>5</skip> | <skip>5</skip> | ||||
<!-- penalty between blocks b11 and b12, set by InlineLM in b1 --> | <!-- penalty between blocks b11 and b12, set by InlineLM in b1 --> | ||||
<penalty w="0" p="0"/> | <penalty w="0" p="0"/> | ||||
<skip>6</skip> | |||||
<skip>5</skip> | |||||
<!-- penalty between blocks b21 and b22, set by InlineLM in b2 --> | <!-- penalty between blocks b21 and b22, set by InlineLM in b2 --> | ||||
<!-- keep-together.within-page="always" --> | <!-- keep-together.within-page="always" --> | ||||
<penalty w="0" p="1000"/> | <penalty w="0" p="1000"/> | ||||
<skip>6</skip> | |||||
<skip>3</skip> | |||||
<!-- penalty between blocks b31 and b32, set by InlineLM in b3 --> | <!-- penalty between blocks b31 and b32, set by InlineLM in b3 --> | ||||
<!-- keep-with-next.within-page="always" --> | <!-- keep-with-next.within-page="always" --> | ||||
<penalty w="0" p="1000"/> | <penalty w="0" p="1000"/> | ||||
<skip>5</skip> | |||||
<skip>3</skip> | |||||
<skip>14</skip> | |||||
</element-list> | </element-list> | ||||
</checks> | </checks> | ||||
</testcase> | </testcase> |
<?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> | |||||
<?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> |
<element-list category="breaker" index="0"> | <element-list category="breaker" index="0"> | ||||
<box w="14400"/> | <box w="14400"/> | ||||
<penalty w="0" p="0"/> | <penalty w="0" p="0"/> | ||||
<box w="28800"/> | |||||
<penalty w="0" p="0"/> | |||||
<box w="14400"/> | <box w="14400"/> | ||||
<skip>3</skip> | |||||
<penalty w="0" p="INF"/> | |||||
<box w="14400"/> | |||||
<skip>5</skip> | |||||
</element-list> | </element-list> | ||||
</checks> | </checks> | ||||
</testcase> | </testcase> |
<element-list category="breaker" index="0"> | <element-list category="breaker" index="0"> | ||||
<box w="14400"/> | <box w="14400"/> | ||||
<penalty w="0" p="0"/> | <penalty w="0" p="0"/> | ||||
<box w="28800"/> | |||||
<box w="14400"/> | |||||
<penalty w="0" p="INF"/> | |||||
<box w="14400"/> | |||||
<penalty w="0" p="INF"/> | <penalty w="0" p="INF"/> | ||||
<box w="14400"/> | <box w="14400"/> | ||||
<penalty w="0" p="0"/> | <penalty w="0" p="0"/> |