From f1269cc280b846cd6da396177bc74c4c9808579e Mon Sep 17 00:00:00 2001 From: "Andreas L. Delmelle" Date: Wed, 9 Feb 2011 22:45:16 +0000 Subject: [PATCH] Further attempts at improving code readability, reduce some more duplication, and move logic to where it is appropriate git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1069154 13f79535-47bb-0310-9956-ffa450edef68 --- .../BlockContainerLayoutManager.java | 173 +++++++++--------- .../fop/layoutmgr/BlockLayoutManager.java | 36 ++++ .../layoutmgr/BlockStackingLayoutManager.java | 91 +++++---- .../fop/layoutmgr/FlowLayoutManager.java | 24 ++- 4 files changed, 203 insertions(+), 121 deletions(-) diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 134755a8d..34403a956 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -86,6 +86,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager private MinOptMax effSpaceBefore; private MinOptMax effSpaceAfter; + private double contentRectOffsetX = 0; + private double contentRectOffsetY = 0; /** * Create a new block container layout manager. @@ -183,67 +185,36 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return getNextKnuthElements(context, alignment, null, null, null); } + /** + * Overridden to handle writing-mode, and different stack limit + * setup. + * {@inheritDoc} + */ + @Override + protected LayoutContext makeChildLayoutContext(LayoutContext context) { + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimitBP( + context.getStackLimitBP().minus(MinOptMax.getInstance(relDims.bpd))); + childLC.setRefIPD(relDims.ipd); + childLC.setWritingMode(getBlockContainerFO().getWritingMode()); + return childLC; + } + /** {@inheritDoc} */ - @Override // CSOK: MethodLength - public List getNextKnuthElements - (LayoutContext context, int alignment, Stack lmStack, - Position restartPosition, LayoutManager restartAtLM) { + @Override + public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack, + Position restartPosition, LayoutManager restartAtLM) { resetSpaces(); + // special treatment for position="absolute|fixed" if (isAbsoluteOrFixed()) { return getNextKnuthElementsAbsolute(context); } boolean isRestart = (lmStack != null); boolean emptyStack = (!isRestart || lmStack.isEmpty()); - BlockContainer fo = getBlockContainerFO(); - - autoHeight = false; - //boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); - int maxbpd = context.getStackLimitBP().getOpt(); - int allocBPD; - if (height.getEnum() == EN_AUTO - || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { - //auto height when height="auto" or "if that dimension is not specified explicitly - //(i.e., it depends on content's block-progression-dimension)" (XSL 1.0, 7.14.1) - allocBPD = maxbpd; - autoHeight = true; - if (fo.getReferenceOrientation() == 0) { - //Cannot easily inline element list when ref-or="180" - inlineElementList = true; - } - } else { - allocBPD = height.getValue(this); //this is the content-height - allocBPD += getBPIndents(); - } - vpContentBPD = allocBPD - getBPIndents(); - - referenceIPD = context.getRefIPD(); - if (width.getEnum() == EN_AUTO) { - updateContentAreaIPDwithOverconstrainedAdjust(); - } else { - int contentWidth = width.getValue(this); - updateContentAreaIPDwithOverconstrainedAdjust(contentWidth); - } - - double contentRectOffsetX = 0; - contentRectOffsetX += fo.getCommonMarginBlock().startIndent.getValue(this); - double contentRectOffsetY = 0; - contentRectOffsetY += fo.getCommonBorderPaddingBackground().getBorderBeforeWidth(false); - contentRectOffsetY += fo.getCommonBorderPaddingBackground().getPaddingBefore(false, this); - - updateRelDims(contentRectOffsetX, contentRectOffsetY, autoHeight); - - int availableIPD = referenceIPD - getIPIndents(); - if (getContentAreaIPD() > availableIPD) { - BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( - fo.getUserAgent().getEventBroadcaster()); - eventProducer.objectTooWide(this, fo.getName(), - getContentAreaIPD(), context.getRefIPD(), - fo.getLocator()); - } - MinOptMax stackLimit = MinOptMax.getInstance(relDims.bpd); + setupAreaDimensions(context); List returnedList; List contentList = new LinkedList(); @@ -256,14 +227,12 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager addFirstVisibleMarks(returnList, context, alignment); if (autoHeight && inlineElementList) { - //Spaces, border and padding to be repeated at each break - addPendingMarks(context); LayoutManager curLM; // currently active LM LayoutManager prevLM = null; // previously active LM LayoutContext childLC; - boolean doReset = true; + boolean doReset = isRestart; if (isRestart) { if (emptyStack) { assert restartAtLM != null && restartAtLM.getParent() == this; @@ -282,21 +251,15 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (doReset) { curLM.reset(); } - childLC = new LayoutContext(0); - childLC.copyPendingMarksFrom(context); - childLC.setStackLimitBP(context.getStackLimitBP().minus(stackLimit)); - childLC.setRefIPD(relDims.ipd); - childLC.setWritingMode(fo.getWritingMode()); - if (curLM == this.childLMs.get(0)) { - childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); - //Handled already by the parent (break collapsing, see above) - } + + childLC = makeChildLayoutContext(context); // get elements from curLM if (!isRestart || emptyStack) { - returnedList = curLM.getNextKnuthElements(childLC, alignment); + returnedList = getNextChildElements(curLM, context, childLC, alignment, + null, null, null); } else { - returnedList = curLM.getNextKnuthElements(childLC, alignment, + returnedList = getNextChildElements(curLM, context, childLC, alignment, lmStack, restartPosition, restartAtLM); // once encountered, irrelevant for following child LMs emptyStack = true; @@ -338,7 +301,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } wrapPositionElements(contentList, returnList); - return returnList; } } @@ -350,13 +312,11 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } wrapPositionElements(contentList, returnList); } else { - returnList.add(generateNonInlinedBox(contentRectOffsetX, contentRectOffsetY)); + returnList.add(generateNonInlinedBox()); } - addKnuthElementsForBorderPaddingAfter(returnList, true); - addKnuthElementsForSpaceAfter(returnList, alignment); - //All child content is processed. Only break-after can occur now, so... - context.clearPendingMarks(); + addLastVisibleMarks(returnList, context, alignment); + addKnuthElementsForBreakAfter(returnList, context); context.updateKeepWithNextPending(getKeepWithNext()); @@ -365,8 +325,50 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return returnList; } - private KnuthBox generateNonInlinedBox(double contentRectOffsetX, - double contentRectOffsetY) { + private void setupAreaDimensions(LayoutContext context) { + autoHeight = false; + int maxbpd = context.getStackLimitBP().getOpt(); + int allocBPD; + BlockContainer fo = getBlockContainerFO(); + if (height.getEnum() == EN_AUTO + || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { + //auto height when height="auto" or "if that dimension is not specified explicitly + //(i.e., it depends on content's block-progression-dimension)" (XSL 1.0, 7.14.1) + allocBPD = maxbpd; + autoHeight = true; + //Cannot easily inline element list when ref-or<>"0" + inlineElementList = (fo.getReferenceOrientation() == 0); + } else { + allocBPD = height.getValue(this); //this is the content-height + allocBPD += getBPIndents(); + } + vpContentBPD = allocBPD - getBPIndents(); + + referenceIPD = context.getRefIPD(); + if (width.getEnum() == EN_AUTO) { + updateContentAreaIPDwithOverconstrainedAdjust(); + } else { + int contentWidth = width.getValue(this); + updateContentAreaIPDwithOverconstrainedAdjust(contentWidth); + } + + contentRectOffsetX += fo.getCommonMarginBlock().startIndent.getValue(this); + contentRectOffsetY += fo.getCommonBorderPaddingBackground().getBorderBeforeWidth(false); + contentRectOffsetY += fo.getCommonBorderPaddingBackground().getPaddingBefore(false, this); + + updateRelDims(); + + int availableIPD = referenceIPD - getIPIndents(); + if (getContentAreaIPD() > availableIPD) { + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + fo.getUserAgent().getEventBroadcaster()); + eventProducer.objectTooWide(this, fo.getName(), + getContentAreaIPD(), context.getRefIPD(), + fo.getLocator()); + } + } + + private KnuthBox generateNonInlinedBox() { MinOptMax range = MinOptMax.getInstance(relDims.ipd); BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); @@ -380,7 +382,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } else { vpContentBPD = newHeight; } - updateRelDims(contentRectOffsetX, contentRectOffsetY, false); + updateRelDims(); } Position bcPosition = new BlockContainerPosition(this, breaker); @@ -414,7 +416,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return true; } - private List getNextKnuthElementsAbsolute(LayoutContext context) { + private List getNextKnuthElementsAbsolute(LayoutContext context) { autoHeight = false; boolean bpDirectionChanges = blockProgressionDirectionChanges(); @@ -520,7 +522,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager vpContentBPD = allocBPD - getBPIndents(); setContentAreaIPD(allocIPD - getIPIndents()); - updateRelDims(0, 0, autoHeight); + contentRectOffsetX = 0; + contentRectOffsetY = 0; + updateRelDims(); MinOptMax range = MinOptMax.getInstance(relDims.ipd); BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); @@ -534,9 +538,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } else { vpContentBPD = newHeight; } - updateRelDims(0, 0, false); + updateRelDims(); } - List returnList = new LinkedList(); + List returnList = new LinkedList(); if (!breaker.isEmpty()) { Position bcPosition = new BlockContainerPosition(this, breaker); returnList.add(new KnuthBox(0, notifyPos(bcPosition), false)); @@ -556,9 +560,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return returnList; } - private void updateRelDims(double xOffset, double yOffset, boolean skipAutoHeight) { + private void updateRelDims() { Rectangle2D rect = new Rectangle2D.Double( - xOffset, yOffset, + contentRectOffsetX, contentRectOffsetY, getContentAreaIPD(), this.vpContentBPD); relDims = new FODimension(0, 0); @@ -616,7 +620,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } public int getDifferenceOfFirstPart() { - PageBreakPosition pbp = (PageBreakPosition)this.deferredAlg.getPageBreaks().getFirst(); + PageBreakPosition pbp = this.deferredAlg.getPageBreaks().getFirst(); return pbp.difference; } @@ -645,13 +649,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager protected List getNextKnuthElements(LayoutContext context, int alignment) { LayoutManager curLM; // currently active LM - List returnList = new LinkedList(); + List returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { - LayoutContext childLC = new LayoutContext(0); - childLC.setStackLimitBP(context.getStackLimitBP()); - childLC.setRefIPD(context.getRefIPD()); - childLC.setWritingMode(getBlockContainerFO().getWritingMode()); + LayoutContext childLC = makeChildLayoutContext(context); List returnedList = null; if (!curLM.isFinished()) { diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 45036b36e..55c5cfd66 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -114,6 +114,42 @@ public class BlockLayoutManager extends BlockStackingLayoutManager context, alignment, lmStack, restartPosition, restartAtLM); } + /** + * Overridden to take into account that the childLM may be the block's + * {@link LineLayoutManager}. + * {@inheritDoc} + */ + @Override + protected List getNextChildElements(LayoutManager childLM, LayoutContext context, + LayoutContext childLC, int alignment, Stack lmStack, Position restartPosition, + LayoutManager restartAtLM) { + + childLC.copyPendingMarksFrom(context); + + if (childLM instanceof LineLayoutManager) { + childLC.setRefIPD(getContentAreaIPD()); + } else { + // nop; will have been properly set by makeChildLayoutContext() + } + + if (childLM == this.childLMs.get(0)) { + childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); + //Handled already by the parent (break collapsing, see above) + } + + if (lmStack == null) { + return childLM.getNextKnuthElements(childLC, alignment); + } else { + if (childLM instanceof LineLayoutManager) { + return ((LineLayoutManager) childLM).getNextKnuthElements(childLC, alignment, + (LeafPosition) restartPosition); + } else { + return childLM.getNextKnuthElements(childLC, alignment, + lmStack, restartPosition, restartAtLM); + } + } + } + private void resetSpaces() { this.discardBorderBefore = false; this.discardBorderAfter = false; diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index ca2f69fb2..f5cb983b2 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -38,7 +37,6 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.SpaceProperty; import org.apache.fop.layoutmgr.inline.InlineLayoutManager; -import org.apache.fop.layoutmgr.inline.LineLayoutManager; import org.apache.fop.traits.MinOptMax; import org.apache.fop.util.BreakUtil; import org.apache.fop.util.ListUtil; @@ -261,9 +259,6 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager addFirstVisibleMarks(elements, context, alignment); - //Spaces, border and padding to be repeated at each break - addPendingMarks(context); - //Used to indicate a special break-after case when all content has already been generated. BreakElement forcedBreakAfterLast = null; @@ -291,7 +286,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager currentChildLM.reset(); // TODO won't work with forced breaks } - childLC = new LayoutContext(0); + childLC = makeChildLayoutContext(context); if (!isRestart || emptyStack) { childElements = getNextChildElements(currentChildLM, context, childLC, alignment, @@ -374,11 +369,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager wrapPositionElements(contentList, elements); } - addKnuthElementsForBorderPaddingAfter(elements, true); - addKnuthElementsForSpaceAfter(elements, alignment); + addLastVisibleMarks(elements, context, alignment); - // All child content processed. Only break-after can occur now, so... - context.clearPendingMarks(); if (forcedBreakAfterLast == null) { addKnuthElementsForBreakAfter(elements, context); } else { @@ -391,22 +383,54 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager return elements; } + /** + * Creates and initializes a {@link LayoutContext} to pass to the child LM + * @param context the parent {@link LayoutContext} + * @return a new child layout context + */ + protected LayoutContext makeChildLayoutContext(LayoutContext context) { + LayoutContext childLC = new LayoutContext(0); + childLC.copyPendingMarksFrom(context); + childLC.setStackLimitBP(context.getStackLimitBP()); + childLC.setRefIPD(referenceIPD); + return childLC; + } + /** * Checks if this LM's first "visible marks" (= borders, padding, spaces) have * already been processed, and if necessary, adds corresponding elements to - * the specified list. + * the specified list, and updates the given layout context accordingly. * @param elements the element list * @param context the layout context * @param alignment the vertical alignment */ protected void addFirstVisibleMarks(List elements, - LayoutContext context, int alignment) { + LayoutContext context, int alignment) { if (!firstVisibleMarkServed) { addKnuthElementsForSpaceBefore(elements, alignment); context.updateKeepWithPreviousPending(getKeepWithPrevious()); } addKnuthElementsForBorderPaddingBefore(elements, !firstVisibleMarkServed); firstVisibleMarkServed = true; + + //Spaces, border and padding to be repeated at each break + addPendingMarks(context); + } + + /** + * Adds elements the LM's last/closing marks to the specified list, and + * updates the layout context accordingly. + * @param elements the element list + * @param context the layout context + * @param alignment the vertical alignment + */ + protected void addLastVisibleMarks(List elements, + LayoutContext context, int alignment) { + addKnuthElementsForBorderPaddingAfter(elements, true); + addKnuthElementsForSpaceAfter(elements, alignment); + + // All child content processed. Only break-after can occur now, so... + context.clearPendingMarks(); } /** @@ -450,31 +474,36 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager isAuxiliary); } - private List getNextChildElements(LayoutManager childLM, LayoutContext context, - LayoutContext childLC, int alignment, Stack lmStack, Position restartPosition, - LayoutManager restartAtLM) { - childLC.copyPendingMarksFrom(context); - childLC.setStackLimitBP(context.getStackLimitBP()); - if (childLM instanceof LineLayoutManager) { - childLC.setRefIPD(getContentAreaIPD()); - } else { - childLC.setRefIPD(referenceIPD); - } + /** + * Gets the next set of child elements for the given childLM. + * The default implementation basically copies the pending marks to the child layout context, + * and subsequently calls the appropriate variant of {@code childLM.getNextKnuthElements()}, + * passing it all relevant parameters. + * @param childLM the current child LM + * @param context the layout context + * @param childLC the child layout context + * @param alignment the vertical alignment + * @param lmStack the stack of currently active LMs (if any) + * @param restartPosition the position to restart from (if any) + * @param restartAtLM the LM to restart from (if any) + * @return list of elements corresponding to the content generated by childLM + */ + protected List getNextChildElements(LayoutManager childLM, LayoutContext context, + LayoutContext childLC, int alignment, Stack lmStack, + Position restartPosition, LayoutManager restartAtLM) { + if (childLM == this.childLMs.get(0)) { childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); //Handled already by the parent (break collapsing, see above) } if (lmStack == null) { + // route to default implementation, in case childLM does not provide + // an override similar to this class return childLM.getNextKnuthElements(childLC, alignment); } else { - if (childLM instanceof LineLayoutManager) { - return ((LineLayoutManager) childLM).getNextKnuthElements(childLC, alignment, - (LeafPosition) restartPosition); - } else { - return childLM.getNextKnuthElements(childLC, alignment, - lmStack, restartPosition, restartAtLM); - } + return childLM.getNextKnuthElements(childLC, alignment, lmStack, + restartPosition, restartAtLM); } } @@ -908,7 +937,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } /** @return the space-before property */ - private SpaceProperty getSpaceBeforeProperty() { + protected SpaceProperty getSpaceBeforeProperty() { if (fobj instanceof org.apache.fop.fo.flow.Block) { return ((org.apache.fop.fo.flow.Block)fobj) .getCommonMarginBlock().spaceBefore; @@ -930,7 +959,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } /** @return the space-after property */ - private SpaceProperty getSpaceAfterProperty() { + protected SpaceProperty getSpaceAfterProperty() { if (fobj instanceof org.apache.fop.fo.flow.Block) { return ((org.apache.fop.fo.flow.Block)fobj) .getCommonMarginBlock().spaceAfter; diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 6b1038c1f..5357565a7 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -141,7 +141,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager return elements; } - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = makeChildLayoutContext(context); List childElements = getNextChildElements(childLM, context, childLC, alignment, lmStack, position, restartAtLM); @@ -193,13 +193,29 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } } - private List getNextChildElements(LayoutManager childLM, LayoutContext context, - LayoutContext childLC, int alignment, Stack lmStack, - Position restartPosition, LayoutManager restartLM) { + /** + * Overridden to take into account the current page-master's + * writing-mode + * {@inheritDoc} + */ + @Override + protected LayoutContext makeChildLayoutContext(LayoutContext context) { + LayoutContext childLC = new LayoutContext(0); childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode()); + return childLC; + } + /** + * Overridden to wrap the child positions before returning the list + * {@inheritDoc} + */ + @Override + protected List getNextChildElements(LayoutManager childLM, LayoutContext context, + LayoutContext childLC, int alignment, Stack lmStack, + Position restartPosition, LayoutManager restartLM) { + List childElements; if (lmStack == null) { childElements = childLM.getNextKnuthElements(childLC, alignment); -- 2.39.5