diff options
author | Vincent Hennebert <vhennebert@apache.org> | 2009-08-26 17:42:11 +0000 |
---|---|---|
committer | Vincent Hennebert <vhennebert@apache.org> | 2009-08-26 17:42:11 +0000 |
commit | 9520407736edcb4389c1418b70e0f7f376d7bd85 (patch) | |
tree | 04d708dc09139eae1e4668c14314231c5ed4a71c | |
parent | ccc743d929c38077f06886f245bd05f3a7780999 (diff) | |
download | xmlgraphics-fop-9520407736edcb4389c1418b70e0f7f376d7bd85.tar.gz xmlgraphics-fop-9520407736edcb4389c1418b70e0f7f376d7bd85.zip |
Reverted changes made in revision 796809 (manual merge of clean-up changes made in the ChangingIPDHack branch). Those changes will be re-applied when merging the branch back to Trunk with svn merge --reintegrate (if everything goes well...)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@808135 13f79535-47bb-0310-9956-ffa450edef68
16 files changed, 807 insertions, 343 deletions
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index cc23de404..6393935ae 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -293,6 +293,14 @@ public abstract class AbstractBreaker { /** * Starts the page breaking process. * @param flowBPD the constant available block-progression-dimension (used for every part) + */ + public void doLayout(int flowBPD) { + doLayout(flowBPD, false); + } + + /** + * Starts the page breaking process. + * @param flowBPD the constant available block-progression-dimension (used for every part) * @param autoHeight true if warnings about overflows should be disabled because the * the BPD is really undefined (for footnote-separators, for example) */ diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index 690081d23..8dca1c749 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -47,22 +47,22 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager private static Log log = LogFactory.getLog(AbstractLayoutManager.class); /** Parent LayoutManager for this LayoutManager */ - protected LayoutManager parentLM; + protected LayoutManager parentLM = null; /** List of child LayoutManagers */ - protected List childLMs; + protected List childLMs = null; /** Iterator for child LayoutManagers */ - protected ListIterator fobjIter; + protected ListIterator fobjIter = null; /** Marker map for markers related to this LayoutManager */ - private Map markers; + private Map markers = null; /** True if this LayoutManager has handled all of its content. */ - private boolean isFinished; + private boolean isFinished = false; /** child LM during getNextKnuthElement phase */ - protected LayoutManager curChildLM; + protected LayoutManager curChildLM = null; /** child LM iterator during getNextKnuthElement phase */ - protected ListIterator childLMiter; + protected ListIterator childLMiter = null; private int lastGeneratedPosition = -1; private int smallestPosNumberChecked = Integer.MAX_VALUE; diff --git a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java index 14183c52e..a429359ad 100644 --- a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java +++ b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java @@ -117,7 +117,7 @@ public class AreaAdditionUtil { // set space after for each LM, in order to implement // display-align = distribute lc.setSpaceAfter(layoutContext.getSpaceAfter()); - lc.setStackLimitBP(layoutContext.getStackLimitBP()); + lc.setStackLimitsFrom(layoutContext); childLM.addAreas(childPosIter, lc); } diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 4b21b4e11..20895a38e 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -67,6 +67,9 @@ public class BlockLayoutManager extends BlockStackingLayoutManager private MinOptMax effSpaceBefore; private MinOptMax effSpaceAfter; + /** The list of child BreakPoss instances. */ + protected List childBreaks = new java.util.ArrayList(); + /** * Creates a new BlockLayoutManager. * @param inBlock the block FO object to create the layout manager for. @@ -246,8 +249,8 @@ public class BlockLayoutManager extends BlockStackingLayoutManager // and put them in a new list; LinkedList positionList = new LinkedList(); Position pos; - boolean spaceBefore = false; - boolean spaceAfter = false; + boolean bSpaceBefore = false; + boolean bSpaceAfter = false; Position firstPos = null; Position lastPos = null; while (parentIter.hasNext()) { @@ -270,11 +273,11 @@ public class BlockLayoutManager extends BlockStackingLayoutManager // this means the space was not discarded if (positionList.size() == 0) { // pos was in the element representing space-before - spaceBefore = true; + bSpaceBefore = true; //log.trace(" space before"); } else { // pos was in the element representing space-after - spaceAfter = true; + bSpaceAfter = true; //log.trace(" space-after"); } } else if (innerPosition.getLM() == this @@ -299,7 +302,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager // the Positions in positionList were inside the elements // created by the LineLM childPosIter = new StackingIter(positionList.listIterator()); - } else { + } else { // the Positions in positionList were inside the elements // created by the BlockLM in the createUnitElements() method //if (((Position) positionList.getLast()) instanceof @@ -338,7 +341,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager // + " spacing"); // add space before and / or after the paragraph // to reach a multiple of bpUnit - if (spaceBefore && spaceAfter) { + if (bSpaceBefore && bSpaceAfter) { foSpaceBefore = new SpaceVal(getBlockFO() .getCommonMarginBlock().spaceBefore, this).getSpace(); foSpaceAfter = new SpaceVal(getBlockFO() @@ -351,7 +354,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager + foSpaceBefore.min + foSpaceAfter.min) * bpUnit - splitLength - adjustedSpaceBefore; - } else if (spaceBefore) { + } else if (bSpaceBefore) { adjustedSpaceBefore = neededUnits(splitLength + foSpaceBefore.min) * bpUnit - splitLength; diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 3cd7b0994..73c8eb00d 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -54,26 +54,31 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager */ private static Log log = LogFactory.getLog(BlockStackingLayoutManager.class); - protected BlockParent parentArea; + /** + * Reference to FO whose areas it's managing or to the traits + * of the FO. + */ + //protected LayoutManager curChildLM = null; AbstractLayoutManager also defines this! + protected BlockParent parentArea = null; /** Value of the block-progression-unit (non-standard property) */ - protected int bpUnit; + protected int bpUnit = 0; /** space-before value adjusted for block-progression-unit handling */ - protected int adjustedSpaceBefore; + protected int adjustedSpaceBefore = 0; /** space-after value adjusted for block-progression-unit handling */ - protected int adjustedSpaceAfter; + protected int adjustedSpaceAfter = 0; /** Only used to store the original list when createUnitElements is called */ - protected List storedList; + protected List storedList = null; /** Indicates whether break before has been served or not */ - protected boolean breakBeforeServed; + protected boolean breakBeforeServed = false; /** Indicates whether the first visible mark has been returned by this LM, yet */ - protected boolean firstVisibleMarkServed; + protected boolean firstVisibleMarkServed = false; /** Reference IPD available */ - protected int referenceIPD; + protected int referenceIPD = 0; /** the effective start-indent value */ - protected int startIndent; + protected int startIndent = 0; /** the effective end-indent value */ - protected int endIndent; + protected int endIndent = 0; /** * Holds the (one-time use) fo:block space-before * and -after properties. Large fo:blocks are split @@ -83,13 +88,13 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * Block and space-after at the end of the last Block * used in rendering the fo:block. */ - protected MinOptMax foSpaceBefore; + protected MinOptMax foSpaceBefore = null; /** see foSpaceBefore */ - protected MinOptMax foSpaceAfter; + protected MinOptMax foSpaceAfter = null; private Position auxiliaryPosition; - private int contentAreaIPD; + private int contentAreaIPD = 0; /** * @param node the fo this LM deals with @@ -243,27 +248,38 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager /** {@inheritDoc} */ public List getNextKnuthElements(LayoutContext context, int alignment) { + //log.debug("BLM.getNextKnuthElements> keep-together = " + // + layoutProps.keepTogether.getType()); + //log.debug(" keep-with-previous = " + + // layoutProps.keepWithPrevious.getType()); + //log.debug(" keep-with-next = " + + // layoutProps.keepWithNext.getType()); + BlockLevelLayoutManager curLM; // currently active LM + BlockLevelLayoutManager prevLM = null; // previously active LM + referenceIPD = context.getRefIPD(); + updateContentAreaIPDwithOverconstrainedAdjust(); + List returnedList = null; List contentList = new LinkedList(); - List elements = new LinkedList(); + List returnList = new LinkedList(); if (!breakBeforeServed) { breakBeforeServed = true; if (!context.suppressBreakBefore()) { - if (addKnuthElementsForBreakBefore(elements, context)) { - return elements; + if (addKnuthElementsForBreakBefore(returnList, context)) { + return returnList; } } } if (!firstVisibleMarkServed) { - addKnuthElementsForSpaceBefore(elements, alignment); + addKnuthElementsForSpaceBefore(returnList, alignment); context.updateKeepWithPreviousPending(getKeepWithPrevious()); } - addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed); + addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); firstVisibleMarkServed = true; //Spaces, border and padding to be repeated at each break @@ -272,107 +288,142 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager //Used to indicate a special break-after case when all content has already been generated. BreakElement forcedBreakAfterLast = null; - LayoutManager currentChildLM; - while ((currentChildLM = (LayoutManager) getChildLM()) != null) { + while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); + childLC.copyPendingMarksFrom(context); + if (curLM instanceof LineLayoutManager) { + // curLM is a LineLayoutManager + // set stackLimit for lines (stack limit is now i-p-direction, not b-p-direction!) + childLC.setStackLimitBP(context.getStackLimitBP()); + childLC.setStackLimitIP(new MinOptMax(getContentAreaIPD())); + childLC.setRefIPD(getContentAreaIPD()); + } else { + // curLM is a ? + //childLC.setStackLimit(MinOptMax.subtract(context + // .getStackLimit(), stackSize)); + childLC.setStackLimitBP(context.getStackLimitBP()); + childLC.setRefIPD(referenceIPD); + } + if (curLM == this.childLMs.get(0)) { + childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); + //Handled already by the parent (break collapsing, see above) + } - List childrenElements = getNextChildElements(currentChildLM, context, childLC, - alignment); - - if (contentList.isEmpty()) { + // get elements from curLM + returnedList = curLM.getNextKnuthElements(childLC, alignment); + if (contentList.isEmpty() && childLC.isKeepWithPreviousPending()) { //Propagate keep-with-previous up from the first child context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + childLC.clearKeepWithPreviousPending(); } - if (childrenElements != null && !childrenElements.isEmpty()) { - if (!contentList.isEmpty() - && !ElementListUtils.startsWithForcedBreak(childrenElements)) { + if (returnedList != null + && returnedList.size() == 1 + && ((ListElement) returnedList.get(0)).isForcedBreak()) { + + if (curLM.isFinished() && !hasNextChildLM()) { + // a descendant of this block has break-before + forcedBreakAfterLast = (BreakElement) returnedList.get(0); + context.clearPendingMarks(); + break; + } + + if (contentList.isEmpty()) { + // Empty fo:block, zero-length box makes sure the IDs and/or markers + // are registered and borders/padding are painted. + returnList.add(new KnuthBox(0, notifyPos(new Position(this)), false)); + } + // a descendant of this block has break-before + contentList.addAll(returnedList); + + /* extension: conversione di tutta la sequenza fin'ora ottenuta */ + if (bpUnit > 0) { + storedList = contentList; + contentList = createUnitElements(contentList); + } + /* end of extension */ + + // "wrap" the Position inside each element + // moving the elements from contentList to returnList + returnedList = new LinkedList(); + wrapPositionElements(contentList, returnList); + + return returnList; + } else { + if (returnedList == null || returnedList.isEmpty()) { + //Avoid NoSuchElementException below (happens with empty blocks) + continue; + } + if (prevLM != null + && !ElementListUtils.startsWithForcedBreak(returnedList)) { // there is a block handled by prevLM before the one // handled by curLM, and the one handled // by the current LM does not begin with a break addInBetweenBreak(contentList, context, childLC); } - if (childrenElements.size() == 1 - && ElementListUtils.startsWithForcedBreak(childrenElements)) { - - if (currentChildLM.isFinished() && !hasNextChildLM()) { - // a descendant of this block has break-before - forcedBreakAfterLast = (BreakElement) childrenElements.get(0); + contentList.addAll(returnedList); + if (ElementListUtils.endsWithForcedBreak(returnedList)) { + // a descendant of this block has break-after + if (curLM.isFinished() && !hasNextChildLM()) { + forcedBreakAfterLast = (BreakElement) ListUtil + .removeLast(contentList); context.clearPendingMarks(); break; } - if (contentList.isEmpty()) { - // Empty fo:block, zero-length box makes sure the IDs and/or markers - // are registered and borders/padding are painted. - elements.add(new KnuthBox(0, notifyPos(new Position(this)), false)); + /* extension: conversione di tutta la sequenza fin'ora ottenuta */ + if (bpUnit > 0) { + storedList = contentList; + contentList = createUnitElements(contentList); } - // a descendant of this block has break-before - contentList.addAll(childrenElements); + /* end of extension */ - wrapPositionElements(contentList, elements); + returnedList = new LinkedList(); + wrapPositionElements(contentList, returnList); - return elements; - } else { - contentList.addAll(childrenElements); - if (ElementListUtils.endsWithForcedBreak(childrenElements)) { - // a descendant of this block has break-after - if (currentChildLM.isFinished() && !hasNextChildLM()) { - forcedBreakAfterLast = (BreakElement) ListUtil.removeLast(contentList); - context.clearPendingMarks(); - break; - } - - wrapPositionElements(contentList, elements); - - return elements; - } + return returnList; } - context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); } + // propagate and clear + context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); + childLC.clearKeepsPending(); + prevLM = curLM; + } + + /* Extension: conversione di tutta la sequenza fin'ora ottenuta */ + if (bpUnit > 0) { + storedList = contentList; + contentList = createUnitElements(contentList); } + /* end of extension */ + returnedList = new LinkedList(); if (!contentList.isEmpty()) { - wrapPositionElements(contentList, elements); + wrapPositionElements(contentList, returnList); } else if (forcedBreakAfterLast == null) { // Empty fo:block, zero-length box makes sure the IDs and/or markers // are registered. - elements.add(new KnuthBox(0, notifyPos(new Position(this)), true)); + returnList.add(new KnuthBox(0, notifyPos(new Position(this)), true)); } - addKnuthElementsForBorderPaddingAfter(elements, true); - addKnuthElementsForSpaceAfter(elements, alignment); + addKnuthElementsForBorderPaddingAfter(returnList, true); + addKnuthElementsForSpaceAfter(returnList, alignment); //All child content is processed. Only break-after can occur now, so... context.clearPendingMarks(); if (forcedBreakAfterLast == null) { - addKnuthElementsForBreakAfter(elements, context); - } else { + addKnuthElementsForBreakAfter(returnList, context); + } + + if (forcedBreakAfterLast != null) { forcedBreakAfterLast.clearPendingMarks(); - elements.add(forcedBreakAfterLast); + returnList.add(forcedBreakAfterLast); } context.updateKeepWithNextPending(getKeepWithNext()); setFinished(true); - return elements; - } - - private List getNextChildElements(LayoutManager childLM, LayoutContext context, - LayoutContext childLC, int alignment) { - childLC.copyPendingMarksFrom(context); - childLC.setStackLimitBP(context.getStackLimitBP()); - if (childLM instanceof LineLayoutManager) { - childLC.setRefIPD(getContentAreaIPD()); - } else { - childLC.setRefIPD(referenceIPD); - } - if (childLM == this.childLMs.get(0)) { - childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); - //Handled already by the parent (break collapsing, see above) - } - - return childLM.getNextKnuthElements(childLC, alignment); + return returnList; } /** diff --git a/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java index bde969211..c6bd7bcec 100644 --- a/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java @@ -1283,8 +1283,12 @@ public abstract class BreakingAlgorithm { * @return the width/length in millipoints */ protected int getLineWidth(int line) { - assert lineWidth >= 0; - return this.lineWidth; + if (this.lineWidth < 0) { + throw new IllegalStateException("lineWidth must be set" + + (this.lineWidth != 0 ? " and positive, but it is: " + this.lineWidth : "")); + } else { + return this.lineWidth; + } } /** @return the constant line/part width or -1 if there is no such value */ diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 6424475c3..5a80c3318 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -29,6 +29,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.fop.area.Area; import org.apache.fop.area.BlockParent; import org.apache.fop.fo.pagination.Flow; +import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; +import org.apache.fop.layoutmgr.inline.WrapperLayoutManager; /** * LayoutManager for an fo:flow object. @@ -62,89 +64,110 @@ public class FlowLayoutManager extends BlockStackingLayoutManager /** {@inheritDoc} */ public List getNextKnuthElements(LayoutContext context, int alignment) { - List elements = new LinkedList(); + // set layout dimensions + int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth(); + int flowBPD = getCurrentPV().getBodyRegion().getBPD(); - LayoutManager currentChildLM; - while ((currentChildLM = getChildLM()) != null) { - if (handleSpanChange(currentChildLM, elements, context)) { - SpaceResolver.resolveElementList(elements); - return elements; + // currently active LM + LayoutManager curLM; + List returnedList; + List returnList = new LinkedList(); + + while ((curLM = getChildLM()) != null) { + if (!(curLM instanceof WrapperLayoutManager) + && curLM instanceof InlineLevelLayoutManager) { + log.error("inline area not allowed under flow - ignoring"); + curLM.setFinished(true); + continue; } - LayoutContext childLC = new LayoutContext(0); - List childrenElements = getNextChildElements(currentChildLM, context, childLC, - alignment); - if (elements.isEmpty()) { - context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + int span = EN_NONE; + int disableColumnBalancing = EN_FALSE; + if (curLM instanceof BlockLayoutManager) { + span = ((BlockLayoutManager)curLM).getBlockFO().getSpan(); + disableColumnBalancing = ((BlockLayoutManager) curLM).getBlockFO() + .getDisableColumnBalancing(); + } else if (curLM instanceof BlockContainerLayoutManager) { + span = ((BlockContainerLayoutManager)curLM).getBlockContainerFO().getSpan(); + disableColumnBalancing = ((BlockContainerLayoutManager) curLM).getBlockContainerFO() + .getDisableColumnBalancing(); } - if (!elements.isEmpty() - && !ElementListUtils.startsWithForcedBreak(childrenElements)) { - addInBetweenBreak(elements, context, childLC); + + int currentSpan = context.getCurrentSpan(); + if (currentSpan != span) { + if (span == EN_ALL) { + context.setDisableColumnBalancing(disableColumnBalancing); + } + log.debug("span change from " + currentSpan + " to " + span); + context.signalSpanChange(span); + SpaceResolver.resolveElementList(returnList); + return returnList; } - context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); - elements.addAll(childrenElements); + // Set up a LayoutContext + //MinOptMax bpd = context.getStackLimit(); - if (ElementListUtils.endsWithForcedBreak(elements)) { - // a descendant of this flow has break-before or break-after - if (currentChildLM.isFinished() && !hasNextChildLM()) { - setFinished(true); - } - SpaceResolver.resolveElementList(elements); - return elements; + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimitBP(context.getStackLimitBP()); + childLC.setRefIPD(context.getRefIPD()); + childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode()); + + // get elements from curLM + returnedList = curLM.getNextKnuthElements(childLC, alignment); + //log.debug("FLM.getNextKnuthElements> returnedList.size() = " + returnedList.size()); + if (returnList.size() == 0 && childLC.isKeepWithPreviousPending()) { + context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending()); + childLC.clearKeepWithPreviousPending(); } - } - SpaceResolver.resolveElementList(elements); - setFinished(true); + // "wrap" the Position inside each element + List tempList = returnedList; + returnedList = new LinkedList(); + wrapPositionElements(tempList, returnedList); + + if (returnedList.size() == 1 + && ElementListUtils.endsWithForcedBreak(returnedList)) { + // a descendant of this flow has break-before + returnList.addAll(returnedList); + SpaceResolver.resolveElementList(returnList); + return returnList; + } else if (returnedList.size() > 0) { + if (returnList.size() > 0 + && !ElementListUtils.startsWithForcedBreak(returnedList)) { + addInBetweenBreak(returnList, context, childLC); + } + returnList.addAll(returnedList); + if (ElementListUtils.endsWithForcedBreak(returnList)) { + if (curLM.isFinished() && !hasNextChildLM()) { + //If the layout manager is finished at this point, the pending + //marks become irrelevant. + childLC.clearPendingMarks(); + //setFinished(true); + break; + } + // a descendant of this flow has break-after + SpaceResolver.resolveElementList(returnList); + return returnList; + } + } - assert !elements.isEmpty(); - return elements; - } + //Propagate and clear + context.updateKeepWithNextPending(childLC.getKeepWithNextPending()); + childLC.clearKeepWithNextPending(); - private boolean handleSpanChange(LayoutManager childLM, List elements, LayoutContext context) { - int span = EN_NONE; - int disableColumnBalancing = EN_FALSE; - if (childLM instanceof BlockLayoutManager) { - span = ((BlockLayoutManager)childLM).getBlockFO().getSpan(); - disableColumnBalancing = ((BlockLayoutManager) childLM).getBlockFO() - .getDisableColumnBalancing(); - } else if (childLM instanceof BlockContainerLayoutManager) { - span = ((BlockContainerLayoutManager)childLM).getBlockContainerFO().getSpan(); - disableColumnBalancing = ((BlockContainerLayoutManager) childLM).getBlockContainerFO() - .getDisableColumnBalancing(); + context.updateKeepWithNextPending(getKeepWithNext()); } - int currentSpan = context.getCurrentSpan(); - if (currentSpan != span) { - if (span == EN_ALL) { - context.setDisableColumnBalancing(disableColumnBalancing); - } - log.debug("span change from " + currentSpan + " to " + span); - context.signalSpanChange(span); - return true; + SpaceResolver.resolveElementList(returnList); + setFinished(true); + + if (returnList.size() > 0) { + return returnList; } else { - return false; + return null; } } - private List getNextChildElements(LayoutManager childLM, LayoutContext context, - LayoutContext childLC, int alignment) { - childLC.setStackLimitBP(context.getStackLimitBP()); - childLC.setRefIPD(context.getRefIPD()); - childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode()); - - // get elements from curLM - List childrenElements = childLM.getNextKnuthElements(childLC, alignment); - assert !childrenElements.isEmpty(); - - // "wrap" the Position inside each element - List tempList = childrenElements; - childrenElements = new LinkedList(); - wrapPositionElements(tempList, childrenElements); - return childrenElements; - } - /** * {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java b/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java index 104c71131..6d11a3c24 100644 --- a/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java +++ b/src/java/org/apache/fop/layoutmgr/InlineKnuthSequence.java @@ -57,12 +57,16 @@ public class InlineKnuthSequence extends KnuthSequence { return true; } - /** {@inheritDoc} */ + /* (non-Javadoc) + * {@inheritDoc} + */ public boolean canAppendSequence(KnuthSequence sequence) { return sequence.isInlineSequence() && !isClosed; } - /** {@inheritDoc} */ + /* (non-Javadoc) + * {@inheritDoc} + */ public boolean appendSequence(KnuthSequence sequence) { if (!canAppendSequence(sequence)) { return false; @@ -79,14 +83,18 @@ public class InlineKnuthSequence extends KnuthSequence { return true; } - /** {@inheritDoc} */ + /* (non-Javadoc) + * {@inheritDoc} + */ public boolean appendSequence(KnuthSequence sequence, boolean keepTogether, BreakElement breakElement) { return appendSequence(sequence); } - /** {@inheritDoc} */ + /* (non-Javadoc) + * {@inheritDoc} + */ public KnuthSequence endSequence() { if (!isClosed) { add(new KnuthPenalty(0, -KnuthElement.INFINITE, false, null, false)); diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 81726e57b..41d4c5cfc 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -78,6 +78,15 @@ public class LayoutContext { * level LM to allow them to optimize returned break possibilities. */ private MinOptMax stackLimitBP; + /** + * Total available stacking dimension for a "galley-level" layout + * manager in inline-progression-direction. It is passed by the + * parent LM. For LineLM, the block LM determines this based on + * indent properties. + * These LM <b>may</b> wish to pass this information down to lower + * level LM to allow them to optimize returned break possibilities. + */ + private MinOptMax stackLimitIP; /** to keep track of spanning in multi-column layout */ private int currentSpan = Constants.NOT_SET; @@ -149,7 +158,7 @@ public class LayoutContext { this.flags = parentLC.flags; this.refIPD = parentLC.refIPD; this.writingMode = parentLC.writingMode; - setStackLimitBP(parentLC.getStackLimitBP()); + setStackLimitsFrom(parentLC); this.leadingSpace = parentLC.leadingSpace; //??? this.trailingSpace = parentLC.trailingSpace; //??? this.hyphContext = parentLC.hyphContext; @@ -174,6 +183,7 @@ public class LayoutContext { this.flags = flags; this.refIPD = 0; stackLimitBP = new MinOptMax(0); + stackLimitIP = new MinOptMax(0); leadingSpace = null; trailingSpace = null; } @@ -388,6 +398,31 @@ public class LayoutContext { } /** + * Sets the stack limit in inline-progression-dimension. + * @param limit the stack limit + */ + public void setStackLimitIP(MinOptMax limit) { + stackLimitIP = limit; + } + + /** + * Returns the stack limit in inline-progression-dimension. + * @return the stack limit + */ + public MinOptMax getStackLimitIP() { + return stackLimitIP; + } + + /** + * Sets (Copies) the stack limits in both directions from another layout context. + * @param context the layout context to take the values from + */ + public void setStackLimitsFrom(LayoutContext context) { + setStackLimitBP(context.getStackLimitBP()); + setStackLimitIP(context.getStackLimitIP()); + } + + /** * Sets the inline-progression-dimension of the nearest ancestor reference area. */ public void setRefIPD(int ipd) { @@ -627,6 +662,8 @@ public class LayoutContext { return "Layout Context:" + "\nStack Limit BPD: \t" + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString()) + + "\nStack Limit IPD: \t" + + (getStackLimitIP() == null ? "null" : getStackLimitIP().toString()) + "\nTrailing Space: \t" + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString()) + "\nLeading Space: \t" diff --git a/src/java/org/apache/fop/layoutmgr/LeafPosition.java b/src/java/org/apache/fop/layoutmgr/LeafPosition.java index 07eeef51f..ed8cc94e2 100644 --- a/src/java/org/apache/fop/layoutmgr/LeafPosition.java +++ b/src/java/org/apache/fop/layoutmgr/LeafPosition.java @@ -21,15 +21,15 @@ package org.apache.fop.layoutmgr; public class LeafPosition extends Position { - private int leafPos; + private int iLeafPos; public LeafPosition(LayoutManager lm, int pos) { super(lm); - leafPos = pos; + iLeafPos = pos; } public int getLeafPos() { - return leafPos; + return iLeafPos; } public boolean generatesAreas() { diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index 84afdcea9..ed0b37602 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -77,14 +77,6 @@ public class PageBreaker extends AbstractBreaker { return pslm.getPageProvider(); } - /** - * Starts the page breaking process. - * @param flowBPD the constant available block-progression-dimension (used for every part) - */ - void doLayout(int flowBPD) { - doLayout(flowBPD, false); - } - /** {@inheritDoc} */ protected PageBreakingLayoutListener createLayoutListener() { return new PageBreakingLayoutListener() { diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index d5949f4a2..4bfbd46f5 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -21,6 +21,10 @@ package org.apache.fop.layoutmgr; import java.util.LinkedList; import java.util.List; +import java.util.ListIterator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -31,7 +35,10 @@ import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.fo.pagination.SideRegion; import org.apache.fop.fo.pagination.StaticContent; import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener; +import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; import org.apache.fop.layoutmgr.inline.TextLayoutManager; +import org.apache.fop.traits.MinOptMax; +import org.apache.fop.util.ListUtil; /** * LayoutManager for an fo:flow object. @@ -41,6 +48,11 @@ import org.apache.fop.layoutmgr.inline.TextLayoutManager; */ public class StaticContentLayoutManager extends BlockStackingLayoutManager { + /** + * logging instance + */ + private static Log log = LogFactory.getLog(StaticContentLayoutManager.class); + private RegionReference targetRegion; private Block targetBlock; private SideRegion regionFO; @@ -77,7 +89,96 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { /** {@inheritDoc} */ public List getNextKnuthElements(LayoutContext context, int alignment) { - throw new IllegalStateException(); + if (true) { + throw new UnsupportedOperationException( + "Shouldn't this method be emptied because it's never called at all?"); + } + //TODO Empty this method?!? + // set layout dimensions + setContentAreaIPD(context.getRefIPD()); + setContentAreaBPD(context.getStackLimitBP().opt); + + //TODO Copied from elsewhere. May be worthwhile to factor out the common parts. + // currently active LM + BlockLevelLayoutManager curLM; + BlockLevelLayoutManager prevLM = null; + MinOptMax stackSize = new MinOptMax(); + List returnedList; + List returnList = new LinkedList(); + + while ((curLM = ((BlockLevelLayoutManager) getChildLM())) != null) { + if (curLM instanceof InlineLevelLayoutManager) { + log.error("inline area not allowed under flow - ignoring"); + curLM.setFinished(true); + continue; + } + + // Set up a LayoutContext + MinOptMax bpd = context.getStackLimitBP(); + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimitBP(MinOptMax.subtract(bpd, stackSize)); + childLC.setRefIPD(context.getRefIPD()); + + // get elements from curLM + returnedList = curLM.getNextKnuthElements(childLC, alignment); + //log.debug("FLM.getNextKnuthElements> returnedList.size() = " + // + returnedList.size()); + + // "wrap" the Position inside each element + List tempList = returnedList; + KnuthElement tempElement; + returnedList = new LinkedList(); + ListIterator listIter = tempList.listIterator(); + while (listIter.hasNext()) { + tempElement = (KnuthElement)listIter.next(); + tempElement.setPosition(new NonLeafPosition(this, tempElement.getPosition())); + returnedList.add(tempElement); + } + + if (returnedList.size() == 1 + && ((KnuthElement)returnedList.get(0)).isPenalty() + && ((KnuthPenalty)returnedList.get(0)).getP() == -KnuthElement.INFINITE) { + // a descendant of this flow has break-before + returnList.addAll(returnedList); + return returnList; + } else { + if (!returnList.isEmpty()) { + // there is a block before this one + if (prevLM.mustKeepWithNext() + || curLM.mustKeepWithPrevious()) { + // add an infinite penalty to forbid a break between blocks + returnList.add(new KnuthPenalty(0, + KnuthElement.INFINITE, false, + new Position(this), false)); + } else if (!((KnuthElement) ListUtil.getLast(returnList)) + .isGlue()) { + // add a null penalty to allow a break between blocks + returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false)); + } + } +/*LF*/ if (!returnedList.isEmpty()) { // controllare! + returnList.addAll(returnedList); + final KnuthElement last = (KnuthElement) ListUtil + .getLast(returnedList); + if (last.isPenalty() + && ((KnuthPenalty) last).getP() == -KnuthElement.INFINITE) { + // a descendant of this flow has break-after +/*LF*/ //log.debug("FLM - break after!!"); + return returnList; + } +/*LF*/ } + } + prevLM = curLM; + } + + setFinished(true); + + if (returnList.isEmpty()) { + return null; + } else { + return returnList; + } } /** diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index 95f798161..a5247d652 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -27,7 +27,6 @@ import java.util.ListIterator; 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.LineArea; @@ -44,6 +43,7 @@ import org.apache.fop.layoutmgr.PageSequenceLayoutManager; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.SpaceSpecifier; +import org.apache.fop.traits.MinOptMax; /** * Content Layout Manager. @@ -111,6 +111,8 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager LayoutContext childLC = new LayoutContext(LayoutContext.NEW_AREA); childLC.setLeadingSpace(new SpaceSpecifier(false)); childLC.setTrailingSpace(new SpaceSpecifier(false)); + // set stackLimit for lines + childLC.setStackLimitIP(new MinOptMax(ipd)); childLC.setRefIPD(ipd); int lineHeight = 14000; @@ -127,7 +129,8 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager stackSize = 0; - List contentList = getNextKnuthElements(childLC, Constants.EN_START); + List contentList = + getNextKnuthElements(childLC, Constants.EN_START); ListIterator contentIter = contentList.listIterator(); while (contentIter.hasNext()) { KnuthElement element = (KnuthElement) contentIter.next(); @@ -146,7 +149,8 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true); lc.setLeadingSpace(new SpaceSpecifier(false)); lc.setTrailingSpace(new SpaceSpecifier(false)); - KnuthPossPosIter contentPosIter = new KnuthPossPosIter(contentList, 0, contentList.size()); + KnuthPossPosIter contentPosIter = + new KnuthPossPosIter(contentList, 0, contentList.size()); curLM.addAreas(contentPosIter, lc); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 6e0c34a82..0c332281f 100755 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -248,6 +248,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { List returnList = new LinkedList(); KnuthSequence lastSequence = null; + SpaceSpecifier leadingSpace = context.getLeadingSpace(); + if (fobj instanceof Title) { alignmentContext = new AlignmentContext(font, lineHeight.getOptimum(this).getLength().getValue(this), @@ -272,6 +274,14 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { if (getSpaceStart() != null) { context.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart(), this)); } + + // Check for "fence" + if (hasLeadingFence(!context.isFirstArea())) { + // Reset leading space sequence for child areas + leadingSpace = new SpaceSpecifier(false); + } + // Reset state variables + clearPrevIPD(); // Clear stored prev content dimensions } StringBuffer trace = new StringBuffer("InlineLM:"); diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index 65e59554f..963b98b37 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -19,13 +19,12 @@ package org.apache.fop.layoutmgr.inline; -import java.util.Iterator; import java.util.LinkedList; +import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.HashMap; -import org.apache.fop.area.Area; -import org.apache.fop.area.inline.Space; import org.apache.fop.fo.FObj; import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.layoutmgr.AbstractLayoutManager; @@ -35,6 +34,8 @@ import org.apache.fop.layoutmgr.LayoutManager; import org.apache.fop.layoutmgr.NonLeafPosition; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; +import org.apache.fop.area.Area; +import org.apache.fop.area.inline.Space; import org.apache.fop.traits.MinOptMax; /** @@ -61,6 +62,12 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager } } + + /** + * Size of any start or end borders and padding. + */ + private MinOptMax allocIPD = new MinOptMax(0); + /** * Size of border and padding in BPD (ie, before and after). */ @@ -71,6 +78,9 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager /** The child layout context */ protected LayoutContext childLC; + /** Used to store previous content IPD for each child LM. */ + private HashMap hmPrevIPD = new HashMap(); + /** * Create an inline stacking layout manager. * This is used for fo's that create areas that @@ -139,6 +149,22 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager } /** + * TODO: Explain this method + * @param lm ??? + * @return ??? + */ + protected MinOptMax getPrevIPD(LayoutManager lm) { + return (MinOptMax) hmPrevIPD.get(lm); + } + + /** + * Clear the previous IPD calculation. + */ + protected void clearPrevIPD() { + hmPrevIPD.clear(); + } + + /** * Returns the current area. * @return the current area */ diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 95bc9ab2d..aea851f54 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -116,8 +116,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager * inline break positions. */ private static class LineBreakPosition extends LeafPosition { - private int parIndex; // index of the Paragraph this Position refers to - private int startIndex; //index of the first element this Position refers to + private int iParIndex; // index of the Paragraph this Position refers to + private int iStartIndex; //index of the first element this Position refers to private int availableShrink; private int availableStretch; private int difference; @@ -130,16 +130,16 @@ public class LineLayoutManager extends InlineStackingLayoutManager private int spaceAfter; private int baseline; - LineBreakPosition(LayoutManager lm, int index, int startIndex, int breakIndex, + LineBreakPosition(LayoutManager lm, int index, int iStartIndex, int iBreakIndex, int shrink, int stretch, int diff, double ipdA, double adjust, int ind, int lh, int lw, int sb, int sa, int bl) { - super(lm, breakIndex); + super(lm, iBreakIndex); availableShrink = shrink; availableStretch = stretch; difference = diff; - parIndex = index; - this.startIndex = startIndex; + iParIndex = index; + this.iStartIndex = iStartIndex; ipdAdjust = ipdA; dAdjust = adjust; startIndent = ind; @@ -167,13 +167,18 @@ public class LineLayoutManager extends InlineStackingLayoutManager private Length lineHeight; private int lead; private int follow; - private AlignmentContext alignmentContext; + private AlignmentContext alignmentContext = null; - private List knuthParagraphs; + private List knuthParagraphs = null; + private int iReturnedLBP = 0; + + // parameters of Knuth's algorithm: + // penalty value for flagged penalties + private int flaggedPenalty = 50; private LineLayoutPossibilities lineLayouts; private List lineLayoutsList; - private int ipd = 0; + private int iLineWidth = 0; /** * this constant is used to create elements when text-align is center: @@ -233,7 +238,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } else { lineFiller = new MinOptMax(lastLineEndIndent, lastLineEndIndent, - layoutManager.ipd); + layoutManager.iLineWidth); } // add auxiliary elements at the beginning of the paragraph @@ -314,9 +319,11 @@ public class LineLayoutManager extends InlineStackingLayoutManager private int activePossibility; private int addedPositions; private int textIndent; + private int fillerMinWidth; private int lineHeight; private int lead; private int follow; + private int maxDiff; private static final double MAX_DEMERITS = 10e6; public LineBreakingAlgorithm (int pageAlign, @@ -327,17 +334,22 @@ public class LineLayoutManager extends InlineStackingLayoutManager super(textAlign, textAlignLast, first, false, maxFlagCount); pageAlignment = pageAlign; textIndent = indent; + fillerMinWidth = fillerWidth; lineHeight = lh; lead = ld; follow = fl; thisLLM = llm; activePossibility = -1; + maxDiff = fobj.getWidows() >= fobj.getOrphans() + ? fobj.getWidows() + : fobj.getOrphans(); } public void updateData1(int lineCount, double demerits) { lineLayouts.addPossibility(lineCount, demerits); - if (log.isTraceEnabled()) { - log.trace("Layout possibility in " + lineCount + " lines; break at position:"); + if (super.log.isTraceEnabled()) { + super.log.trace( + "Layout possibility in " + lineCount + " lines; break at position:"); } } @@ -418,7 +430,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager // true if this line contains only zero-height, auxiliary boxes // and the actual line width is 0; in this case, the line "collapses" // i.e. the line area will have bpd = 0 - boolean bZeroHeightLine = (difference == ipd); + boolean bZeroHeightLine = (difference == iLineWidth); // if line-stacking-strategy is "font-height", the line height // is not affected by its content @@ -474,7 +486,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager firstElementIndex, lastElementIndex, availableShrink, availableStretch, difference, ratio, 0, indent, - 0, ipd, 0, 0, 0); + 0, iLineWidth, 0, 0, 0); } else { return new LineBreakPosition(thisLLM, knuthParagraphs.indexOf(par), @@ -482,7 +494,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager availableShrink, availableStretch, difference, ratio, 0, indent, lineLead + lineFollow, - ipd, spaceBefore, spaceAfter, + iLineWidth, spaceBefore, spaceAfter, lineLead); } } @@ -566,12 +578,14 @@ public class LineLayoutManager extends InlineStackingLayoutManager FontInfo fi = fobj.getFOEventHandler().getFontInfo(); FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); Font fs = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this)); - alignmentContext = new AlignmentContext(fs, lineHeight.getValue(this), - context.getWritingMode()); + alignmentContext + = new AlignmentContext(fs, lineHeight.getValue(this), context.getWritingMode()); context.setAlignmentContext(alignmentContext); // Get a break from currently active child LM // Set up constraints for inline level managers + clearPrevIPD(); + //PHASE 1: Create Knuth elements if (knuthParagraphs == null) { // it's the first time this method is called @@ -592,6 +606,34 @@ public class LineLayoutManager extends InlineStackingLayoutManager //PHASE 2: Create line breaks return createLineBreaks(context.getBPAlignment(), context); + /* + LineBreakPosition lbp = null; + if (breakpoints == null) { + // find the optimal line breaking points for each paragraph + breakpoints = new ArrayList(); + ListIterator paragraphsIterator + = knuthParagraphs.listIterator(knuthParagraphs.size()); + Paragraph currPar = null; + while (paragraphsIterator.hasPrevious()) { + currPar = (Paragraph) paragraphsIterator.previous(); + findBreakingPoints(currPar, context.getStackLimit().opt); + } + }*/ + + //PHASE 3: Return lines + + /* + // get a break point from the list + lbp = (LineBreakPosition) breakpoints.get(iReturnedLBP ++); + if (iReturnedLBP == breakpoints.size()) { + setFinished(true); + } + + BreakPoss curLineBP = new BreakPoss(lbp); + curLineBP.setFlag(BreakPoss.ISLAST, isFinished()); + curLineBP.setStackingSize(new MinOptMax(lbp.lineHeight)); + return curLineBP; + */ } /** @@ -601,20 +643,22 @@ public class LineLayoutManager extends InlineStackingLayoutManager private void collectInlineKnuthElements(LayoutContext context) { LayoutContext inlineLC = new LayoutContext(context); - ipd = context.getRefIPD(); + InlineLevelLayoutManager curLM; + List returnedList = null; + iLineWidth = context.getStackLimitIP().opt; // convert all the text in a sequence of paragraphs made // of KnuthBox, KnuthGlue and KnuthPenalty objects - boolean previousIsBox = false; + boolean bPrevWasKnuthBox = false; StringBuffer trace = new StringBuffer("LineLM:"); Paragraph lastPar = null; - InlineLevelLayoutManager curLM; while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) { - List inlineElements = curLM.getNextKnuthElements(inlineLC, effectiveAlignment); - if (inlineElements == null || inlineElements.size() == 0) { + returnedList = curLM.getNextKnuthElements(inlineLC, effectiveAlignment); + if (returnedList == null + || returnedList.size() == 0) { /* curLM.getNextKnuthElements() returned null or an empty list; * this can happen if there is nothing more to layout, * so just iterate once more to see if there are other children */ @@ -622,7 +666,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } if (lastPar != null) { - KnuthSequence firstSeq = (KnuthSequence) inlineElements.get(0); + KnuthSequence firstSeq = (KnuthSequence) returnedList.get(0); // finish last paragraph before a new block sequence if (!firstSeq.isInlineSequence()) { @@ -632,7 +676,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager if (log.isTraceEnabled()) { trace.append(" ]"); } - previousIsBox = false; + bPrevWasKnuthBox = false; } // does the first element of the first paragraph add to an existing word? @@ -640,24 +684,27 @@ public class LineLayoutManager extends InlineStackingLayoutManager KnuthElement thisElement; thisElement = (KnuthElement) firstSeq.get(0); if (thisElement.isBox() && !thisElement.isAuxiliary() - && previousIsBox) { + && bPrevWasKnuthBox) { lastPar.addALetterSpace(); } } } // loop over the KnuthSequences (and single KnuthElements) in returnedList - ListIterator iter = inlineElements.listIterator(); + ListIterator iter = returnedList.listIterator(); while (iter.hasNext()) { KnuthSequence sequence = (KnuthSequence) iter.next(); // the sequence contains inline Knuth elements if (sequence.isInlineSequence()) { // look at the last element ListElement lastElement = sequence.getLast(); - assert lastElement != null; - previousIsBox = lastElement.isBox() - && !((KnuthElement) lastElement).isAuxiliary() - && ((KnuthElement) lastElement).getW() != 0; + if (lastElement == null) { + throw new NullPointerException( + "Sequence was empty! lastElement is null"); + } + bPrevWasKnuthBox = lastElement.isBox() + && !((KnuthElement) lastElement).isAuxiliary() + && ((KnuthElement) lastElement).getW() != 0; // if last paragraph is open, add the new elements to the paragraph // else this is the last paragraph @@ -682,7 +729,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager // finish last paragraph if it was closed with a linefeed if (lastElement.isPenalty() - && ((KnuthPenalty) lastElement).getP() == -KnuthPenalty.INFINITE) { + && ((KnuthPenalty) lastElement).getP() + == -KnuthPenalty.INFINITE) { // a penalty item whose value is -inf // represents a preserved linefeed, // which forces a line break @@ -690,7 +738,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager if (!lastPar.containsBox()) { //only a forced linefeed on this line //-> compensate with an auxiliary glue - lastPar.add(new KnuthGlue(ipd, 0, ipd, null, true)); + lastPar.add(new KnuthGlue(iLineWidth, 0, iLineWidth, null, true)); } lastPar.endParagraph(); ElementListObserver.observe(lastPar, "line", null); @@ -698,7 +746,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager if (log.isTraceEnabled()) { trace.append(" ]"); } - previousIsBox = false; + bPrevWasKnuthBox = false; } } else { // the sequence is a block sequence // the positions will be wrapped with this LM in postProcessLineBreaks @@ -720,14 +768,144 @@ public class LineLayoutManager extends InlineStackingLayoutManager } /** + * Find a set of breaking points. + * This method is called only once by getNextBreakPoss, and it + * subsequently calls the other findBreakingPoints() method with + * different parameters, until a set of breaking points is found. + * + * @param par the list of elements that must be parted + * into lines + * @param lineWidth the desired length ot the lines + */ + /* + private void findBreakingPoints(Paragraph par, int lineWidth) { + // maximum adjustment ratio permitted + float maxAdjustment = 1; + + // first try + if (!findBreakingPoints(par, lineWidth, maxAdjustment, false)) { + // the first try failed, now try something different + log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment); + if (hyphenationProperties.hyphenate == Constants.EN_TRUE) { + // consider every hyphenation point as a legal break + findHyphenationPoints(par); + } else { + // try with a higher threshold + maxAdjustment = 5; + } + + if (!findBreakingPoints(par, lineWidth, maxAdjustment, false)) { + // the second try failed too, try with a huge threshold; + // if this fails too, use a different algorithm + log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment + + (hyphenationProperties.hyphenate == Constants.EN_TRUE ? " and hyphenation" : "")); + maxAdjustment = 20; + if (!findBreakingPoints(par, lineWidth, maxAdjustment, true)) { + log.debug("No set of breaking points found, using first-fit algorithm"); + } + } + } + } + + private boolean findBreakingPoints(Paragraph par, int lineWidth, + double threshold, boolean force) { + KnuthParagraph knuthPara = new KnuthParagraph(par); + int lines = knuthPara.findBreakPoints(lineWidth, threshold, force); + if (lines == 0) { + return false; + } + + for (int i = lines-1; i >= 0; i--) { + int line = i+1; + if (log.isTraceEnabled()) { + log.trace("Making line from " + knuthPara.getStart(i) + " to " + + knuthPara.getEnd(i)); + } + // compute indent and adjustment ratio, according to + // the value of text-align and text-align-last + + int difference = knuthPara.getDifference(i); + if (line == lines) { + difference += par.lineFillerWidth; + } + int textAlign = (line < lines) + ? textAlignment : textAlignmentLast; + int indent = (textAlign == EN_CENTER) + ? difference / 2 + : (textAlign == EN_END) ? difference : 0; + indent += (line == 1 && knuthParagraphs.indexOf(par) == 0) + ? textIndent.getValue(this) : 0; + double ratio = (textAlign == EN_JUSTIFY) + ? knuthPara.getAdjustRatio(i) : 0; + + int start = knuthPara.getStart(i); + int end = knuthPara.getEnd(i); + makeLineBreakPosition(par, start, end, 0, ratio, indent); + } + return true; + } + + private void makeLineBreakPosition(Paragraph par, + int firstElementIndex, int lastElementIndex, + int insertIndex, double ratio, int indent) { + // line height calculation + + int halfLeading = (lineHeight - lead - follow) / 2; + // height above the main baseline + int lineLead = lead + halfLeading; + // maximum size of top and bottom alignment + int lineFollow = follow + halfLeading; + + ListIterator inlineIterator + = par.listIterator(firstElementIndex); + for (int j = firstElementIndex; + j <= lastElementIndex; + j++) { + KnuthElement element = (KnuthElement) inlineIterator.next(); + if (element.isBox()) { + KnuthInlineBox box = (KnuthInlineBox)element; + if (box.getLead() > lineLead) { + lineLead = box.getLead(); + } + if (box.getTotal() > lineFollow) { + lineFollow = box.getTotal(); + } + if (box.getMiddle() > lineLead + middleShift) { + lineLead += box.getMiddle() + - lineLead - middleShift; + } + if (box.getMiddle() > middlefollow - middleShift) { + middlefollow += box.getMiddle() + - middlefollow + middleShift; + } + } + } + + if (lineFollow - lineLead > middlefollow) { + middlefollow = lineFollow - lineLead; + } + + breakpoints.add(insertIndex, + new LineBreakPosition(this, + knuthParagraphs.indexOf(par), + lastElementIndex , + ratio, 0, indent, + lineLead + middlefollow, + lineLead)); + }*/ + + + /** * Phase 2 of Knuth algorithm: find optimal break points. * @param alignment alignment in BP direction of the paragraph * @param context the layout context * @return a list of Knuth elements representing broken lines */ private List createLineBreaks(int alignment, LayoutContext context) { + // find the optimal line breaking points for each paragraph - ListIterator paragraphsIterator = knuthParagraphs.listIterator(knuthParagraphs.size()); + ListIterator paragraphsIterator + = knuthParagraphs.listIterator(knuthParagraphs.size()); lineLayoutsList = new ArrayList(knuthParagraphs.size()); LineLayoutPossibilities llPoss; while (paragraphsIterator.hasPrevious()) { @@ -780,7 +958,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } else { allowedBreaks = BreakingAlgorithm.NO_FLAGGED_PENALTIES; } - alg.setConstantLineWidth(ipd); + alg.setConstantLineWidth(iLineWidth); iBPcount = alg.findBreakingPoints(currPar, maxAdjustment, false, allowedBreaks); if (iBPcount == 0 || alignment == EN_JUSTIFY) { @@ -836,26 +1014,26 @@ public class LineLayoutManager extends InlineStackingLayoutManager alg.resetAlgorithm(); lineLayouts.savePossibilities(true); // try with shorter lines - int savedLineWidth = ipd; - ipd = (int) (ipd * 0.95); + int savedLineWidth = iLineWidth; + iLineWidth = (int) (iLineWidth * 0.95); iBPcount = alg.findBreakingPoints(currPar, - maxAdjustment, true, allowedBreaks); + maxAdjustment, true, allowedBreaks); // use normal lines, when possible lineLayouts.restorePossibilities(); - ipd = savedLineWidth; + iLineWidth = savedLineWidth; } if (!lineLayouts.canUseLessLines()) { alg.resetAlgorithm(); lineLayouts.savePossibilities(true); // try with longer lines - int savedLineWidth = ipd; - ipd = (int) (ipd * 1.05); - alg.setConstantLineWidth(ipd); + int savedLineWidth = iLineWidth; + iLineWidth = (int) (iLineWidth * 1.05); + alg.setConstantLineWidth(iLineWidth); iBPcount = alg.findBreakingPoints(currPar, maxAdjustment, true, allowedBreaks); // use normal lines, when possible lineLayouts.restorePossibilities(); - ipd = savedLineWidth; + iLineWidth = savedLineWidth; } //log.debug("LLM.getNextKnuthElements> now, layouts with more lines? " + lineLayouts.canUseMoreLines()); //log.debug(" now, layouts with fewer lines? " + lineLayouts.canUseLessLines()); @@ -937,14 +1115,15 @@ public class LineLayoutManager extends InlineStackingLayoutManager while (elementIterator.nextIndex() <= endIndex) { KnuthElement element = (KnuthElement) elementIterator.next(); if (element instanceof KnuthInlineBox - && ((KnuthInlineBox) element).isAnchor()) { + && ((KnuthInlineBox) element).isAnchor()) { footnoteList.add(((KnuthInlineBox) element).getFootnoteBodyLM()); } else if (element instanceof KnuthBlockBox) { footnoteList.addAll(((KnuthBlockBox) element).getFootnoteBodyLMs()); } } startIndex = endIndex + 1; - LineBreakPosition lbp = (LineBreakPosition) llPoss.getChosenPosition(i); + LineBreakPosition lbp + = (LineBreakPosition) llPoss.getChosenPosition(i); returnList.add(new KnuthBlockBox (lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter, footnoteList, lbp, false)); @@ -1418,7 +1597,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager Position pos = (Position) parentIter.next(); boolean isLastPosition = !parentIter.hasNext(); if (pos instanceof LineBreakPosition) { - addInlineArea(context, (LineBreakPosition) pos, isLastPosition); + addInlineArea(context, pos, isLastPosition); } else if ((pos instanceof NonLeafPosition) && pos.generatesAreas()) { addBlockArea(context, pos, isLastPosition); } else { @@ -1438,129 +1617,147 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param pos the position for which the line is generated * @param isLastPosition true if this is the last position of this LM */ - private void addInlineArea(LayoutContext context, LineBreakPosition lbp, - boolean isLastPosition) { - // the TLM which created the last KnuthElement in this line - LayoutManager lastLM = null; - - KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(lbp.parIndex); - int startElementIndex = lbp.startIndex; - int endElementIndex = lbp.getLeafPos(); - - LineArea lineArea = new LineArea( - (lbp.getLeafPos() < seq.size() - 1 ? textAlignment : textAlignmentLast), - lbp.difference, lbp.availableStretch, lbp.availableShrink); - if (lbp.startIndent != 0) { - lineArea.addTrait(Trait.START_INDENT, new Integer(lbp.startIndent)); - } - lineArea.setBPD(lbp.lineHeight); - lineArea.setIPD(lbp.lineWidth); - lineArea.addTrait(Trait.SPACE_BEFORE, new Integer(lbp.spaceBefore)); - lineArea.addTrait(Trait.SPACE_AFTER, new Integer(lbp.spaceAfter)); - alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline); - - if (seq instanceof Paragraph) { - Paragraph currPar = (Paragraph) seq; - // ignore the first elements added by the LineLayoutManager - startElementIndex += (startElementIndex == 0) ? currPar.ignoreAtStart : 0; - - // if this is the last line area that for this paragraph, - // ignore the last elements added by the LineLayoutManager and - // subtract the last-line-end-indent from the area ipd - if (endElementIndex == (currPar.size() - 1)) { - endElementIndex -= currPar.ignoreAtEnd; - lineArea.setIPD(lineArea.getIPD() - lastLineEndIndent.getValue(this)); + private void addInlineArea(LayoutContext context, Position pos, boolean isLastPosition) { + ListIterator seqIterator = null; + KnuthElement tempElement = null; + // the TLM which created the last KnuthElement in this line + LayoutManager lastLM = null; + + LineBreakPosition lbp = (LineBreakPosition) pos; + int iCurrParIndex; + iCurrParIndex = lbp.iParIndex; + KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(iCurrParIndex); + int iStartElement = lbp.iStartIndex; + int iEndElement = lbp.getLeafPos(); + + LineArea lineArea + = new LineArea((lbp.getLeafPos() < seq.size() - 1 + ? textAlignment : textAlignmentLast), + lbp.difference, lbp.availableStretch, lbp.availableShrink); + if (lbp.startIndent != 0) { + lineArea.addTrait(Trait.START_INDENT, new Integer(lbp.startIndent)); + } + lineArea.setBPD(lbp.lineHeight); + lineArea.setIPD(lbp.lineWidth); + lineArea.addTrait(Trait.SPACE_BEFORE, new Integer(lbp.spaceBefore)); + lineArea.addTrait(Trait.SPACE_AFTER, new Integer(lbp.spaceAfter)); + alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline); + + if (seq instanceof Paragraph) { + Paragraph currPar = (Paragraph) seq; + // ignore the first elements added by the LineLayoutManager + iStartElement += (iStartElement == 0) ? currPar.ignoreAtStart : 0; + + // if this is the last line area that for this paragraph, + // ignore the last elements added by the LineLayoutManager and + // subtract the last-line-end-indent from the area ipd + if (iEndElement == (currPar.size() - 1)) { + iEndElement -= currPar.ignoreAtEnd; + lineArea.setIPD(lineArea.getIPD() - lastLineEndIndent.getValue(this)); + } } - } - // Remove trailing spaces if allowed so - if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED + // Remove trailing spaces if allowed so + if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED || whiteSpaceTreament == EN_IGNORE || whiteSpaceTreament == EN_IGNORE_IF_BEFORE_LINEFEED) { - // ignore the last element in the line if it is a KnuthGlue object - ListIterator seqIterator = seq.listIterator(endElementIndex); - KnuthElement lastElement = (KnuthElement) seqIterator.next(); - lastLM = lastElement.getLayoutManager(); - if (lastElement.isGlue()) { - endElementIndex--; - // this returns the same KnuthElement - seqIterator.previous(); - if (seqIterator.hasPrevious()) { - lastLM = ((KnuthElement) seqIterator.previous()).getLayoutManager(); + // ignore the last element in the line if it is a KnuthGlue object + seqIterator = seq.listIterator(iEndElement); + tempElement = (KnuthElement) seqIterator.next(); + if (tempElement.isGlue()) { + iEndElement--; + // this returns the same KnuthElement + seqIterator.previous(); + if (seqIterator.hasPrevious()) { + tempElement = (KnuthElement) seqIterator.previous(); + } else { + tempElement = null; + } + } + if (tempElement != null) { + lastLM = tempElement.getLayoutManager(); } } - } - // Remove leading spaces if allowed so - if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED + // Remove leading spaces if allowed so + if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED || whiteSpaceTreament == EN_IGNORE || whiteSpaceTreament == EN_IGNORE_IF_AFTER_LINEFEED) { - // ignore KnuthGlue and KnuthPenalty objects - // at the beginning of the line - ListIterator seqIterator = seq.listIterator(startElementIndex); - while (seqIterator.hasNext() && !((KnuthElement) seqIterator.next()).isBox()) { - startElementIndex++; + // ignore KnuthGlue and KnuthPenalty objects + // at the beginning of the line + seqIterator = seq.listIterator(iStartElement); + tempElement = (KnuthElement) seqIterator.next(); + while (!tempElement.isBox() && seqIterator.hasNext()) { + tempElement = (KnuthElement) seqIterator.next(); + iStartElement++; + } } - } - // Add the inline areas to lineArea - PositionIterator inlinePosIter = new KnuthPossPosIter(seq, startElementIndex, - endElementIndex + 1); - - LayoutContext lc = new LayoutContext(0); - lc.setAlignmentContext(alignmentContext); - lc.setSpaceAdjust(lbp.dAdjust); - lc.setIPDAdjust(lbp.ipdAdjust); - lc.setLeadingSpace(new SpaceSpecifier(true)); - lc.setTrailingSpace(new SpaceSpecifier(false)); - lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true); - - /* - * extension (not in the XSL FO recommendation): if the left and right margins - * have been optimized, recompute indents and / or adjust ratio, according - * to the paragraph horizontal alignment - */ - if (false && textAlignment == EN_JUSTIFY) { - // re-compute space adjust ratio - int updatedDifference = context.getRefIPD() - - lbp.lineWidth + lbp.difference; - double updatedRatio = 0.0; - if (updatedDifference > 0) { - updatedRatio = (float) updatedDifference / lbp.availableStretch; - } else if (updatedDifference < 0) { - updatedRatio = (float) updatedDifference / lbp.availableShrink; + // Add the inline areas to lineArea + PositionIterator inlinePosIter + = new KnuthPossPosIter(seq, iStartElement, iEndElement + 1); + + iStartElement = lbp.getLeafPos() + 1; + if (iStartElement == seq.size()) { + // advance to next paragraph + iStartElement = 0; } - lc.setIPDAdjust(updatedRatio); - //log.debug("LLM.addAreas> old difference = " + lbp.difference + " new difference = " + updatedDifference); - //log.debug(" old ratio = " + lbp.ipdAdjust + " new ratio = " + updatedRatio); - } else if (false && textAlignment == EN_CENTER) { - // re-compute indent - int updatedIndent = lbp.startIndent - + (context.getRefIPD() - lbp.lineWidth) / 2; - lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); - } else if (false && textAlignment == EN_END) { - // re-compute indent - int updatedIndent = lbp.startIndent - + (context.getRefIPD() - lbp.lineWidth); - lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); - } - setCurrentArea(lineArea); - setChildContext(lc); - LayoutManager childLM; - while ((childLM = inlinePosIter.getNextChildLM()) != null) { - lc.setFlags(LayoutContext.LAST_AREA, (childLM == lastLM)); - childLM.addAreas(inlinePosIter, lc); - lc.setLeadingSpace(lc.getTrailingSpace()); + LayoutContext lc = new LayoutContext(0); + lc.setAlignmentContext(alignmentContext); + lc.setSpaceAdjust(lbp.dAdjust); + lc.setIPDAdjust(lbp.ipdAdjust); + lc.setLeadingSpace(new SpaceSpecifier(true)); lc.setTrailingSpace(new SpaceSpecifier(false)); - } + lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true); + + /* + * extension (not in the XSL FO recommendation): if the left and right margins + * have been optimized, recompute indents and / or adjust ratio, according + * to the paragraph horizontal alignment + */ + if (false && textAlignment == EN_JUSTIFY) { + // re-compute space adjust ratio + int updatedDifference = context.getStackLimitIP().opt + - lbp.lineWidth + lbp.difference; + double updatedRatio = 0.0; + if (updatedDifference > 0) { + updatedRatio = (float) updatedDifference / lbp.availableStretch; + } else if (updatedDifference < 0) { + updatedRatio = (float) updatedDifference / lbp.availableShrink; + } + lc.setIPDAdjust(updatedRatio); + //log.debug("LLM.addAreas> old difference = " + lbp.difference + " new difference = " + updatedDifference); + //log.debug(" old ratio = " + lbp.ipdAdjust + " new ratio = " + updatedRatio); + } else if (false && textAlignment == EN_CENTER) { + // re-compute indent + int updatedIndent = lbp.startIndent + + (context.getStackLimitIP().opt - lbp.lineWidth) / 2; + lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); + } else if (false && textAlignment == EN_END) { + // re-compute indent + int updatedIndent = lbp.startIndent + + (context.getStackLimitIP().opt - lbp.lineWidth); + lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent)); + } - // if display-align is distribute, add space after - if (context.getSpaceAfter() > 0 - && (!context.isLastArea() || !isLastPosition)) { - lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter()); - } - lineArea.finalise(); - parentLM.addChildArea(lineArea); + setCurrentArea(lineArea); + setChildContext(lc); + LayoutManager childLM; + while ((childLM = inlinePosIter.getNextChildLM()) != null) { + lc.setFlags(LayoutContext.LAST_AREA, (childLM == lastLM)); + childLM.addAreas(inlinePosIter, lc); + lc.setLeadingSpace(lc.getTrailingSpace()); + lc.setTrailingSpace(new SpaceSpecifier(false)); + } + + // when can this be null? + // if display-align is distribute, add space after + if (context.getSpaceAfter() > 0 + && (!context.isLastArea() || !isLastPosition)) { + lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter()); + } + lineArea.finalise(); + parentLM.addChildArea(lineArea); } /** @@ -1603,7 +1800,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager // set last area flag blocklc.setFlags(LayoutContext.LAST_AREA, (context.isLastArea() && childLM == lastLM)); - blocklc.setStackLimitBP(context.getStackLimitBP()); + blocklc.setStackLimitsFrom(context); // Add the line areas to Area childLM.addAreas(childPosIter, blocklc); blocklc.setLeadingSpace(blocklc.getTrailingSpace()); |