diff options
author | Andreas L. Delmelle <adelmelle@apache.org> | 2009-08-23 20:27:48 +0000 |
---|---|---|
committer | Andreas L. Delmelle <adelmelle@apache.org> | 2009-08-23 20:27:48 +0000 |
commit | a6b2b2e4b9c9d42fabe160a1f5682dfd5903f052 (patch) | |
tree | 85f3566090fe3eec137495609928f0e8229e0815 /src/java | |
parent | 6f8f64269426d81124876958b437536536b469f2 (diff) | |
download | xmlgraphics-fop-a6b2b2e4b9c9d42fabe160a1f5682dfd5903f052.tar.gz xmlgraphics-fop-a6b2b2e4b9c9d42fabe160a1f5682dfd5903f052.zip |
Bugzilla 46905: Added basic implementation for column-level keeps.
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-ffa450edef68
Diffstat (limited to 'src/java')
30 files changed, 777 insertions, 494 deletions
diff --git a/src/java/org/apache/fop/fo/flow/table/EffRow.java b/src/java/org/apache/fop/fo/flow/table/EffRow.java index 16d507303..a5853cd91 100644 --- a/src/java/org/apache/fop/fo/flow/table/EffRow.java +++ b/src/java/org/apache/fop/fo/flow/table/EffRow.java @@ -23,8 +23,7 @@ import java.util.Iterator; import java.util.List; import org.apache.fop.fo.Constants; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; -import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.table.TableRowIterator; import org.apache.fop.traits.MinOptMax; import org.apache.fop.util.BreakUtil; @@ -170,20 +169,19 @@ public class EffRow { * * @return the strength of the keep-with-previous constraint */ - public int getKeepWithPreviousStrength() { - int strength = BlockLevelLayoutManager.KEEP_AUTO; + public Keep getKeepWithPrevious() { + Keep keep = Keep.KEEP_AUTO; TableRow row = getTableRow(); if (row != null) { - strength = Math.max(strength, - KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithPrevious())); + keep = Keep.getKeep(row.getKeepWithPrevious()); } for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); if (gu.isPrimary()) { - strength = Math.max(strength, gu.getPrimary().getKeepWithPreviousStrength()); + keep = keep.compare(gu.getPrimary().getKeepWithPrevious()); } } - return strength; + return keep; } /** @@ -192,20 +190,19 @@ public class EffRow { * * @return the strength of the keep-with-next constraint */ - public int getKeepWithNextStrength() { - int strength = BlockLevelLayoutManager.KEEP_AUTO; + public Keep getKeepWithNext() { + Keep keep = Keep.KEEP_AUTO; TableRow row = getTableRow(); if (row != null) { - strength = Math.max(strength, - KeepUtil.getCombinedBlockLevelKeepStrength(row.getKeepWithNext())); + keep = Keep.getKeep(row.getKeepWithNext()); } for (Iterator iter = gridUnits.iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) { - strength = Math.max(strength, gu.getPrimary().getKeepWithNextStrength()); + keep = keep.compare(gu.getPrimary().getKeepWithNext()); } } - return strength; + return keep; } /** @@ -213,16 +210,13 @@ public class EffRow { * not take the parent table's keeps into account! * @return the keep-together strength */ - public int getKeepTogetherStrength() { + public Keep getKeepTogether() { TableRow row = getTableRow(); - int strength = BlockLevelLayoutManager.KEEP_AUTO; + Keep keep = Keep.KEEP_AUTO; if (row != null) { - strength = Math.max(strength, KeepUtil.getKeepStrength( - row.getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - row.getKeepTogether().getWithinColumn())); + keep = Keep.getKeep(row.getKeepTogether()); } - return strength; + return keep; } /** diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java index 3254e928b..9326d6cd4 100644 --- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java +++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java @@ -19,14 +19,13 @@ package org.apache.fop.fo.flow.table; -import java.util.LinkedList; import java.util.List; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.ElementListUtils; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.table.TableCellLayoutManager; /** @@ -54,8 +53,8 @@ public class PrimaryGridUnit extends GridUnit { private boolean isSeparateBorderModel; private int halfBorderSeparationBPD; - private int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; - private int keepWithNext = BlockLevelLayoutManager.KEEP_AUTO; + private Keep keepWithPrevious = Keep.KEEP_AUTO; + private Keep keepWithNext = Keep.KEEP_AUTO; private int breakBefore = Constants.EN_AUTO; private int breakAfter = Constants.EN_AUTO; @@ -334,16 +333,16 @@ public class PrimaryGridUnit extends GridUnit { * * @return the keep-with-previous strength */ - public int getKeepWithPreviousStrength() { + public Keep getKeepWithPrevious() { return keepWithPrevious; } /** * Don't use, reserved for TableCellLM. TODO - * @param strength the keep strength + * @param keep the keep strength */ - public void setKeepWithPreviousStrength(int strength) { - this.keepWithPrevious = strength; + public void setKeepWithPrevious(Keep keep) { + this.keepWithPrevious = keep; } /** @@ -352,16 +351,16 @@ public class PrimaryGridUnit extends GridUnit { * * @return the keep-with-next strength */ - public int getKeepWithNextStrength() { + public Keep getKeepWithNext() { return keepWithNext; } /** * Don't use, reserved for TableCellLM. TODO - * @param strength the keep strength + * @param keep the keep strength */ - public void setKeepWithNextStrength(int strength) { - this.keepWithNext = strength; + public void setKeepWithNext(Keep keep) { + this.keepWithNext = keep; } /** diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index b6dd4d082..4a4becebf 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -37,6 +37,7 @@ import org.apache.fop.datatypes.FODimension; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.flow.BlockContainer; import org.apache.fop.fo.properties.CommonAbsolutePosition; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; import org.apache.fop.util.ListUtil; @@ -261,7 +262,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (!firstVisibleMarkServed) { addKnuthElementsForSpaceBefore(returnList, alignment); - context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); + context.updateKeepWithPreviousPending(getKeepWithPrevious()); } addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); @@ -271,9 +272,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager //Spaces, border and padding to be repeated at each break addPendingMarks(context); - BlockLevelLayoutManager curLM; // currently active LM - BlockLevelLayoutManager prevLM = null; // previously active LM - while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { + LayoutManager curLM; // currently active LM + LayoutManager prevLM = null; // previously active LM + while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); childLC.copyPendingMarksFrom(context); // curLM is a ? @@ -323,8 +324,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager //Avoid NoSuchElementException below (happens with empty blocks) continue; } - if (((ListElement) ListUtil.getLast(returnedList)) - .isForcedBreak()) { + if (ElementListUtils.endsWithForcedBreak(returnedList)) { // a descendant of this block has break-after if (curLM.isFinished()) { // there is no other content in this block; @@ -391,7 +391,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager context.clearPendingMarks(); addKnuthElementsForBreakAfter(returnList, context); - context.updateKeepWithNextPending(getKeepWithNextStrength()); + context.updateKeepWithNextPending(getKeepWithNext()); setFinished(true); return returnList; @@ -1011,23 +1011,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - int strength = KeepUtil.getCombinedBlockLevelKeepStrength( - getBlockContainerFO().getKeepTogether()); - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; + public KeepProperty getKeepTogetherProperty() { + return getBlockContainerFO().getKeepTogether(); } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength( - getBlockContainerFO().getKeepWithNext()); + public KeepProperty getKeepWithPreviousProperty() { + return getBlockContainerFO().getKeepWithPrevious(); } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength( - getBlockContainerFO().getKeepWithPrevious()); + public KeepProperty getKeepWithNextProperty() { + return getBlockContainerFO().getKeepWithNext(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 49f96a365..4b21b4e11 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -207,21 +207,18 @@ public class BlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - KeepProperty keep = getBlockFO().getKeepTogether(); - int strength = KeepUtil.getCombinedBlockLevelKeepStrength(keep); - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; + public KeepProperty getKeepTogetherProperty() { + return getBlockFO().getKeepTogether(); } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithNext()); + public KeepProperty getKeepWithPreviousProperty() { + return getBlockFO().getKeepWithPrevious(); } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength(getBlockFO().getKeepWithPrevious()); + public KeepProperty getKeepWithNextProperty() { + return getBlockFO().getKeepWithNext(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java index 9163193a2..3d30abde0 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java @@ -19,6 +19,8 @@ package org.apache.fop.layoutmgr; +import org.apache.fop.fo.properties.KeepProperty; + /** * The interface for LayoutManagers which generate block areas */ @@ -35,11 +37,6 @@ public interface BlockLevelLayoutManager extends LayoutManager { /** Adjustment class: adjustment for line height */ int LINE_HEIGHT_ADJUSTMENT = 3; - /** The integer value for "auto" keep strength */ - int KEEP_AUTO = Integer.MIN_VALUE; - /** The integer value for "always" keep strength */ - int KEEP_ALWAYS = Integer.MAX_VALUE; - int negotiateBPDAdjustment(int adj, KnuthElement lastElement); void discardSpace(KnuthGlue spaceGlue); @@ -48,7 +45,7 @@ public interface BlockLevelLayoutManager extends LayoutManager { * Returns the keep-together strength for this element. * @return the keep-together strength */ - int getKeepTogetherStrength(); + Keep getKeepTogether(); /** * @return true if this element must be kept together @@ -59,7 +56,7 @@ public interface BlockLevelLayoutManager extends LayoutManager { * Returns the keep-with-previous strength for this element. * @return the keep-with-previous strength */ - int getKeepWithPreviousStrength(); + Keep getKeepWithPrevious(); /** * @return true if this element must be kept with the previous element. @@ -70,11 +67,28 @@ public interface BlockLevelLayoutManager extends LayoutManager { * Returns the keep-with-next strength for this element. * @return the keep-with-next strength */ - int getKeepWithNextStrength(); + Keep getKeepWithNext(); /** * @return true if this element must be kept with the next element. */ boolean mustKeepWithNext(); + /** + * Returns the keep-together property specified on the FObj. + * @return the keep-together property + */ + KeepProperty getKeepTogetherProperty(); + + /** + * Returns the keep-with-previous property specified on the FObj. + * @return the keep-together property + */ + KeepProperty getKeepWithPreviousProperty(); + + /** + * Returns the keep-with-next property specified on the FObj. + * @return the keep-together property + */ + KeepProperty getKeepWithNextProperty(); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index adda23def..3cd7b0994 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -31,9 +31,11 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockParent; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.properties.BreakPropertySet; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.SpaceProperty; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.layoutmgr.inline.InlineLayoutManager; import org.apache.fop.layoutmgr.inline.LineLayoutManager; import org.apache.fop.traits.MinOptMax; @@ -258,7 +260,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (!firstVisibleMarkServed) { addKnuthElementsForSpaceBefore(elements, alignment); - context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); + context.updateKeepWithPreviousPending(getKeepWithPrevious()); } addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed); @@ -349,7 +351,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager elements.add(forcedBreakAfterLast); } - context.updateKeepWithNextPending(getKeepWithNextStrength()); + context.updateKeepWithNextPending(getKeepWithNext()); setFinished(true); @@ -375,31 +377,31 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** * Adds a break element to the content list between individual child elements. - * @param contentList the content list to populate - * @param context the current layout context + * @param contentList + * @param parentLC * @param childLC the currently active child layout context */ - protected void addInBetweenBreak(List contentList, LayoutContext context, - LayoutContext childLC) { + protected void addInBetweenBreak(List contentList, LayoutContext parentLC, + LayoutContext childLC) { + if (mustKeepTogether() - || context.isKeepWithNextPending() + || parentLC.isKeepWithNextPending() || childLC.isKeepWithPreviousPending()) { - int strength = getKeepTogetherStrength(); + Keep keep = getKeepTogether(); //Handle pending keep-with-next - strength = Math.max(strength, context.getKeepWithNextPending()); - context.clearKeepWithNextPending(); + keep = keep.compare(parentLC.getKeepWithNextPending()); + parentLC.clearKeepWithNextPending(); //Handle pending keep-with-previous from child LM - strength = Math.max(strength, childLC.getKeepWithPreviousPending()); + keep = keep.compare(childLC.getKeepWithPreviousPending()); childLC.clearKeepWithPreviousPending(); - int penalty = KeepUtil.getPenaltyForKeep(strength); - // add a penalty to forbid or discourage a break between blocks contentList.add(new BreakElement( - new Position(this), penalty, context)); + new Position(this), keep.getPenalty(), + keep.getContext(), parentLC)); return; } @@ -430,7 +432,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // add a null penalty to allow a break between blocks contentList.add(new BreakElement( - new Position(this), 0, context)); + new Position(this), 0, Constants.EN_AUTO, parentLC)); } } @@ -766,33 +768,77 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * Retrieves and returns the keep-together strength from the parent element. * @return the keep-together strength */ - protected int getParentKeepTogetherStrength() { - int strength = KEEP_AUTO; + protected Keep getParentKeepTogether() { + Keep keep = Keep.KEEP_AUTO; if (getParent() instanceof BlockLevelLayoutManager) { - strength = ((BlockLevelLayoutManager)getParent()).getKeepTogetherStrength(); + keep = ((BlockLevelLayoutManager)getParent()).getKeepTogether(); } else if (getParent() instanceof InlineLayoutManager) { if (((InlineLayoutManager) getParent()).mustKeepTogether()) { - strength = KEEP_ALWAYS; + keep = Keep.KEEP_ALWAYS; } //TODO Fix me //strength = ((InlineLayoutManager) getParent()).getKeepTogetherStrength(); } - return strength; + return keep; } /** {@inheritDoc} */ public boolean mustKeepTogether() { - return getKeepTogetherStrength() > KEEP_AUTO; + return !getKeepTogether().isAuto(); } /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { - return getKeepWithPreviousStrength() > KEEP_AUTO; + return !getKeepWithPrevious().isAuto(); } /** {@inheritDoc} */ public boolean mustKeepWithNext() { - return getKeepWithNextStrength() > KEEP_AUTO; + return !getKeepWithNext().isAuto(); + } + + /** {@inheritDoc} */ + public Keep getKeepTogether() { + Keep keep = Keep.getKeep(getKeepTogetherProperty()); + keep = keep.compare(getParentKeepTogether()); + return keep; + } + + /** {@inheritDoc} */ + public Keep getKeepWithPrevious() { + return Keep.getKeep(getKeepWithPreviousProperty()); + } + + /** {@inheritDoc} */ + public Keep getKeepWithNext() { + return Keep.getKeep(getKeepWithNextProperty()); + } + + /** + * {@inheritDoc} + * Default implementation throws {@code IllegalStateException} + * Must be implemented by the subclass, if applicable. + */ + public KeepProperty getKeepTogetherProperty() { + throw new IllegalStateException(); + } + + /** + * {@inheritDoc} + * Default implementation throws {@code IllegalStateException} + * Must be implemented by the subclass, if applicable. + */ + public KeepProperty getKeepWithPreviousProperty() { + throw new IllegalStateException(); + } + + /** + * {@inheritDoc} + * Default implementation throws {@code IllegalStateException} + * Must be implemented by the subclass, if applicable. + */ + public KeepProperty getKeepWithNextProperty() { + throw new IllegalStateException(); } /** diff --git a/src/java/org/apache/fop/layoutmgr/BreakElement.java b/src/java/org/apache/fop/layoutmgr/BreakElement.java index 98e31dbf8..3eb96e9cd 100644 --- a/src/java/org/apache/fop/layoutmgr/BreakElement.java +++ b/src/java/org/apache/fop/layoutmgr/BreakElement.java @@ -41,7 +41,22 @@ public class BreakElement extends UnresolvedListElement { * @param context the layout context which contains the pending conditional elements */ public BreakElement(Position position, int penaltyValue, LayoutContext context) { - this(position, 0, penaltyValue, -1, context); + this(position, penaltyValue, -1, context); + } + + /** + * Create a new BreakElement for the given {@code position}, {@code penaltyValue} + * and {@code breakClass}. (Used principally to generate break-possibilities in + * ranges of content that must be kept together within the context corresponding + * to the {@code breakClass}; expected to be one of {@link Constants#EN_AUTO}, + * {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or {@link Constants#EN_PAGE}) + * @param position the corresponding {@link Position} + * @param penaltyValue the penalty value + * @param breakClass the break class + * @param context the {@link LayoutContext} + */ + public BreakElement(Position position, int penaltyValue, int breakClass, LayoutContext context) { + this(position, 0, penaltyValue, breakClass, context); } /** @@ -65,6 +80,10 @@ public class BreakElement extends UnresolvedListElement { this.pendingAfterMarks = context.getPendingAfterMarks(); } + private static String getBreakClassName(int breakClass) { + return AbstractBreaker.getBreakClassName(breakClass); + } + /** {@inheritDoc} */ public boolean isConditional() { return false; //Does not really apply here @@ -143,27 +162,17 @@ public class BreakElement extends UnresolvedListElement { /** {@inheritDoc} */ public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuffer sb = new StringBuffer(64); sb.append("BreakPossibility[p:"); - sb.append(this.penaltyValue); + sb.append(KnuthPenalty.valueOf(this.penaltyValue)); if (isForcedBreak()) { - sb.append(" (forced break"); - switch (getBreakClass()) { - case Constants.EN_PAGE: - sb.append(", page"); - break; - case Constants.EN_COLUMN: - sb.append(", column"); - break; - case Constants.EN_EVEN_PAGE: - sb.append(", even page"); - break; - case Constants.EN_ODD_PAGE: - sb.append(", odd page"); - break; - default: - } - sb.append(")"); + sb.append(" (forced break, ") + .append(getBreakClassName(this.breakClass)) + .append(")"); + } else if (this.penaltyValue >= 0 && this.breakClass != -1) { + sb.append(" (keep constraint, ") + .append(getBreakClassName(this.breakClass)) + .append(")"); } sb.append("; w:"); sb.append(penaltyWidth); diff --git a/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java index 35b8ceedb..bde969211 100644 --- a/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java @@ -611,6 +611,14 @@ public abstract class BreakingAlgorithm { } /** + * Return the last node that yielded a too short line. + * @return the node corresponding to the last too short line + */ + protected final KnuthNode getLastTooShort() { + return this.lastTooShort; + } + + /** * Generic handler for a {@link KnuthElement} at the given {@code position}, * taking into account whether the preceding element was a box, and which * type(s) of breaks are allowed. @@ -647,7 +655,7 @@ public abstract class BreakingAlgorithm { /** * Handle a {@link KnuthBox}. - * <em>Note: default implementation just adds the box's width + * <br/><em>Note: default implementation just adds the box's width * to the total content width. Subclasses that do not keep track * of this themselves, but override this method, should remember * to call {@code super.handleBox(box)} to avoid unwanted side-effects.</em> @@ -808,14 +816,16 @@ public abstract class BreakingAlgorithm { lastDeactivated = null; lastTooLong = null; for (int line = startLine; line < endLine; line++) { - if (!elementCanEndLine(element, line)) { - continue; - } for (KnuthNode node = getNode(line); node != null; node = node.next) { if (node.position == elementIdx) { continue; } int difference = computeDifference(node, element, elementIdx); + if (!elementCanEndLine(element, endLine, difference)) { + log.trace("Skipping legal break"); + break; + } + double r = computeAdjustmentRatio(node, difference); int availableShrink = totalShrink - node.totalShrink; int availableStretch = totalStretch - node.totalStretch; @@ -854,9 +864,10 @@ public abstract class BreakingAlgorithm { * number. * @param element the element * @param line the line number + * @param difference * @return {@code true} if the element can end the line */ - protected boolean elementCanEndLine(KnuthElement element, int line) { + protected boolean elementCanEndLine(KnuthElement element, int line, int difference) { return (!element.isPenalty() || element.getP() < KnuthElement.INFINITE); } diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 3b39909c5..6424475c3 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -181,18 +181,18 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - return KEEP_AUTO; + public Keep getKeepTogether() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KEEP_AUTO; + public Keep getKeepWithNext() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KEEP_AUTO; + public Keep getKeepWithPrevious() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java index 791008aec..affa75abb 100644 --- a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java @@ -92,18 +92,18 @@ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - return getParentKeepTogetherStrength(); + public Keep getKeepTogether() { + return getParentKeepTogether(); } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KEEP_AUTO; + public Keep getKeepWithNext() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KEEP_AUTO; + public Keep getKeepWithPrevious() { + return Keep.KEEP_AUTO; } } diff --git a/src/java/org/apache/fop/layoutmgr/Keep.java b/src/java/org/apache/fop/layoutmgr/Keep.java new file mode 100644 index 000000000..444448ae4 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/Keep.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file to You under the Apache + * License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.layoutmgr; + +import org.apache.fop.fo.Constants; +import org.apache.fop.fo.properties.KeepProperty; +import org.apache.fop.fo.properties.Property; + +/** + * Object representing a keep constraint, corresponding + * to the XSL-FO <a href="http://www.w3.org/TR/xsl/#d0e26492">keep properties</a>. + */ +public class Keep { + + /** The integer value for "auto" keep strength. */ + private static final int STRENGTH_AUTO = Integer.MIN_VALUE; + + /** The integer value for "always" keep strength. */ + private static final int STRENGTH_ALWAYS = Integer.MAX_VALUE; + + public static final Keep KEEP_AUTO = new Keep(STRENGTH_AUTO, Constants.EN_AUTO); + + public static final Keep KEEP_ALWAYS = new Keep(STRENGTH_ALWAYS, Constants.EN_LINE); + + private int strength; + + private int context; + + private Keep(int strength, int context) { + this.strength = strength; + this.context = context; + } + + private static int getKeepStrength(Property keep) { + if (keep.isAuto()) { + return STRENGTH_AUTO; + } else if (keep.getEnum() == Constants.EN_ALWAYS) { + return STRENGTH_ALWAYS; + } else { + return keep.getNumber().intValue(); + } + } + + /** + * Obtain a Keep instance corresponding to the given {@link KeepProperty} + * + * @param keepProperty the {@link KeepProperty} + * @return a new instance corresponding to the given property + */ + public static Keep getKeep(KeepProperty keepProperty) { + Keep keep = new Keep(STRENGTH_AUTO, Constants.EN_AUTO); + keep.update(keepProperty.getWithinPage(), Constants.EN_PAGE); + keep.update(keepProperty.getWithinColumn(), Constants.EN_COLUMN); + keep.update(keepProperty.getWithinLine(), Constants.EN_LINE); + return keep; + } + + private void update(Property keep, int context) { + if (!keep.isAuto()) { + this.strength = getKeepStrength(keep); + this.context = context; + } + } + + /** @return {@code true} if the keep property was specified as "auto" */ + public boolean isAuto() { + return strength == STRENGTH_AUTO; + } + + /** + * Returns the context of this keep. + * + * @return one of {@link Constants#EN_LINE}, {@link Constants#EN_COLUMN} or + * {@link Constants#EN_PAGE} + */ + public int getContext() { + return context; + } + + /** @return the penalty value corresponding to the strength of this Keep */ + public int getPenalty() { + if (strength == STRENGTH_AUTO) { + return 0; + } else if (strength == STRENGTH_ALWAYS) { + return KnuthElement.INFINITE; + } else { + return KnuthElement.INFINITE - 1; + } + } + + private static int getKeepContextPriority(int context) { + switch (context) { + case Constants.EN_LINE: return 0; + case Constants.EN_COLUMN: return 1; + case Constants.EN_PAGE: return 2; + case Constants.EN_AUTO: return 3; + default: throw new IllegalArgumentException(); + } + } + + /** + * Compare this Keep instance to another one, and return the + * stronger one if the context is the same + * + * @param other the instance to compare to + * @return the winning Keep instance + */ + public Keep compare(Keep other) { + + /* check strength "always" first, regardless of priority */ + if (this.strength == STRENGTH_ALWAYS + && this.strength > other.strength) { + return this; + } else if (other.strength == STRENGTH_ALWAYS + && other.strength > this.strength) { + return other; + } + + int pThis = getKeepContextPriority(this.context); + int pOther = getKeepContextPriority(other.context); + + /* equal priority: strongest wins */ + if (pThis == pOther) { + return (strength >= other.strength) ? this : other; + } + + /* different priority: lowest priority wins */ + return (pThis < pOther) ? this : other; + } + + /** {@inheritDoc} */ + public String toString() { + return (strength == STRENGTH_AUTO) ? "auto" + : (strength == STRENGTH_ALWAYS) ? "always" + : Integer.toString(strength); + } +} diff --git a/src/java/org/apache/fop/layoutmgr/KeepUtil.java b/src/java/org/apache/fop/layoutmgr/KeepUtil.java deleted file mode 100644 index 5cc33533f..000000000 --- a/src/java/org/apache/fop/layoutmgr/KeepUtil.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.layoutmgr; - -import org.apache.fop.fo.Constants; -import org.apache.fop.fo.properties.KeepProperty; -import org.apache.fop.fo.properties.Property; - -/** - * Utility class for working with keeps. - */ -public class KeepUtil { - - /** - * Converts a keep property into an integer value. - * <p> - * Note: The conversion restricts the effectively available integer range by two values. - * Integer.MIN_VALUE is used to represent the value "auto" and - * Integer.MAX_VALUE is used to represebt the value "always". - * @param keep the keep property - * @return the keep value as an integer - */ - public static int getKeepStrength(Property keep) { - if (keep.isAuto()) { - return BlockLevelLayoutManager.KEEP_AUTO; - } else if (keep.getEnum() == Constants.EN_ALWAYS) { - return BlockLevelLayoutManager.KEEP_ALWAYS; - } else { - return keep.getNumber().intValue(); - } - } - - /** - * Returns the combined block-level keep strength from a keep property. - * <p> - * Note: This is a temporary method to be used until it is possible to differentiate between - * page and column keeps! - * @param keep the keep property - * @return the combined keep strength - */ - public static int getCombinedBlockLevelKeepStrength(KeepProperty keep) { - return Math.max( - getKeepStrength(keep.getWithinPage()), - getKeepStrength(keep.getWithinColumn())); - } - - /** - * Indicates whether a keep strength indicates a keep constraint. - * @param strength the keep strength - * @return true if the keep is not "auto" - */ - public static boolean hasKeep(int strength) { - return strength > BlockLevelLayoutManager.KEEP_AUTO; - } - - /** - * Returns the penalty value to be used for a certain keep strength. - * <ul> - * <li>"auto": returns 0</li> - * <li>"always": returns KnuthElement.INFINITE</li> - * <li>otherwise: returns KnuthElement.INFINITE - 1</li> - * </ul> - * @param keepStrength the keep strength - * @return the penalty value - */ - public static int getPenaltyForKeep(int keepStrength) { - if (keepStrength == BlockLevelLayoutManager.KEEP_AUTO) { - return 0; - } - int penalty = KnuthElement.INFINITE; - if (keepStrength < BlockLevelLayoutManager.KEEP_ALWAYS) { - penalty--; - } - return penalty; - } - - /** - * Returns a string representation of a keep strength value. - * @param keepStrength the keep strength - * @return the string representation - */ - public static String keepStrengthToString(int keepStrength) { - if (keepStrength == BlockLevelLayoutManager.KEEP_AUTO) { - return "auto"; - } else if (keepStrength == BlockLevelLayoutManager.KEEP_ALWAYS) { - return "always"; - } else { - return Integer.toString(keepStrength); - } - } - -} diff --git a/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java b/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java index 6c13fba8a..5e44127df 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthPenalty.java @@ -45,7 +45,7 @@ public class KnuthPenalty extends KnuthElement { public static final int FLAGGED_PENALTY = 50; private int penalty; - private boolean bFlagged; + private boolean isFlagged; private int breakClass = -1; /** @@ -55,12 +55,12 @@ public class KnuthPenalty extends KnuthElement { * @param p the penalty value of this penalty * @param f is this penalty flagged? * @param pos the Position stored in this penalty - * @param bAux is this penalty auxiliary? + * @param isAuxiliary is this penalty auxiliary? */ - public KnuthPenalty(int w, int p, boolean f, Position pos, boolean bAux) { - super(w, pos, bAux); + public KnuthPenalty(int w, int p, boolean f, Position pos, boolean isAuxiliary) { + super(w, pos, isAuxiliary); penalty = p; - bFlagged = f; + isFlagged = f; } /** @@ -69,18 +69,37 @@ public class KnuthPenalty extends KnuthElement { * @param w the width of this penalty * @param p the penalty value of this penalty * @param f is this penalty flagged? - * @param iBreakClass the break class of this penalty (one of + * @param breakClass the break class of this penalty (one of * {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, {@link Constants#EN_PAGE}, * {@link Constants#EN_EVEN_PAGE}, {@link Constants#EN_ODD_PAGE}) * @param pos the Position stored in this penalty - * @param bAux is this penalty auxiliary? + * @param isAuxiliary is this penalty auxiliary? */ public KnuthPenalty(int w, int p, boolean f, - int iBreakClass, Position pos, boolean bAux) { - super(w, pos, bAux); - penalty = p; - bFlagged = f; - breakClass = iBreakClass; + int breakClass, Position pos, boolean isAuxiliary) { + this(w, p, f, pos, isAuxiliary); + this.breakClass = breakClass; + } + + private static String getBreakClassName(int breakClass) { + return AbstractBreaker.getBreakClassName(breakClass); + } + + /** + * Get the penalty's value as a {@code java.lang.String}. + * (Mainly used in {@code toString()} methods, to improve readability + * of the trace logs.) + * + * @param penaltyValue the penalty value + * @return the penalty value as a {@code java.lang.String} + */ + protected static String valueOf(int penaltyValue) { + String result = (penaltyValue < 0) ? "-" : ""; + int tmpValue = Math.abs(penaltyValue); + result += (tmpValue == KnuthElement.INFINITE) + ? "INFINITE" + : String.valueOf(tmpValue); + return result; } /** {@inheritDoc} */ @@ -105,7 +124,7 @@ public class KnuthPenalty extends KnuthElement { /** @return true is this penalty is a flagged one. */ public boolean isFlagged() { - return bFlagged; + return isFlagged; } /** {@inheritDoc} */ @@ -121,14 +140,6 @@ public class KnuthPenalty extends KnuthElement { return breakClass; } - /** - * Sets the break class for this penalty. - * @param cl the break class (EN_AUTO, EN_COLUMN, EN_PAGE, EN_EVEN_PAGE, EN_ODD_PAGE) - */ - public void setBreakClass(int cl) { - this.breakClass = cl; - } - /** {@inheritDoc} */ public String toString() { StringBuffer sb = new StringBuffer(64); @@ -137,39 +148,22 @@ public class KnuthPenalty extends KnuthElement { } sb.append("penalty"); sb.append(" p="); - if (getP() < 0) { - sb.append("-"); - } - if (Math.abs(getP()) == INFINITE) { - sb.append("INFINITE"); - } else { - sb.append(getP()); - } - if (isFlagged()) { + sb.append(valueOf(this.penalty)); + if (this.isFlagged) { sb.append(" [flagged]"); } sb.append(" w="); sb.append(getW()); if (isForcedBreak()) { - sb.append(" (forced break"); - switch (getBreakClass()) { - case Constants.EN_PAGE: - sb.append(", page"); - break; - case Constants.EN_COLUMN: - sb.append(", column"); - break; - case Constants.EN_EVEN_PAGE: - sb.append(", even page"); - break; - case Constants.EN_ODD_PAGE: - sb.append(", odd page"); - break; - default: - } - sb.append(")"); + sb.append(" (forced break, ") + .append(getBreakClassName(this.breakClass)) + .append(")"); + } else if (this.penalty >= 0 && this.breakClass != -1) { + //penalty corresponding to a keep constraint + sb.append(" (keep constraint, ") + .append(getBreakClassName(this.breakClass)) + .append(")"); } return sb.toString(); } - } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 8cf0cb5d3..81726e57b 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -136,8 +136,8 @@ public class LayoutContext { private int breakBefore; private int breakAfter; - private int pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO; - private int pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; + private Keep pendingKeepWithNext = Keep.KEEP_AUTO; + private Keep pendingKeepWithPrevious = Keep.KEEP_AUTO; private int disableColumnBalancing; @@ -227,7 +227,7 @@ public class LayoutContext { * Returns the strength of a keep-with-next currently pending. * @return the keep-with-next strength */ - public int getKeepWithNextPending() { + public Keep getKeepWithNextPending() { return this.pendingKeepWithNext; } @@ -235,7 +235,7 @@ public class LayoutContext { * Returns the strength of a keep-with-previous currently pending. * @return the keep-with-previous strength */ - public int getKeepWithPreviousPending() { + public Keep getKeepWithPreviousPending() { return this.pendingKeepWithPrevious; } @@ -243,14 +243,14 @@ public class LayoutContext { * Clears any pending keep-with-next strength. */ public void clearKeepWithNextPending() { - this.pendingKeepWithNext = BlockLevelLayoutManager.KEEP_AUTO; + this.pendingKeepWithNext = Keep.KEEP_AUTO; } /** * Clears any pending keep-with-previous strength. */ public void clearKeepWithPreviousPending() { - this.pendingKeepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; + this.pendingKeepWithPrevious = Keep.KEEP_AUTO; } /** @@ -263,18 +263,18 @@ public class LayoutContext { /** * Updates the currently pending keep-with-next strength. - * @param strength the new strength to consider + * @param keep the new strength to consider */ - public void updateKeepWithNextPending(int strength) { - this.pendingKeepWithNext = Math.max(this.pendingKeepWithNext, strength); + public void updateKeepWithNextPending(Keep keep) { + this.pendingKeepWithNext = this.pendingKeepWithNext.compare(keep); } /** * Updates the currently pending keep-with-previous strength. - * @param strength the new strength to consider + * @param keep the new strength to consider */ - public void updateKeepWithPreviousPending(int strength) { - this.pendingKeepWithPrevious = Math.max(this.pendingKeepWithPrevious, strength); + public void updateKeepWithPreviousPending(Keep keep) { + this.pendingKeepWithPrevious = this.pendingKeepWithPrevious.compare(keep); } /** @@ -282,7 +282,7 @@ public class LayoutContext { * @return true if a keep-with-next constraint is pending */ public boolean isKeepWithNextPending() { - return getKeepWithNextPending() != BlockLevelLayoutManager.KEEP_AUTO; + return !getKeepWithNextPending().isAuto(); } /** @@ -290,7 +290,7 @@ public class LayoutContext { * @return true if a keep-with-previous constraint is pending */ public boolean isKeepWithPreviousPending() { - return getKeepWithPreviousPending() != BlockLevelLayoutManager.KEEP_AUTO; + return !getKeepWithPreviousPending().isAuto(); } public void setLeadingSpace(SpaceSpecifier space) { @@ -640,9 +640,8 @@ public class LayoutContext { + "\nStarts New Area: \t" + startsNewArea() + "\nIs Last Area: \t" + isLastArea() + "\nTry Hyphenate: \t" + tryHyphenate() - + "\nKeeps: \t[keep-with-next=" + KeepUtil.keepStrengthToString(getKeepWithNextPending()) - + "][keep-with-previous=" - + KeepUtil.keepStrengthToString(getKeepWithPreviousPending()) + "] pending" + + "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending() + + "][keep-with-previous=" + getKeepWithPreviousPending() + "] pending" + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]"; } diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index 70e1b2d8f..84afdcea9 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -451,9 +451,7 @@ public class PageBreaker extends AbstractBreaker { pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished(); } - /** - * @return the current child flow layout manager - */ + /** @return the current child flow layout manager */ protected LayoutManager getCurrentChildLM() { return childFLM; } @@ -472,44 +470,51 @@ public class PageBreaker extends AbstractBreaker { */ private void handleBreakTrait(int breakVal) { Page curPage = pslm.getCurrentPage(); - if (breakVal == Constants.EN_ALL) { + switch (breakVal) { + case Constants.EN_ALL: //break due to span change in multi-column layout curPage.getPageViewport().createSpan(true); return; - } else if (breakVal == Constants.EN_NONE) { + case Constants.EN_NONE: curPage.getPageViewport().createSpan(false); return; - } else if (breakVal == Constants.EN_COLUMN - || breakVal <= 0 - || breakVal == Constants.EN_AUTO) { + case Constants.EN_COLUMN: + case Constants.EN_AUTO: + case Constants.EN_PAGE: + case -1: PageViewport pv = curPage.getPageViewport(); //Check if previous page was spanned boolean forceNewPageWithSpan = false; RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion( Constants.FO_REGION_BODY); - if (rb.getColumnCount() > 1 - && pv.getCurrentSpan().getColumnCount() == 1) { - forceNewPageWithSpan = true; - } + forceNewPageWithSpan + = (rb.getColumnCount() > 1 + && pv.getCurrentSpan().getColumnCount() == 1); if (forceNewPageWithSpan) { + log.trace("Forcing new page with span"); curPage = pslm.makeNewPage(false, false); curPage.getPageViewport().createSpan(true); } else if (pv.getCurrentSpan().hasMoreFlows()) { + log.trace("Moving to next flow"); pv.getCurrentSpan().moveToNextFlow(); } else { - curPage = pslm.makeNewPage(false, false); + log.trace("Making new page"); + /*curPage = */pslm.makeNewPage(false, false); } return; - } - log.debug("handling break-before after page " + pslm.getCurrentPageNum() - + " breakVal=" + getBreakClassName(breakVal)); - if (needBlankPageBeforeNew(breakVal)) { - curPage = pslm.makeNewPage(true, false); - } - if (needNewPage(breakVal)) { - curPage = pslm.makeNewPage(false, false); + default: + log.debug("handling break-before after page " + pslm.getCurrentPageNum() + + " breakVal=" + getBreakClassName(breakVal)); + if (needBlankPageBeforeNew(breakVal)) { + log.trace("Inserting blank page"); + /*curPage = */pslm.makeNewPage(true, false); + } + if (needNewPage(breakVal)) { + log.trace("Making new page"); + /*curPage = */pslm.makeNewPage(false, false); + } } } diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index 3fa2e1f91..bbb743048 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -96,6 +96,11 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { //Controls whether a single part should be forced if possible (ex. block-container) private boolean favorSinglePart = false; + //Used to keep track of switches in keep-context + private int currentKeepContext = Constants.EN_AUTO; + private KnuthNode lastBeforeKeepContextSwitch; + + public PageBreakingAlgorithm(LayoutManager topLevelLM, PageProvider pageProvider, PageBreakingLayoutListener layoutListener, @@ -190,6 +195,72 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { footnoteElementIndex = -1; } + /** + * {@inheritDoc} + * Overridden to defer a part to the next page, if it + * must be kept within one page, but is too large to fit in + * the last column. + */ + protected KnuthNode recoverFromTooLong(KnuthNode lastTooLong) { + + if (log.isDebugEnabled()) { + log.debug("Recovering from too long: " + lastTooLong); + log.debug("\tlastTooShort = " + getLastTooShort()); + log.debug("\tlastBeforeKeepContextSwitch = " + lastBeforeKeepContextSwitch); + log.debug("\tcurrentKeepContext = " + AbstractBreaker.getBreakClassName(currentKeepContext)); + } + + if (lastBeforeKeepContextSwitch == null + || currentKeepContext == Constants.EN_AUTO) { + return super.recoverFromTooLong(lastTooLong); + } + + KnuthNode node = lastBeforeKeepContextSwitch; + lastBeforeKeepContextSwitch = null; + // content would overflow, insert empty page/column(s) and try again + while (!pageProvider.endPage(node.line - 1)) { + log.trace("Adding node for empty column"); + node = createNode( + node.position, + node.line + 1, 1, + 0, 0, 0, + 0, 0, 0, + 0, 0, node); + } + return node; + } + + /** + * Compare two KnuthNodes and return the node with the least demerit. + * + * @param node1 The first knuth node. + * @param node2 The other knuth node. + * @return the node with the least demerit. + */ + protected KnuthNode compareNodes(KnuthNode node1, KnuthNode node2) { + + /* if either node is null, return the other one */ + if (node1 == null || node2 == null) { + return (node1 == null) ? node2 : node1; + } + + /* if either one of the nodes corresponds to a mere column-break, + * and the other one corresponds to a page-break, return the page-break node + */ + if (pageProvider != null) { + if (pageProvider.endPage(node1.line - 1) + && !pageProvider.endPage(node2.line - 1)) { + return node1; + } else if (pageProvider.endPage(node2.line - 1) + && !pageProvider.endPage(node1.line - 1)) { + return node2; + } + } + + /* all other cases: use superclass implementation */ + return super.compareNodes(node1, node2); + } + /** {@inheritDoc} */ protected KnuthNode createNode(int position, int line, int fitness, int totalWidth, int totalStretch, int totalShrink, @@ -234,6 +305,28 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { } /** + * {@inheritDoc} + * Overridden to consider penalties with value {@link KnuthElement#INFINITE} + * as legal break-points, if the current keep-context allows this + * (a keep-*.within-page="always" constraint still permits column-breaks) + */ + protected void handlePenaltyAt(KnuthPenalty penalty, int position, + int allowedBreaks) { + super.handlePenaltyAt(penalty, position, allowedBreaks); + /* if the penalty had value INFINITE, default implementation + * will not have considered it a legal break, but it could still + * be one. + */ + if (penalty.getP() == KnuthPenalty.INFINITE) { + int breakClass = penalty.getBreakClass(); + if (breakClass == Constants.EN_PAGE + || breakClass == Constants.EN_COLUMN) { + considerLegalBreak(penalty, position); + } + } + } + + /** * Handles the footnotes cited inside a block-level box. Updates footnotesList and the * value of totalFootnotesLength with the lengths of the given footnotes. * @param elementLists list of KnuthElement sequences corresponding to the footnotes @@ -317,10 +410,66 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { /** {@inheritDoc} */ protected void considerLegalBreak(KnuthElement element, int elementIdx) { + if (element.isPenalty()) { + int breakClass = ((KnuthPenalty) element).getBreakClass(); + switch (breakClass) { + case Constants.EN_PAGE: + if (this.currentKeepContext != breakClass) { + this.lastBeforeKeepContextSwitch = getLastTooShort(); + } + this.currentKeepContext = breakClass; + break; + case Constants.EN_COLUMN: + if (this.currentKeepContext != breakClass) { + this.lastBeforeKeepContextSwitch = getLastTooShort(); + } + this.currentKeepContext = breakClass; + break; + case Constants.EN_AUTO: + this.currentKeepContext = breakClass; + break; + default: + //nop + } + } super.considerLegalBreak(element, elementIdx); newFootnotes = false; } + /** {@inheritDoc} */ + protected boolean elementCanEndLine(KnuthElement element, int line, int difference) { + if (!(element.isPenalty()) || pageProvider == null) { + return true; + } else { + KnuthPenalty p = (KnuthPenalty) element; + if (p.getP() <= 0) { + return true; + } else { + int context = p.getBreakClass(); + switch (context) { + case Constants.EN_LINE: + case Constants.EN_COLUMN: + return p.getP() < KnuthPenalty.INFINITE; + case Constants.EN_PAGE: + return p.getP() < KnuthPenalty.INFINITE + || !pageProvider.endPage(line - 1); + //|| (deferPart && difference < 0); + case Constants.EN_AUTO: + log.warn("keep is not auto but context is"); + return true; + default: + if (p.getP() < KnuthPenalty.INFINITE) { + log.warn("Non recognized keep context:" + context); + return true; + } else { + return false; + } + } + } + } + } + + /** {@inheritDoc} */ protected int computeDifference(KnuthNode activeNode, KnuthElement element, int elementIndex) { KnuthPageNode pageNode = (KnuthPageNode) activeNode; diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java index 9073c48bb..c03aea091 100644 --- a/src/java/org/apache/fop/layoutmgr/PageProvider.java +++ b/src/java/org/apache/fop/layoutmgr/PageProvider.java @@ -146,6 +146,49 @@ public class PageProvider implements Constants { return this.lastReportedBPD; } + // Wish there were a more elegant way to do this in Java + private int[] getColIndexAndColCount(int index) { + int columnCount = 0; + int colIndex = startColumnOfCurrentElementList + index; + int pageIndex = -1; + do { + colIndex -= columnCount; + pageIndex++; + Page page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST); + columnCount = page.getPageViewport().getCurrentSpan().getColumnCount(); + } while (colIndex >= columnCount); + return new int[] {colIndex, columnCount}; + } + + /** + * Checks if a break at the passed index would start a new page + * @param index the index of the element before the break + * @return {@code true} if the break starts a new page + */ + boolean startPage(int index) { + return getColIndexAndColCount(index)[0] == 0; + } + + /** + * Checks if a break at the passed index would end a page + * @param index the index of the element before the break + * @return {@code true} if the break ends a page + */ + boolean endPage(int index) { + int[] colIndexAndColCount = getColIndexAndColCount(index); + return colIndexAndColCount[0] == colIndexAndColCount[1] - 1; + } + + /** + * Obtain the applicable column-count for the element at the + * passed index + * @param index the index of the element + * @return the number of columns + */ + int getColumnCount(int index) { + return getColIndexAndColCount(index)[1]; + } + /** * Returns the part index (0<x<partCount) which denotes the first part on the last page * generated by the current element list. @@ -272,4 +315,4 @@ public class PageProvider implements Constants { return page; } -}
\ No newline at end of file +} diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index 0054b9849..d5949f4a2 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -314,18 +314,18 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - return KEEP_AUTO; + public Keep getKeepTogether() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KEEP_AUTO; + public Keep getKeepWithNext() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KEEP_AUTO; + public Keep getKeepWithPrevious() { + return Keep.KEEP_AUTO; } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index c28cc470e..95bc9ab2d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -36,6 +36,7 @@ import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.Block; import org.apache.fop.fo.properties.CommonHyphenation; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; @@ -46,7 +47,7 @@ import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.BreakingAlgorithm; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.InlineKnuthSequence; -import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -876,12 +877,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager for (int p = 0; p < knuthParagraphs.size(); p++) { // penalty between paragraphs if (p > 0) { - int strength = getKeepTogetherStrength(); - int penalty = KeepUtil.getPenaltyForKeep(strength); - if (penalty < KnuthElement.INFINITE) { - returnList.add(new BreakElement( - new Position(this), penalty, context)); - } + Keep keep = getKeepTogether(); + returnList.add(new BreakElement( + new Position(this), + keep.getPenalty(), + keep.getContext(), + context)); } LineLayoutPossibilities llPoss; @@ -920,12 +921,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager && i >= fobj.getOrphans() && i <= llPoss.getChosenLineCount() - fobj.getWidows()) { // penalty allowing a page break between lines - int strength = getKeepTogetherStrength(); - int penalty = KeepUtil.getPenaltyForKeep(strength); - if (penalty < KnuthElement.INFINITE) { - returnList.add(new BreakElement( - returnPosition, penalty, context)); - } + Keep keep = getKeepTogether(); + returnList.add(new BreakElement( + new Position(this), + keep.getPenalty(), + keep.getContext(), + context)); } int endIndex = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos(); @@ -1104,28 +1105,43 @@ public class LineLayoutManager extends InlineStackingLayoutManager } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - return ((BlockLevelLayoutManager) getParent()).getKeepTogetherStrength(); + public KeepProperty getKeepTogetherProperty() { + return ((BlockLevelLayoutManager) getParent()).getKeepTogetherProperty(); + } + + /** {@inheritDoc} */ + public KeepProperty getKeepWithPreviousProperty() { + return ((BlockLevelLayoutManager) getParent()).getKeepWithPreviousProperty(); + } + + /** {@inheritDoc} */ + public KeepProperty getKeepWithNextProperty() { + return ((BlockLevelLayoutManager) getParent()).getKeepWithNextProperty(); + } + + /** {@inheritDoc} */ + public Keep getKeepTogether() { + return ((BlockLevelLayoutManager) getParent()).getKeepTogether(); } /** {@inheritDoc} */ public boolean mustKeepWithPrevious() { - return getKeepWithPreviousStrength() > KEEP_AUTO; + return !getKeepWithPrevious().isAuto(); } /** {@inheritDoc} */ public boolean mustKeepWithNext() { - return getKeepWithNextStrength() > KEEP_AUTO; + return !getKeepWithNext().isAuto(); } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KEEP_AUTO; + public Keep getKeepWithNext() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KEEP_AUTO; + public Keep getKeepWithPrevious() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ @@ -1230,6 +1246,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager break; } //TODO Something's not right here. See block_hyphenation_linefeed_preserve.xml + //for more info: see also https://issues.apache.org/bugzilla/show_bug.cgi?id=38264 // collect word fragments, ignoring auxiliary elements; // each word fragment was created by a different TextLM diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index 1cd3ab9d2..a9f2eeb27 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -29,10 +29,10 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListBlock; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListUtils; -import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; @@ -279,21 +279,18 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - int strength = KeepUtil.getCombinedBlockLevelKeepStrength( - getListBlockFO().getKeepTogether()); - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; + public KeepProperty getKeepTogetherProperty() { + return getListBlockFO().getKeepTogether(); } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithNext()); + public KeepProperty getKeepWithPreviousProperty() { + return getListBlockFO().getKeepWithPrevious(); } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength(getListBlockFO().getKeepWithPrevious()); + public KeepProperty getKeepWithNextProperty() { + return getListBlockFO().getKeepWithNext(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 0a2dec945..7fd2219ea 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -28,8 +28,9 @@ import org.apache.fop.area.Block; import org.apache.fop.fo.flow.AbstractListItemPart; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; -import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; @@ -221,20 +222,18 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getPartFO().getKeepTogether()); - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; + public KeepProperty getKeepTogetherProperty() { + return getPartFO().getKeepTogether(); } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KEEP_AUTO; + public Keep getKeepWithNext() { + return Keep.KEEP_AUTO; } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KEEP_AUTO; + public Keep getKeepWithPrevious() { + return Keep.KEEP_AUTO; } } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index a4e8982f7..7000a8748 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -32,13 +32,13 @@ import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListItem; import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.ElementListUtils; -import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -83,8 +83,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager private MinOptMax effSpaceBefore; private MinOptMax effSpaceAfter; - private int keepWithNextPendingOnLabel; - private int keepWithNextPendingOnBody; + private Keep keepWithNextPendingOnLabel; + private Keep keepWithNextPendingOnBody; private int listItemHeight; @@ -254,8 +254,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager context.updateKeepWithNextPending(this.keepWithNextPendingOnLabel); context.updateKeepWithNextPending(this.keepWithNextPendingOnBody); - context.updateKeepWithNextPending(getKeepWithNextStrength()); - context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); + context.updateKeepWithNextPending(getKeepWithNext()); + context.updateKeepWithPreviousPending(getKeepWithPrevious()); setFinished(true); resetSpaces(); @@ -276,16 +276,16 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int totalHeight = Math.max(fullHeights[0], fullHeights[1]); int step; int addedBoxHeight = 0; - int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO; + Keep keepWithNextActive = Keep.KEEP_AUTO; LinkedList returnList = new LinkedList(); while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { if (end[0] + 1 == elementLists[0].size()) { - keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel); + keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnLabel); } if (end[1] + 1 == elementLists[1].size()) { - keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnBody); + keepWithNextActive = keepWithNextActive.compare(keepWithNextPendingOnBody); } // compute penalty height and box height @@ -339,14 +339,13 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } if (addedBoxHeight < totalHeight) { - int strength = BlockLevelLayoutManager.KEEP_AUTO; - strength = Math.max(strength, keepWithNextActive); - strength = Math.max(strength, getKeepTogetherStrength()); + Keep keep = keepWithNextActive.compare(getKeepTogether()); int p = stepPenalty; if (p > -KnuthElement.INFINITE) { - p = Math.max(p, KeepUtil.getPenaltyForKeep(strength)); + p = Math.max(p, keep.getPenalty()); } - returnList.add(new BreakElement(stepPosition, penaltyHeight, p, -1, context)); + returnList.add(new BreakElement(stepPosition, penaltyHeight, p, keep.getContext(), + context)); } } @@ -644,21 +643,18 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - int strength = KeepUtil.getCombinedBlockLevelKeepStrength( - getListItemFO().getKeepTogether()); - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; + public KeepProperty getKeepTogetherProperty() { + return getListItemFO().getKeepTogether(); } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithNext()); + public KeepProperty getKeepWithPreviousProperty() { + return getListItemFO().getKeepWithPrevious(); } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength(getListItemFO().getKeepWithPrevious()); + public KeepProperty getKeepWithNextProperty() { + return getListItemFO().getKeepWithNext(); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index 30177f988..53e798e3c 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -32,8 +32,8 @@ import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.ElementListUtils; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; @@ -75,7 +75,7 @@ class ActiveCell { /** True if the next CellPart that will be created will be the last one for this cell. */ private boolean lastCellPart; - private int keepWithNextStrength; + private Keep keepWithNext; private int spanIndex = 0; @@ -218,7 +218,7 @@ class ActiveCell { includedLength = -1; // Avoid troubles with cells having content of zero length totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList); endRowIndex = rowIndex + pgu.getCell().getNumberRowsSpanned() - 1; - keepWithNextStrength = BlockLevelLayoutManager.KEEP_AUTO; + keepWithNext = Keep.KEEP_AUTO; remainingLength = totalLength - previousRowsLength; afterNextStep = new Step(previousRowsLength); @@ -314,7 +314,11 @@ class ActiveCell { KnuthElement el = (KnuthElement) knuthIter.next(); if (el.isPenalty()) { prevIsBox = false; - if (el.getP() < KnuthElement.INFINITE) { + if (el.getP() < KnuthElement.INFINITE + || ((KnuthPenalty) el).getBreakClass() == Constants.EN_PAGE) { + // TODO too much is being done in that test, only to handle + // keep.within-column properly. + // First legal break point breakFound = true; KnuthPenalty p = (KnuthPenalty) el; @@ -533,7 +537,7 @@ class ActiveCell { */ CellPart createCellPart() { if (nextStep.end + 1 == elementList.size()) { - keepWithNextStrength = pgu.getKeepWithNextStrength(); + keepWithNext = pgu.getKeepWithNext(); // TODO if keep-with-next is set on the row, must every cell of the row // contribute some content from children blocks? // see http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-dev/200802.mbox/ @@ -576,8 +580,8 @@ class ActiveCell { } } - int getKeepWithNextStrength() { - return keepWithNextStrength; + Keep getKeepWithNext() { + return keepWithNext; } int getPenaltyValue() { diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 54cb1ebfe..83e71bb21 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -60,8 +60,8 @@ class RowGroupLayoutManager { LinkedList returnList = new LinkedList(); createElementsForRowGroup(context, alignment, bodyType, returnList); - context.updateKeepWithPreviousPending(rowGroup[0].getKeepWithPreviousStrength()); - context.updateKeepWithNextPending(rowGroup[rowGroup.length - 1].getKeepWithNextStrength()); + context.updateKeepWithPreviousPending(rowGroup[0].getKeepWithPrevious()); + context.updateKeepWithNextPending(rowGroup[rowGroup.length - 1].getKeepWithNext()); int breakBefore = Constants.EN_AUTO; TableRow firstRow = rowGroup[0].getTableRow(); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index 4cf68b97b..edf73acab 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -23,6 +23,7 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.fo.flow.table.TableAndCaption; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; @@ -201,19 +202,8 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; - /* TODO Complete me! - int strength = KeepUtil.getCombinedBlockLevelKeepStrength( - getTableAndCaptionFO().getKeepTogether()); - */ - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; - } - - /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KEEP_AUTO; + public Keep getKeepWithNext() { + return Keep.KEEP_AUTO; /* TODO Complete me! return KeepUtil.getCombinedBlockLevelKeepStrength( getTableAndCaptionFO().getKeepWithNext()); @@ -221,12 +211,12 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KEEP_AUTO; + public Keep getKeepWithPrevious() { + return Keep.KEEP_AUTO; /* TODO Complete me! return KeepUtil.getCombinedBlockLevelKeepStrength( getTableAndCaptionFO().getKeepWithPrevious()); */ } -}
\ No newline at end of file +} diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 071082624..9d9255e0c 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -23,6 +23,7 @@ import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.fo.flow.table.TableCaption; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; @@ -197,21 +198,8 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; - /* TODO Complete me! - strength = Math.max(strength, KeepUtil.getKeepStrength( - getTableCaptionFO().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - getTableCaptionFO().getKeepTogether().getWithinColumn())); - */ - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; - } - - /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KEEP_AUTO; + public Keep getKeepWithNext() { + return Keep.KEEP_AUTO; /* TODO Complete me! return KeepUtil.getCombinedBlockLevelKeepStrength( getTableCaptionFO().getKeepWithNext()); @@ -219,8 +207,8 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KEEP_AUTO; + public Keep getKeepWithPrevious() { + return Keep.KEEP_AUTO; /* TODO Complete me! return KeepUtil.getCombinedBlockLevelKeepStrength( getTableCaptionFO().getKeepWithPrevious()); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index 239a1a88e..4e3c0b102 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.Trait; @@ -31,21 +32,23 @@ import org.apache.fop.fo.flow.table.ConditionalBorder; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.flow.table.Table; -import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableCell; import org.apache.fop.fo.flow.table.TableColumn; +import org.apache.fop.fo.flow.table.TablePart; import org.apache.fop.fo.flow.table.TableRow; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.layoutmgr.AreaAdditionUtil; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; -import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.ElementListUtils; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.LayoutContext; +import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.SpaceResolver; @@ -138,9 +141,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager List contentList = new LinkedList(); List returnList = new LinkedList(); - BlockLevelLayoutManager curLM; // currently active LM - BlockLevelLayoutManager prevLM = null; // previously active LM - while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { + LayoutManager curLM; // currently active LM + LayoutManager prevLM = null; // previously active LM + while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); // curLM is a ? childLC.setStackLimitBP(MinOptMax.subtract(context @@ -153,11 +156,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager log.debug("child LM signals pending keep with next"); } if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { - primaryGridUnit.setKeepWithPreviousStrength(childLC.getKeepWithPreviousPending()); + primaryGridUnit.setKeepWithPrevious(childLC.getKeepWithPreviousPending()); childLC.clearKeepWithPreviousPending(); } - if (prevLM != null) { + if (prevLM != null + && !ElementListUtils.endsWithForcedBreak(contentList)) { // there is a block handled by prevLM // before the one handled by curLM addInBetweenBreak(contentList, context, childLC); @@ -174,7 +178,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } prevLM = curLM; } - primaryGridUnit.setKeepWithNextStrength(context.getKeepWithNextPending()); + primaryGridUnit.setKeepWithNext(context.getKeepWithNextPending()); returnedList = new LinkedList(); if (!contentList.isEmpty()) { @@ -195,7 +199,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } final KnuthElement lastItem = (KnuthElement) ListUtil .getLast(returnList); - if (((KnuthElement) lastItem).isForcedBreak()) { + if (lastItem.isForcedBreak()) { KnuthPenalty p = (KnuthPenalty) lastItem; primaryGridUnit.setBreakAfter(p.getBreakClass()); p.setP(0); @@ -556,26 +560,23 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - int strength = KEEP_AUTO; + public Keep getKeepTogether() { + Keep keep = Keep.KEEP_AUTO; if (primaryGridUnit.getRow() != null) { - strength = Math.max(strength, KeepUtil.getKeepStrength( - primaryGridUnit.getRow().getKeepTogether().getWithinPage())); - strength = Math.max(strength, KeepUtil.getKeepStrength( - primaryGridUnit.getRow().getKeepTogether().getWithinColumn())); + keep = Keep.getKeep(primaryGridUnit.getRow().getKeepTogether()); } - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; + keep = keep.compare(getParentKeepTogether()); + return keep; } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-next!) + public Keep getKeepWithNext() { + return Keep.KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-next!) } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!) + public Keep getKeepWithPrevious() { + return Keep.KEEP_AUTO; //TODO FIX ME (table-cell has no keep-with-previous!) } // --------- Property Resolution related functions --------- // diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index 2ff97a6a7..40ebf9e0d 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -35,10 +35,9 @@ import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.PrimaryGridUnit; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TablePart; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ElementListUtils; -import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; @@ -213,13 +212,13 @@ public class TableContentLayoutManager implements PercentBaseContext { context.clearKeepsPending(); context.setBreakBefore(Constants.EN_AUTO); context.setBreakAfter(Constants.EN_AUTO); - int keepWithPrevious = BlockLevelLayoutManager.KEEP_AUTO; + Keep keepWithPrevious = Keep.KEEP_AUTO; int breakBefore = Constants.EN_AUTO; if (rowGroup != null) { RowGroupLayoutManager rowGroupLM = new RowGroupLayoutManager(getTableLM(), rowGroup, stepper); List nextRowGroupElems = rowGroupLM.getNextKnuthElements(context, alignment, bodyType); - keepWithPrevious = Math.max(keepWithPrevious, context.getKeepWithPreviousPending()); + keepWithPrevious = keepWithPrevious.compare(context.getKeepWithPreviousPending()); breakBefore = context.getBreakBefore(); int breakBetween = context.getBreakAfter(); returnList.addAll(nextRowGroupElems); @@ -228,7 +227,7 @@ public class TableContentLayoutManager implements PercentBaseContext { //Note previous pending keep-with-next and clear the strength //(as the layout context is reused) - int keepWithNextPending = context.getKeepWithNextPending(); + Keep keepWithNextPending = context.getKeepWithNextPending(); context.clearKeepWithNextPending(); //Get elements for next row group @@ -246,17 +245,17 @@ public class TableContentLayoutManager implements PercentBaseContext { */ //Determine keep constraints - int penaltyStrength = BlockLevelLayoutManager.KEEP_AUTO; - penaltyStrength = Math.max(penaltyStrength, keepWithNextPending); - penaltyStrength = Math.max(penaltyStrength, context.getKeepWithPreviousPending()); + Keep keep = keepWithNextPending.compare(context.getKeepWithPreviousPending()); context.clearKeepWithPreviousPending(); - penaltyStrength = Math.max(penaltyStrength, getTableLM().getKeepTogetherStrength()); - int penaltyValue = KeepUtil.getPenaltyForKeep(penaltyStrength); + keep = keep.compare(getTableLM().getKeepTogether()); + int penaltyValue = keep.getPenalty(); + int breakClass = keep.getContext(); breakBetween = BreakUtil.compareBreakClasses(breakBetween, context.getBreakBefore()); if (breakBetween != Constants.EN_AUTO) { penaltyValue = -KnuthElement.INFINITE; + breakClass = breakBetween; } BreakElement breakElement; ListIterator elemIter = returnList.listIterator(returnList.size()); @@ -267,7 +266,7 @@ public class TableContentLayoutManager implements PercentBaseContext { breakElement = (BreakElement) elem; } breakElement.setPenaltyValue(penaltyValue); - breakElement.setBreakClass(breakBetween); + breakElement.setBreakClass(breakClass); returnList.addAll(nextRowGroupElems); breakBetween = context.getBreakAfter(); } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index dc2b3cc46..9ccca8b9e 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -35,11 +35,11 @@ import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; import org.apache.fop.fo.flow.table.Table; import org.apache.fop.fo.flow.table.TableColumn; +import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.layoutmgr.BlockLevelEventProducer; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.ConditionalElementListener; -import org.apache.fop.layoutmgr.KeepUtil; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.LayoutContext; @@ -256,10 +256,10 @@ public class TableLayoutManager extends BlockStackingLayoutManager log.debug(contentKnuthElements); wrapPositionElements(contentKnuthElements, returnList); - context.updateKeepWithPreviousPending(getKeepWithPreviousStrength()); + context.updateKeepWithPreviousPending(getKeepWithPrevious()); context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); - context.updateKeepWithNextPending(getKeepWithNextStrength()); + context.updateKeepWithNextPending(getKeepWithNext()); context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); if (getTable().isSeparateBorderModel()) { @@ -448,20 +448,18 @@ public class TableLayoutManager extends BlockStackingLayoutManager } /** {@inheritDoc} */ - public int getKeepTogetherStrength() { - int strength = KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepTogether()); - strength = Math.max(strength, getParentKeepTogetherStrength()); - return strength; + public KeepProperty getKeepTogetherProperty() { + return getTable().getKeepTogether(); } /** {@inheritDoc} */ - public int getKeepWithNextStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithNext()); + public KeepProperty getKeepWithPreviousProperty() { + return getTable().getKeepWithPrevious(); } /** {@inheritDoc} */ - public int getKeepWithPreviousStrength() { - return KeepUtil.getCombinedBlockLevelKeepStrength(getTable().getKeepWithPrevious()); + public KeepProperty getKeepWithNextProperty() { + return getTable().getKeepWithNext(); } // --------- Property Resolution related functions --------- // diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index a3fba279e..92a641ed0 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -30,12 +30,10 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.table.EffRow; import org.apache.fop.fo.flow.table.GridUnit; import org.apache.fop.fo.flow.table.PrimaryGridUnit; -import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; -import org.apache.fop.layoutmgr.KeepUtil; +import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; -import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthGlue; import org.apache.fop.layoutmgr.KnuthPenalty; import org.apache.fop.layoutmgr.LayoutContext; @@ -241,40 +239,38 @@ public class TableStepper { } } - int strength = BlockLevelLayoutManager.KEEP_AUTO; + Keep keep = Keep.KEEP_AUTO; int stepPenalty = 0; for (Iterator iter = activeCells.iterator(); iter.hasNext();) { ActiveCell activeCell = (ActiveCell) iter.next(); - strength = Math.max(strength, activeCell.getKeepWithNextStrength()); + keep = keep.compare(activeCell.getKeepWithNext()); stepPenalty = Math.max(stepPenalty, activeCell.getPenaltyValue()); } if (!rowFinished) { - strength = Math.max(strength, rowGroup[activeRowIndex].getKeepTogetherStrength()); + keep = keep.compare(rowGroup[activeRowIndex].getKeepTogether()); //The above call doesn't take the penalty from the table into account, so... - strength = Math.max(strength, getTableLM().getKeepTogetherStrength()); + keep = keep.compare(getTableLM().getKeepTogether()); } else if (activeRowIndex < rowGroup.length - 1) { - strength = Math.max(strength, - rowGroup[activeRowIndex].getKeepWithNextStrength()); - strength = Math.max(strength, - rowGroup[activeRowIndex + 1].getKeepWithPreviousStrength()); + keep = keep.compare(rowGroup[activeRowIndex].getKeepWithNext()); + keep = keep.compare(rowGroup[activeRowIndex + 1].getKeepWithPrevious()); nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass, rowGroup[activeRowIndex].getBreakAfter()); nextBreakClass = BreakUtil.compareBreakClasses(nextBreakClass, rowGroup[activeRowIndex + 1].getBreakBefore()); } - int p = KeepUtil.getPenaltyForKeep(strength); + int p = keep.getPenalty(); if (rowHeightSmallerThanFirstStep) { rowHeightSmallerThanFirstStep = false; p = KnuthPenalty.INFINITE; } - if (p > -KnuthElement.INFINITE) { - p = Math.max(p, stepPenalty); - } + p = Math.max(p, stepPenalty); + int breakClass = keep.getContext(); if (nextBreakClass != Constants.EN_AUTO) { log.trace("Forced break encountered"); p = -KnuthPenalty.INFINITE; //Overrides any keeps (see 4.8 in XSL 1.0) + breakClass = nextBreakClass; } - returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, nextBreakClass, context)); + returnList.add(new BreakElement(penaltyPos, effPenaltyLen, p, breakClass, context)); if (penaltyOrGlueLen < 0) { returnList.add(new KnuthGlue(-penaltyOrGlueLen, 0, 0, new Position(null), true)); } |