diff options
author | Vincent Hennebert <vhennebert@apache.org> | 2009-12-22 17:20:51 +0000 |
---|---|---|
committer | Vincent Hennebert <vhennebert@apache.org> | 2009-12-22 17:20:51 +0000 |
commit | 37b744039a701d5aafd44997a195c696261d3fea (patch) | |
tree | 504f0326b76734cf106ece1b67cf2fca8fd48ac3 | |
parent | a0f281543e947da203e9cfd5cb3559e32912beb4 (diff) | |
download | xmlgraphics-fop-37b744039a701d5aafd44997a195c696261d3fea.tar.gz xmlgraphics-fop-37b744039a701d5aafd44997a195c696261d3fea.zip |
Bugzilla #48071: made the MinOptMax class immutable. Also, lots of clean ups and minor refactorings.
Patch submitted by Alexander Kiel.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@893238 13f79535-47bb-0310-9956-ffa450edef68
52 files changed, 1746 insertions, 1521 deletions
diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index 87ba2146a..ddf2f5198 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -119,7 +119,7 @@ public class Area extends AreaTreeObject implements Serializable { public static final int CLASS_MAX = CLASS_SIDE_FLOAT + 1; private int areaClass = CLASS_NORMAL; - + /** the area's inline-progression-dimension */ protected int ipd; @@ -174,18 +174,18 @@ public class Area extends AreaTreeObject implements Serializable { * @see <a href="http://www.w3.org/TR/xsl/#inline-progression-dimension">ipd</a> */ public int getIPD() { - return this.ipd; + return ipd; } /** * Set the block progression dimension of the content rectangle * for this area. * - * @param b the new block progression dimension + * @param bpd the new block progression dimension * @see <a href="http://www.w3.org/TR/xsl/#block-progression-dimension">bpd</a> */ - public void setBPD(int b) { - bpd = b; + public void setBPD(int bpd) { + this.bpd = bpd; } /** diff --git a/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java b/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java index 3161fc517..d8e8ee272 100644 --- a/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java +++ b/src/java/org/apache/fop/fo/properties/LengthRangeProperty.java @@ -25,6 +25,7 @@ import org.apache.fop.datatypes.PercentBaseContext; import org.apache.fop.fo.FObj; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; +import org.apache.fop.traits.MinOptMax; /** * Superclass for properties that contain LengthRange values @@ -40,6 +41,22 @@ public class LengthRangeProperty extends Property implements CompoundDatatype { private boolean consistent = false; /** + * Converts this <code>LengthRangeProperty</code> to a <code>MinOptMax</code>. + * + * @param context Percentage evaluation context + * @return the requested MinOptMax instance + */ + public MinOptMax toMinOptMax(PercentBaseContext context) { + int min = getMinimum(context).isAuto() ? 0 + : getMinimum(context).getLength().getValue(context); + int opt = getOptimum(context).isAuto() ? min + : getOptimum(context).getLength().getValue(context); + int max = getMaximum(context).isAuto() ? Integer.MAX_VALUE + : getMaximum(context).getLength().getValue(context); + return MinOptMax.getInstance(min, opt, max); + } + + /** * Inner class for a Maker for LengthProperty objects */ public static class Maker extends CompoundPropertyMaker { diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index a58f5523b..db0edb42c 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -201,7 +201,7 @@ public abstract class AbstractBreaker { protected int alignment; private int alignmentLast; - protected MinOptMax footnoteSeparatorLength = new MinOptMax(0); + protected MinOptMax footnoteSeparatorLength = MinOptMax.ZERO; protected abstract int getCurrentDisplayAlign(); protected abstract boolean hasMoreContent(); @@ -307,7 +307,7 @@ public abstract class AbstractBreaker { */ public void doLayout(int flowBPD, boolean autoHeight) { LayoutContext childLC = createLayoutContext(); - childLC.setStackLimitBP(new MinOptMax(flowBPD)); + childLC.setStackLimitBP(MinOptMax.getInstance(flowBPD)); if (getCurrentDisplayAlign() == Constants.EN_X_FILL) { //EN_X_FILL is non-standard (by LF) @@ -613,7 +613,7 @@ public abstract class AbstractBreaker { int averageLineLength = optimizeLineLength(effectiveList, startElementIndex, endElementIndex); if (averageLineLength != 0) { - childLC.setStackLimitBP(new MinOptMax(averageLineLength)); + childLC.setStackLimitBP(MinOptMax.getInstance(averageLineLength)); } } /* *** *** non-standard extension *** *** */ @@ -762,7 +762,8 @@ public abstract class AbstractBreaker { * @param endElementIndex index of the element ending the range * @return the average line length, 0 if there's no content */ - private int optimizeLineLength(KnuthSequence effectiveList, int startElementIndex, int endElementIndex) { + private int optimizeLineLength(KnuthSequence effectiveList, int startElementIndex, + int endElementIndex) { ListIterator effectiveListIterator; // optimize line length int boxCount = 0; @@ -783,9 +784,9 @@ public abstract class AbstractBreaker { accumulatedLineLength += ((KnuthBlockBox) tempEl) .getBPD(); } - if (blockBox.getIPDRange().min > greatestMinimumLength) { + if (blockBox.getIPDRange().getMin() > greatestMinimumLength) { greatestMinimumLength = blockBox - .getIPDRange().min; + .getIPDRange().getMin(); } } } @@ -808,7 +809,8 @@ public abstract class AbstractBreaker { * @param availableBPD the available BPD * @return the effective list */ - private BlockSequence justifyBoxes(BlockSequence blockList, PageBreakingAlgorithm alg, int availableBPD) { + private BlockSequence justifyBoxes(BlockSequence blockList, PageBreakingAlgorithm alg, + int availableBPD) { int iOptPageNumber; alg.setConstantLineWidth(availableBPD); iOptPageNumber = alg.findBreakingPoints(blockList, /*availableBPD,*/ @@ -857,8 +859,8 @@ public abstract class AbstractBreaker { // scan the sub-sequence representing a page, // collecting information about potential adjustments - MinOptMax lineNumberMaxAdjustment = new MinOptMax(0); - MinOptMax spaceMaxAdjustment = new MinOptMax(0); + MinOptMax lineNumberMaxAdjustment = MinOptMax.ZERO; + MinOptMax spaceMaxAdjustment = MinOptMax.ZERO; double spaceAdjustmentRatio = 0.0; LinkedList blockSpacesList = new LinkedList(); LinkedList unconfirmedList = new LinkedList(); @@ -872,30 +874,23 @@ public abstract class AbstractBreaker { // glue elements are used to represent adjustable // lines // and adjustable spaces between blocks - switch (((KnuthGlue) thisElement) - .getAdjustmentClass()) { - case BlockLevelLayoutManager.SPACE_BEFORE_ADJUSTMENT: - // fall through - case BlockLevelLayoutManager.SPACE_AFTER_ADJUSTMENT: + Adjustment adjustment = ((KnuthGlue) thisElement).getAdjustmentClass(); + if (adjustment.equals(Adjustment.SPACE_BEFORE_ADJUSTMENT) + || adjustment.equals(Adjustment.SPACE_AFTER_ADJUSTMENT)) { // potential space adjustment // glue items before the first box or after the // last one // must be ignored unconfirmedList.add(thisElement); - break; - case BlockLevelLayoutManager.LINE_NUMBER_ADJUSTMENT: + } else if (adjustment.equals(Adjustment.LINE_NUMBER_ADJUSTMENT)) { // potential line number adjustment - lineNumberMaxAdjustment.max += ((KnuthGlue) thisElement) - .getStretch(); - lineNumberMaxAdjustment.min -= ((KnuthGlue) thisElement) - .getShrink(); + lineNumberMaxAdjustment + = lineNumberMaxAdjustment.plusMax(thisElement.getStretch()); + lineNumberMaxAdjustment + = lineNumberMaxAdjustment.minusMin(thisElement.getShrink()); adjustableLinesList.add(thisElement); - break; - case BlockLevelLayoutManager.LINE_HEIGHT_ADJUSTMENT: + } else if (adjustment.equals(Adjustment.LINE_HEIGHT_ADJUSTMENT)) { // potential line height adjustment - break; - default: - // nothing } } else if (thisElement.isBox()) { if (!bBoxSeen) { @@ -909,10 +904,8 @@ public abstract class AbstractBreaker { // blockSpaceList KnuthGlue blockSpace = (KnuthGlue) unconfirmedList .removeFirst(); - spaceMaxAdjustment.max += ((KnuthGlue) blockSpace) - .getStretch(); - spaceMaxAdjustment.min -= ((KnuthGlue) blockSpace) - .getShrink(); + spaceMaxAdjustment = spaceMaxAdjustment.plusMax(blockSpace.getStretch()); + spaceMaxAdjustment = spaceMaxAdjustment.minusMin(blockSpace.getShrink()); blockSpacesList.add(blockSpace); } } @@ -931,16 +924,19 @@ public abstract class AbstractBreaker { } if (thisBreak.bpdAdjust != 0 - && (thisBreak.difference > 0 && thisBreak.difference <= spaceMaxAdjustment.max) - || (thisBreak.difference < 0 && thisBreak.difference >= spaceMaxAdjustment.min)) { + && (thisBreak.difference > 0 && thisBreak.difference <= spaceMaxAdjustment + .getMax()) + || (thisBreak.difference < 0 && thisBreak.difference >= spaceMaxAdjustment + .getMin())) { // modify only the spaces between blocks - spaceAdjustmentRatio = ((double) thisBreak.difference / (thisBreak.difference > 0 ? spaceMaxAdjustment.max - : spaceMaxAdjustment.min)); + spaceAdjustmentRatio = ((double) thisBreak.difference / (thisBreak.difference > 0 + ? spaceMaxAdjustment.getMax() + : spaceMaxAdjustment.getMin())); adjustedDiff += adjustBlockSpaces( blockSpacesList, thisBreak.difference, - (thisBreak.difference > 0 ? spaceMaxAdjustment.max - : -spaceMaxAdjustment.min)); + (thisBreak.difference > 0 ? spaceMaxAdjustment.getMax() + : -spaceMaxAdjustment.getMin())); log.debug("single space: " + (adjustedDiff == thisBreak.difference || thisBreak.bpdAdjust == 0 ? "ok" @@ -949,13 +945,13 @@ public abstract class AbstractBreaker { adjustedDiff += adjustLineNumbers( adjustableLinesList, thisBreak.difference, - (thisBreak.difference > 0 ? lineNumberMaxAdjustment.max - : -lineNumberMaxAdjustment.min)); + (thisBreak.difference > 0 ? lineNumberMaxAdjustment.getMax() + : -lineNumberMaxAdjustment.getMin())); adjustedDiff += adjustBlockSpaces( blockSpacesList, thisBreak.difference - adjustedDiff, - ((thisBreak.difference - adjustedDiff) > 0 ? spaceMaxAdjustment.max - : -spaceMaxAdjustment.min)); + ((thisBreak.difference - adjustedDiff) > 0 ? spaceMaxAdjustment.getMax() + : -spaceMaxAdjustment.getMin())); log.debug("lines and space: " + (adjustedDiff == thisBreak.difference || thisBreak.bpdAdjust == 0 ? "ok" diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java index e6a5bea5e..1f91cef1a 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java @@ -48,7 +48,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager private static Log log = LogFactory.getLog(AbstractLayoutManager.class); /** Parent LayoutManager for this LayoutManager */ - protected LayoutManager parentLM; + protected LayoutManager parentLayoutManager; /** List of child LayoutManagers */ protected List childLMs; /** Iterator for child LayoutManagers */ @@ -91,12 +91,12 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** {@inheritDoc} */ public void setParent(LayoutManager lm) { - this.parentLM = lm; + this.parentLayoutManager = lm; } /** {@inheritDoc} */ public LayoutManager getParent() { - return this.parentLM; + return this.parentLayoutManager; } /** {@inheritDoc} */ @@ -230,7 +230,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager /** {@inheritDoc} */ public PageSequenceLayoutManager getPSLM() { - return parentLM.getPSLM(); + return parentLayoutManager.getPSLM(); } /** @@ -442,7 +442,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager * LM is a descendant of the FlowLM. For static-content * the FO may still be needed on following pages. */ - LayoutManager lm = this.parentLM; + LayoutManager lm = this.parentLayoutManager; while (!(lm instanceof FlowLayoutManager || lm instanceof PageSequenceLayoutManager)) { lm = lm.getParent(); diff --git a/src/java/org/apache/fop/layoutmgr/Adjustment.java b/src/java/org/apache/fop/layoutmgr/Adjustment.java new file mode 100644 index 000000000..0a96fb2c1 --- /dev/null +++ b/src/java/org/apache/fop/layoutmgr/Adjustment.java @@ -0,0 +1,73 @@ +/* + * 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; + +/** + * @see KnuthGlue + * @see "http://www.leverkruid.eu/GKPLinebreaking/elements.html" + */ +public final class Adjustment { + + /** + * Adjustment class: no adjustment. + */ + public static final Adjustment NO_ADJUSTMENT = new Adjustment("none"); + + /** + * Adjustment class: adjustment for space-before. + */ + public static final Adjustment SPACE_BEFORE_ADJUSTMENT = new Adjustment("space-before"); + + /** + * Adjustment class: adjustment for space-after. + */ + public static final Adjustment SPACE_AFTER_ADJUSTMENT = new Adjustment("space-after"); + + /** + * Adjustment class: adjustment for number of lines. + */ + public static final Adjustment LINE_NUMBER_ADJUSTMENT = new Adjustment("line-number"); + + /** + * Adjustment class: adjustment for line height. + */ + public static final Adjustment LINE_HEIGHT_ADJUSTMENT = new Adjustment("line-height"); + + private final String name; + + private Adjustment(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + return this == obj; + } + + /** {@inheritDoc} */ + public int hashCode() { + return super.hashCode(); + } + + /** {@inheritDoc} */ + public String toString() { + return name; + } +} diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index 3378d86d7..5ca2b567f 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -107,8 +107,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager startIndent = getBlockContainerFO().getCommonMarginBlock().startIndent.getValue(this); endIndent = getBlockContainerFO().getCommonMarginBlock().endIndent.getValue(this); - boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); - if (rotated) { + if (blockProgressionDirectionChanges()) { height = getBlockContainerFO().getInlineProgressionDimension() .getOptimum(this).getLength(); width = getBlockContainerFO().getBlockProgressionDimension() @@ -156,10 +155,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return (overflow == EN_HIDDEN || overflow == EN_ERROR_IF_OVERFLOW); } - private int getSpaceBefore() { - return foBlockSpaceBefore.opt; - } - private int getBPIndents() { int indents = 0; /* TODO This is wrong isn't it? @@ -200,7 +195,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager autoHeight = false; //boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); - int maxbpd = context.getStackLimitBP().opt; + int maxbpd = context.getStackLimitBP().getOpt(); int allocBPD; if (height.getEnum() == EN_AUTO || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { @@ -246,7 +241,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager getBlockContainerFO().getLocator()); } - MinOptMax stackLimit = new MinOptMax(relDims.bpd); + MinOptMax stackLimit = MinOptMax.getInstance(relDims.bpd); List returnedList; List contentList = new LinkedList(); @@ -279,7 +274,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager LayoutContext childLC = new LayoutContext(0); childLC.copyPendingMarksFrom(context); // curLM is a ? - childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit)); + childLC.setStackLimitBP(context.getStackLimitBP().minus(stackLimit)); childLC.setRefIPD(relDims.ipd); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); if (curLM == this.childLMs.get(0)) { @@ -349,41 +344,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager wrapPositionElements(contentList, returnList); } else { - MinOptMax range = new MinOptMax(relDims.ipd); - BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); - breaker.doLayout(relDims.bpd, autoHeight); - boolean contentOverflows = breaker.isOverflow(); - if (autoHeight) { - //Update content BPD now that it is known - int newHeight = breaker.deferredAlg.totalWidth; - boolean switchedProgressionDirection - = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); - if (switchedProgressionDirection) { - setContentAreaIPD(newHeight); - } else { - vpContentBPD = newHeight; - } - updateRelDims(contentRectOffsetX, contentRectOffsetY, false); - } - - Position bcPosition = new BlockContainerPosition(this, breaker); - returnList.add(new KnuthBox(vpContentBPD, notifyPos(bcPosition), false)); - //TODO Handle min/opt/max for block-progression-dimension - /* These two elements will be used to add stretchability to the above box - returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, - false, returnPosition, false)); - returnList.add(new KnuthGlue(0, 1 * constantLineHeight, 0, - LINE_NUMBER_ADJUSTMENT, returnPosition, false)); - */ - - if (contentOverflows) { - BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( - getBlockContainerFO().getUserAgent().getEventBroadcaster()); - boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW); - eventProducer.viewportOverflow(this, getBlockContainerFO().getName(), - breaker.getOverflowAmount(), needClip(), canRecover, - getBlockContainerFO().getLocator()); - } + returnList.add(refactoredBecauseOfDuplicateCode(contentRectOffsetX, + contentRectOffsetY)); } addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); @@ -398,6 +360,49 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager return returnList; } + private KnuthBox refactoredBecauseOfDuplicateCode(double contentRectOffsetX, + double contentRectOffsetY) { + + MinOptMax range = MinOptMax.getInstance(relDims.ipd); + BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); + breaker.doLayout(relDims.bpd, autoHeight); + boolean contentOverflows = breaker.isOverflow(); + if (autoHeight) { + //Update content BPD now that it is known + int newHeight = breaker.deferredAlg.totalWidth; + if (blockProgressionDirectionChanges()) { + setContentAreaIPD(newHeight); + } else { + vpContentBPD = newHeight; + } + updateRelDims(contentRectOffsetX, contentRectOffsetY, false); + } + + Position bcPosition = new BlockContainerPosition(this, breaker); + KnuthBox knuthBox = new KnuthBox(vpContentBPD, notifyPos(bcPosition), false); + //TODO Handle min/opt/max for block-progression-dimension + /* These two elements will be used to add stretchability to the above box + returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, + false, returnPosition, false)); + returnList.add(new KnuthGlue(0, 1 * constantLineHeight, 0, + LINE_NUMBER_ADJUSTMENT, returnPosition, false)); + */ + + if (contentOverflows) { + BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( + getBlockContainerFO().getUserAgent().getEventBroadcaster()); + boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW); + eventProducer.viewportOverflow(this, getBlockContainerFO().getName(), + breaker.getOverflowAmount(), needClip(), canRecover, + getBlockContainerFO().getLocator()); + } + return knuthBox; + } + + private boolean blockProgressionDirectionChanges() { + return getBlockContainerFO().getReferenceOrientation() % 180 != 0; + } + /** {@inheritDoc} */ public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack, Position restartPosition, LayoutManager restartAtLM) { @@ -408,7 +413,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager autoHeight = false; //boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); - int maxbpd = context.getStackLimitBP().opt; + int maxbpd = context.getStackLimitBP().getOpt(); int allocBPD; if (height.getEnum() == EN_AUTO || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { @@ -454,7 +459,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager getBlockContainerFO().getLocator()); } - MinOptMax stackLimit = new MinOptMax(relDims.bpd); + MinOptMax stackLimit = MinOptMax.getInstance(relDims.bpd); List returnedList; List contentList = new LinkedList(); @@ -492,7 +497,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager setCurrentChildLM(curLM); childLC.copyPendingMarksFrom(context); - childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit)); + childLC.setStackLimitBP(context.getStackLimitBP().minus(stackLimit)); childLC.setRefIPD(relDims.ipd); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); if (curLM == this.childLMs.get(0)) { @@ -507,7 +512,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager setCurrentChildLM(curLM); childLC.copyPendingMarksFrom(context); - childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit)); + childLC.setStackLimitBP(context.getStackLimitBP().minus(stackLimit)); childLC.setRefIPD(relDims.ipd); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); if (curLM == this.childLMs.get(0)) { @@ -578,7 +583,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager childLC = new LayoutContext(0); childLC.copyPendingMarksFrom(context); // curLM is a ? - childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit)); + childLC.setStackLimitBP(context.getStackLimitBP().minus(stackLimit)); childLC.setRefIPD(relDims.ipd); childLC.setWritingMode(getBlockContainerFO().getWritingMode()); if (curLM == this.childLMs.get(0)) { @@ -649,41 +654,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager wrapPositionElements(contentList, returnList); } else { - MinOptMax range = new MinOptMax(relDims.ipd); - BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); - breaker.doLayout(relDims.bpd, autoHeight); - boolean contentOverflows = breaker.isOverflow(); - if (autoHeight) { - //Update content BPD now that it is known - int newHeight = breaker.deferredAlg.totalWidth; - boolean switchedProgressionDirection - = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); - if (switchedProgressionDirection) { - setContentAreaIPD(newHeight); - } else { - vpContentBPD = newHeight; - } - updateRelDims(contentRectOffsetX, contentRectOffsetY, false); - } - - Position bcPosition = new BlockContainerPosition(this, breaker); - returnList.add(new KnuthBox(vpContentBPD, notifyPos(bcPosition), false)); - //TODO Handle min/opt/max for block-progression-dimension - /* These two elements will be used to add stretchability to the above box - returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, - false, returnPosition, false)); - returnList.add(new KnuthGlue(0, 1 * constantLineHeight, 0, - LINE_NUMBER_ADJUSTMENT, returnPosition, false)); - */ - - if (contentOverflows) { - BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( - getBlockContainerFO().getUserAgent().getEventBroadcaster()); - boolean canRecover = (getBlockContainerFO().getOverflow() != EN_ERROR_IF_OVERFLOW); - eventProducer.viewportOverflow(this, getBlockContainerFO().getName(), - breaker.getOverflowAmount(), needClip(), canRecover, - getBlockContainerFO().getLocator()); - } + returnList.add(refactoredBecauseOfDuplicateCode(contentRectOffsetX, + contentRectOffsetY)); } addKnuthElementsForBorderPaddingAfter(returnList, true); addKnuthElementsForSpaceAfter(returnList, alignment); @@ -706,8 +678,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager private List getNextKnuthElementsAbsolute(LayoutContext context, int alignment) { autoHeight = false; - boolean switchedProgressionDirection - = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); + boolean bpDirectionChanges = blockProgressionDirectionChanges(); Point offset = getAbsOffset(); int allocBPD, allocIPD; if (height.getEnum() == EN_AUTO @@ -720,7 +691,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager if (isFixed()) { availHeight = (int)getCurrentPV().getViewArea().getHeight(); } else { - availHeight = context.getStackLimitBP().opt; + availHeight = context.getStackLimitBP().getOpt(); } allocBPD = availHeight; allocBPD -= offset.y; @@ -753,8 +724,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager } } } else { - allocBPD = context.getStackLimitBP().opt; - if (!switchedProgressionDirection) { + allocBPD = context.getStackLimitBP().getOpt(); + if (!bpDirectionChanges) { autoHeight = true; } } @@ -798,7 +769,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager */ allocIPD = 0; } - if (switchedProgressionDirection) { + if (bpDirectionChanges) { autoHeight = true; } } @@ -812,14 +783,14 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager updateRelDims(0, 0, autoHeight); - MinOptMax range = new MinOptMax(relDims.ipd); + MinOptMax range = MinOptMax.getInstance(relDims.ipd); BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); breaker.doLayout((autoHeight ? 0 : relDims.bpd), autoHeight); boolean contentOverflows = breaker.isOverflow(); if (autoHeight) { //Update content BPD now that it is known int newHeight = breaker.deferredAlg.totalWidth; - if (switchedProgressionDirection) { + if (bpDirectionChanges) { setContentAreaIPD(newHeight); } else { vpContentBPD = newHeight; @@ -928,7 +899,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager protected LayoutContext createLayoutContext() { LayoutContext lc = super.createLayoutContext(); - lc.setRefIPD(ipd.opt); + lc.setRefIPD(ipd.getOpt()); lc.setWritingMode(getBlockContainerFO().getWritingMode()); return lc; } @@ -1026,7 +997,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // if this will create the first block area in a page // and display-align is bottom or center, add space before if (layoutContext.getSpaceBefore() > 0) { - addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); + addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore())); } LayoutManager childLM; @@ -1150,20 +1121,20 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager foBlockSpaceAfter = new SpaceVal(getBlockContainerFO() .getCommonMarginBlock().spaceAfter, this).getSpace(); adjustedSpaceBefore = (neededUnits(splitLength - + foBlockSpaceBefore.min - + foBlockSpaceAfter.min) + + foBlockSpaceBefore.getMin() + + foBlockSpaceAfter.getMin()) * bpUnit - splitLength) / 2; adjustedSpaceAfter = neededUnits(splitLength - + foBlockSpaceBefore.min - + foBlockSpaceAfter.min) + + foBlockSpaceBefore.getMin() + + foBlockSpaceAfter.getMin()) * bpUnit - splitLength - adjustedSpaceBefore; } else if (bSpaceBefore) { adjustedSpaceBefore = neededUnits(splitLength - + foBlockSpaceBefore.min) + + foBlockSpaceBefore.getMin()) * bpUnit - splitLength; } else { adjustedSpaceAfter = neededUnits(splitLength - + foBlockSpaceAfter.min) + + foBlockSpaceAfter.getMin()) * bpUnit - splitLength; } //log.debug("space before = " + adjustedSpaceBefore @@ -1209,8 +1180,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager */ public Area getParentArea(Area childArea) { if (referenceArea == null) { - boolean switchedProgressionDirection - = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); + boolean switchedProgressionDirection = blockProgressionDirectionChanges(); boolean allowBPDUpdate = autoHeight && !switchedProgressionDirection; viewportBlockArea = new BlockViewport(allowBPDUpdate); @@ -1270,7 +1240,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager // Set up dimensions // Must get dimensions from parent area - /*Area parentArea =*/ parentLM.getParentArea(referenceArea); + /*Area parentArea =*/ parentLayoutManager.getParentArea(referenceArea); //int referenceIPD = parentArea.getIPD(); referenceArea.setIPD(relDims.ipd); // Get reference IPD from parentArea diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index d7453a399..69e07a404 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -241,7 +241,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager // if this will create the first block area in a page // and display-align is after or center, add space before if (layoutContext.getSpaceBefore() > 0) { - addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); + addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore())); } LayoutManager childLM; @@ -356,20 +356,20 @@ public class BlockLayoutManager extends BlockStackingLayoutManager foSpaceAfter = new SpaceVal(getBlockFO() .getCommonMarginBlock().spaceAfter, this).getSpace(); adjustedSpaceBefore = (neededUnits(splitLength - + foSpaceBefore.min - + foSpaceAfter.min) + + foSpaceBefore.getMin() + + foSpaceAfter.getMin()) * bpUnit - splitLength) / 2; adjustedSpaceAfter = neededUnits(splitLength - + foSpaceBefore.min - + foSpaceAfter.min) + + foSpaceBefore.getMin() + + foSpaceAfter.getMin()) * bpUnit - splitLength - adjustedSpaceBefore; } else if (spaceBefore) { adjustedSpaceBefore = neededUnits(splitLength - + foSpaceBefore.min) + + foSpaceBefore.getMin()) * bpUnit - splitLength; } else { adjustedSpaceAfter = neededUnits(splitLength - + foSpaceAfter.min) + + foSpaceAfter.getMin()) * bpUnit - splitLength; } //log.debug("spazio prima = " + adjustedSpaceBefore @@ -426,7 +426,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager // Must get dimensions from parent area //Don't optimize this line away. It can have ugly side-effects. - /*Area parentArea =*/ parentLM.getParentArea(curBlockArea); + /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); // set traits TraitSetter.setProducerID(curBlockArea, getBlockFO().getId()); diff --git a/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java index 3d30abde0..a1d43dd6f 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLevelLayoutManager.java @@ -26,17 +26,6 @@ import org.apache.fop.fo.properties.KeepProperty; */ public interface BlockLevelLayoutManager extends LayoutManager { - /** Adjustment class: no adjustment */ - int NO_ADJUSTMENT = -1; - /** Adjustment class: adjustment for space-before */ - int SPACE_BEFORE_ADJUSTMENT = 0; - /** Adjustment class: adjustment for space-after */ - int SPACE_AFTER_ADJUSTMENT = 1; - /** Adjustment class: adjustment for number of lines */ - int LINE_NUMBER_ADJUSTMENT = 2; - /** Adjustment class: adjustment for line height */ - int LINE_HEIGHT_ADJUSTMENT = 3; - int negotiateBPDAdjustment(int adj, KnuthElement lastElement); void discardSpace(KnuthGlue spaceGlue); diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 92a423098..4636cb15a 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -128,7 +128,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (sp != 0) { Block spacer = new Block(); spacer.setBPD(sp); - parentLM.addChildArea(spacer); + parentLayoutManager.addChildArea(spacer); } } @@ -177,7 +177,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager */ protected void flush() { if (getCurrentArea() != null) { - parentLM.addChildArea(getCurrentArea()); + parentLayoutManager.addChildArea(getCurrentArea()); } } @@ -654,7 +654,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager if (innerPosition == null && lastElement.isGlue()) { // this adjustment applies to space-before or space-after of this block - if (((KnuthGlue) lastElement).getAdjustmentClass() == SPACE_BEFORE_ADJUSTMENT) { + if (((KnuthGlue) lastElement).getAdjustmentClass() + == Adjustment.SPACE_BEFORE_ADJUSTMENT) { // this adjustment applies to space-before adjustedSpaceBefore += adj; /*LF*/ //log.debug(" BLM.negotiateBPDAdjustment> spazio prima: " + adj); @@ -735,14 +736,14 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // if this block has block-progression-unit > 0, innerPosition can be // a MappingPosition // spaceGlue represents space before or space after of this block - if (spaceGlue.getAdjustmentClass() == SPACE_BEFORE_ADJUSTMENT) { + if (spaceGlue.getAdjustmentClass() == Adjustment.SPACE_BEFORE_ADJUSTMENT) { // space-before must be discarded adjustedSpaceBefore = 0; - foSpaceBefore = new MinOptMax(0); + foSpaceBefore = MinOptMax.ZERO; } else { // space-after must be discarded adjustedSpaceAfter = 0; - foSpaceAfter = new MinOptMax(0); + foSpaceAfter = MinOptMax.ZERO; //TODO Why are both cases handled in the same way? } } else { @@ -909,10 +910,10 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } if (bpUnit > 0) { returnList.add(new KnuthGlue(0, 0, 0, - SPACE_BEFORE_ADJUSTMENT, new NonLeafPosition(this, null), true)); + Adjustment.SPACE_BEFORE_ADJUSTMENT, new NonLeafPosition(this, null), true)); } else { returnList.add(new KnuthGlue(adjustedSpaceBefore, 0, 0, - SPACE_BEFORE_ADJUSTMENT, new NonLeafPosition(this, null), true)); + Adjustment.SPACE_BEFORE_ADJUSTMENT, new NonLeafPosition(this, null), true)); } } @@ -949,12 +950,12 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } if (bpUnit > 0) { returnList.add(new KnuthGlue(0, 0, 0, - SPACE_AFTER_ADJUSTMENT, + Adjustment.SPACE_AFTER_ADJUSTMENT, new NonLeafPosition(this, null), spaceAfterIsConditional)); } else { returnList.add(new KnuthGlue(adjustedSpaceAfter, 0, 0, - SPACE_AFTER_ADJUSTMENT, + Adjustment.SPACE_AFTER_ADJUSTMENT, new NonLeafPosition(this, null), spaceAfterIsConditional)); } @@ -1396,8 +1397,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager bAddedBoxAfter = true; } - MinOptMax totalLength = new MinOptMax(0); - MinOptMax totalUnits = new MinOptMax(0); + MinOptMax totalLength = MinOptMax.ZERO; LinkedList newList = new LinkedList(); //log.debug(" Prima scansione"); @@ -1406,11 +1406,11 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager while (oldListIterator.hasNext()) { KnuthElement element = (KnuthElement) oldListIterator.next(); if (element.isBox()) { - totalLength.add(new MinOptMax(element.getWidth())); + totalLength = totalLength.plus(element.getWidth()); //log.debug("box " + element.getWidth()); } else if (element.isGlue()) { - totalLength.min -= element.getShrink(); - totalLength.max += element.getStretch(); + totalLength = totalLength.minusMin(element.getShrink()); + totalLength = totalLength.plusMax(element.getStretch()); //leafValue = ((LeafPosition) element.getPosition()).getLeafPos(); //log.debug("glue " + element.getWidth() + " + " // + ((KnuthGlue) element).getStretch() + " - " @@ -1421,9 +1421,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } } // compute the total amount of "units" - totalUnits = new MinOptMax(neededUnits(totalLength.min), - neededUnits(totalLength.opt), - neededUnits(totalLength.max)); + MinOptMax totalUnits = MinOptMax.getInstance(neededUnits(totalLength.getMin()), + neededUnits(totalLength.getOpt()), + neededUnits(totalLength.getMax())); //log.debug(" totalLength= " + totalLength); //log.debug(" unita'= " + totalUnits); @@ -1432,35 +1432,35 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // in order to compute partial min, opt and max length // and create the new elements oldListIterator = oldList.listIterator(); - boolean bPrevIsBox = false; - MinOptMax lengthBeforeBreak = new MinOptMax(0); - MinOptMax lengthAfterBreak = (MinOptMax) totalLength.clone(); + boolean prevIsBox; + MinOptMax lengthBeforeBreak = MinOptMax.ZERO; + MinOptMax lengthAfterBreak = totalLength; MinOptMax unitsBeforeBreak; MinOptMax unitsAfterBreak; - MinOptMax unsuppressibleUnits = new MinOptMax(0); + MinOptMax unsuppressibleUnits = MinOptMax.ZERO; int firstIndex = 0; int lastIndex = -1; while (oldListIterator.hasNext()) { KnuthElement element = (KnuthElement) oldListIterator.next(); lastIndex++; if (element.isBox()) { - lengthBeforeBreak.add(new MinOptMax(element.getWidth())); - lengthAfterBreak.subtract(new MinOptMax(element.getWidth())); - bPrevIsBox = true; + lengthBeforeBreak = lengthBeforeBreak.plus(element.getWidth()); + lengthAfterBreak = lengthAfterBreak.minus(element.getWidth()); + prevIsBox = true; } else if (element.isGlue()) { - lengthBeforeBreak.min -= element.getShrink(); - lengthAfterBreak.min += element.getShrink(); - lengthBeforeBreak.max += element.getStretch(); - lengthAfterBreak.max -= element.getStretch(); - bPrevIsBox = false; + lengthBeforeBreak = lengthBeforeBreak.minusMin(element.getShrink()); + lengthAfterBreak = lengthAfterBreak.plusMin(element.getShrink()); + lengthBeforeBreak = lengthBeforeBreak.plusMax(element.getStretch()); + lengthAfterBreak = lengthAfterBreak.minusMax(element.getStretch()); + prevIsBox = false; } else { - lengthBeforeBreak.add(new MinOptMax(element.getWidth())); - bPrevIsBox = false; + lengthBeforeBreak = lengthBeforeBreak.plus(element.getWidth()); + prevIsBox = false; } // create the new elements if (element.isPenalty() && element.getPenalty() < KnuthElement.INFINITE - || element.isGlue() && bPrevIsBox + || element.isGlue() && prevIsBox || !oldListIterator.hasNext()) { // suppress elements after the breaking point int iStepsForward = 0; @@ -1469,8 +1469,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager iStepsForward++; if (el.isGlue()) { // suppressed glue - lengthAfterBreak.min += el.getShrink(); - lengthAfterBreak.max -= el.getStretch(); + lengthAfterBreak = lengthAfterBreak.plusMin(el.getShrink()); + lengthAfterBreak = lengthAfterBreak.minusMax(el.getStretch()); } else if (el.isPenalty()) { // suppressed penalty, do nothing } else { @@ -1479,36 +1479,37 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } } // compute the partial amount of "units" before and after the break - unitsBeforeBreak = new MinOptMax(neededUnits(lengthBeforeBreak.min), - neededUnits(lengthBeforeBreak.opt), - neededUnits(lengthBeforeBreak.max)); - unitsAfterBreak = new MinOptMax(neededUnits(lengthAfterBreak.min), - neededUnits(lengthAfterBreak.opt), - neededUnits(lengthAfterBreak.max)); + unitsBeforeBreak = MinOptMax.getInstance(neededUnits(lengthBeforeBreak.getMin()), + neededUnits(lengthBeforeBreak.getOpt()), + neededUnits(lengthBeforeBreak.getMax())); + unitsAfterBreak = MinOptMax.getInstance(neededUnits(lengthAfterBreak.getMin()), + neededUnits(lengthAfterBreak.getOpt()), + neededUnits(lengthAfterBreak.getMax())); // rewind the iterator and lengthAfterBreak for (int i = 0; i < iStepsForward; i++) { KnuthElement el = (KnuthElement) oldListIterator.previous(); if (el.isGlue()) { - lengthAfterBreak.min -= el.getShrink(); - lengthAfterBreak.max += el.getStretch(); + lengthAfterBreak = lengthAfterBreak.minusMin(el.getShrink()); + lengthAfterBreak = lengthAfterBreak.plusMax(el.getStretch()); } } // compute changes in length, stretch and shrink - int uLengthChange = unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt; - int uStretchChange = (unitsBeforeBreak.max + unitsAfterBreak.max - totalUnits.max) - - (unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt); - int uShrinkChange = (unitsBeforeBreak.opt + unitsAfterBreak.opt - totalUnits.opt) - - (unitsBeforeBreak.min + unitsAfterBreak.min - totalUnits.min); + int uLengthChange = unitsBeforeBreak.getOpt() + unitsAfterBreak.getOpt() + - totalUnits.getOpt(); + int uStretchChange = unitsBeforeBreak.getStretch() + + unitsAfterBreak.getStretch() - totalUnits.getStretch(); + int uShrinkChange = unitsBeforeBreak.getShrink() + + unitsAfterBreak.getShrink() - totalUnits.getShrink(); // compute the number of normal, stretch and shrink unit // that must be added to the new sequence - int uNewNormal = unitsBeforeBreak.opt - unsuppressibleUnits.opt; - int uNewStretch = (unitsBeforeBreak.max - unitsBeforeBreak.opt) - - (unsuppressibleUnits.max - unsuppressibleUnits.opt); - int uNewShrink = (unitsBeforeBreak.opt - unitsBeforeBreak.min) - - (unsuppressibleUnits.opt - unsuppressibleUnits.min); + int uNewNormal = unitsBeforeBreak.getOpt() - unsuppressibleUnits.getOpt(); + int uNewStretch = unitsBeforeBreak.getStretch() + - unsuppressibleUnits.getStretch(); + int uNewShrink = unitsBeforeBreak.getShrink() + - unsuppressibleUnits.getShrink(); //log.debug("(" // + unsuppressibleUnits.min + "-" + unsuppressibleUnits.opt + "-" @@ -1539,10 +1540,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager lastIndex - lastIndexCorrection); // new box - newList.add(new KnuthBox((uNewNormal - uLengthChange) * bpUnit, - mappingPos, - false)); - unsuppressibleUnits.add(new MinOptMax(uNewNormal - uLengthChange)); + newList.add(new KnuthBox((uNewNormal - uLengthChange) * bpUnit, mappingPos, false)); + unsuppressibleUnits = unsuppressibleUnits.plus(uNewNormal - uLengthChange); //log.debug(" box " + (uNewNormal - uLengthChange)); // new infinite penalty, glue and box, if necessary @@ -1558,17 +1557,15 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager newList.add(new KnuthGlue(0, iStretchUnits * bpUnit, iShrinkUnits * bpUnit, - LINE_NUMBER_ADJUSTMENT, + Adjustment.LINE_NUMBER_ADJUSTMENT, mappingPos, false)); //log.debug(" PENALTY"); //log.debug(" glue 0 " + iStretchUnits + " " + iShrinkUnits); - unsuppressibleUnits.max += iStretchUnits; - unsuppressibleUnits.min -= iShrinkUnits; + unsuppressibleUnits = unsuppressibleUnits.plusMax(iStretchUnits); + unsuppressibleUnits = unsuppressibleUnits.minusMin(iShrinkUnits); if (!oldListIterator.hasNext()) { - newList.add(new KnuthBox(0, - mappingPos, - false)); + newList.add(new KnuthBox(0, mappingPos, false)); //log.debug(" box 0"); } } @@ -1583,7 +1580,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager newList.add(new KnuthGlue(0, uStretchChange * bpUnit, uShrinkChange * bpUnit, - LINE_NUMBER_ADJUSTMENT, + Adjustment.LINE_NUMBER_ADJUSTMENT, mappingPos, false)); newList.add(new KnuthPenalty(uLengthChange * bpUnit, @@ -1591,7 +1588,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager newList.add(new KnuthGlue(0, -uStretchChange * bpUnit, -uShrinkChange * bpUnit, - LINE_NUMBER_ADJUSTMENT, + Adjustment.LINE_NUMBER_ADJUSTMENT, mappingPos, false)); //log.debug(" PENALTY"); @@ -1612,7 +1609,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } if (element.isPenalty()) { - lengthBeforeBreak.add(new MinOptMax(-element.getWidth())); + lengthBeforeBreak = lengthBeforeBreak.minus(element.getWidth()); } } @@ -1637,13 +1634,13 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager KnuthBox wrongBox = (KnuthBox) newList.removeFirst(); // if this paragraph is at the top of a page, the space before // must be ignored; compute the length change - int decreasedLength = (neededUnits(totalLength.opt) - - neededUnits(totalLength.opt - adjustedSpaceBefore)) + int decreasedLength = (neededUnits(totalLength.getOpt()) + - neededUnits(totalLength.getOpt() - adjustedSpaceBefore)) * bpUnit; // insert the correct elements newList.addFirst(new KnuthBox(wrongBox.getWidth() - decreasedLength, wrongBox.getPosition(), false)); - newList.addFirst(new KnuthGlue(decreasedLength, 0, 0, SPACE_BEFORE_ADJUSTMENT, + newList.addFirst(new KnuthGlue(decreasedLength, 0, 0, Adjustment.SPACE_BEFORE_ADJUSTMENT, wrongBox.getPosition(), false)); //log.debug(" rimosso box " + neededUnits(wrongBox.getWidth())); //log.debug(" aggiunto glue " + neededUnits(decreasedLength) + " 0 0"); @@ -1673,8 +1670,8 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager // if this paragraph is at the bottom of a page, the space after // must be ignored; compute the length change - int decreasedLength = (neededUnits(totalLength.opt) - - neededUnits(totalLength.opt - adjustedSpaceAfter)) + int decreasedLength = (neededUnits(totalLength.getOpt()) + - neededUnits(totalLength.getOpt() - adjustedSpaceAfter)) * bpUnit; // insert the correct box newList.addLast(new KnuthBox(wrongBox.getWidth() - decreasedLength, @@ -1684,7 +1681,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager newList.addAll(preserveList); } // insert the correct glue - newList.addLast(new KnuthGlue(decreasedLength, 0, 0, SPACE_AFTER_ADJUSTMENT, + newList.addLast(new KnuthGlue(decreasedLength, 0, 0, Adjustment.SPACE_AFTER_ADJUSTMENT, wrongBox.getPosition(), false)); //log.debug(" rimosso box " + neededUnits(wrongBox.getWidth())); //log.debug(" aggiunto box " + neededUnits( @@ -1773,8 +1770,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager */ protected void wrapPositionElement(ListElement el, List targetList, boolean force) { if (force || el.getLayoutManager() != this) { - el.setPosition(notifyPos(new NonLeafPosition(this, - el.getPosition()))); + el.setPosition(notifyPos(new NonLeafPosition(this, el.getPosition()))); } targetList.add(el); } diff --git a/src/java/org/apache/fop/layoutmgr/BorderOrPaddingElement.java b/src/java/org/apache/fop/layoutmgr/BorderOrPaddingElement.java index 28820224a..5236c9234 100644 --- a/src/java/org/apache/fop/layoutmgr/BorderOrPaddingElement.java +++ b/src/java/org/apache/fop/layoutmgr/BorderOrPaddingElement.java @@ -41,7 +41,7 @@ public abstract class BorderOrPaddingElement extends UnresolvedListElementWithLe RelSide side, boolean isFirst, boolean isLast, PercentBaseContext context) { super(position, - new MinOptMax(condLength.getLength().getValue(context)), side, + MinOptMax.getInstance(condLength.getLength().getValue(context)), side, condLength.isDiscard(), isFirst, isLast); } diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java index ca11d27c2..6a843ac63 100644 --- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java +++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java @@ -43,7 +43,7 @@ public final class ElementListUtils { * @return true if the opt constraint is bigger than the list contents */ public static boolean removeLegalBreaks(List elements, MinOptMax constraint) { - return removeLegalBreaks(elements, constraint.opt); + return removeLegalBreaks(elements, constraint.getOpt()); } /** @@ -132,7 +132,7 @@ public final class ElementListUtils { } } else if (el instanceof UnresolvedListElementWithLength) { UnresolvedListElementWithLength uel = (UnresolvedListElementWithLength)el; - len += uel.getLength().opt; + len += uel.getLength().getOpt(); } } else { KnuthElement kel = (KnuthElement)el; @@ -240,4 +240,4 @@ public final class ElementListUtils { return prevBreak; } -}
\ No newline at end of file +} diff --git a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java index affa75abb..4f6cfa9d5 100644 --- a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java @@ -83,7 +83,7 @@ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { /** {@inheritDoc} */ public void addChildArea(Area childArea) { childArea.setAreaClass(Area.CLASS_FOOTNOTE); - parentLM.addChildArea(childArea); + parentLayoutManager.addChildArea(childArea); } /** @return the FootnoteBody node */ diff --git a/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java b/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java index 1aa22ea3e..a7fc5bb72 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthBlockBox.java @@ -41,30 +41,32 @@ public class KnuthBlockBox extends KnuthBox { /** * Creates a new box. - * @param w block progression dimension of this box - * @param range min, opt, max inline progression dimension of this box - * @param bpdim natural width of the line represented by this box. - * @param pos the Position stored in this box - * @param bAux is this box auxiliary? + * + * @param width block progression dimension of this box + * @param range min, opt, max inline progression dimension of this box + * @param bpdim natural width of the line represented by this box. + * @param pos the Position stored in this box + * @param auxiliary is this box auxiliary? */ - public KnuthBlockBox(int w, MinOptMax range, int bpdim, Position pos, boolean bAux) { - super(w, pos, bAux); - ipdRange = (MinOptMax) range.clone(); + public KnuthBlockBox(int width, MinOptMax range, int bpdim, Position pos, boolean auxiliary) { + super(width, pos, auxiliary); + ipdRange = range; bpd = bpdim; footnoteList = new LinkedList(); } /** * Creates a new box. - * @param w block progression dimension of this box - * @param list footnotes cited by elements in this box. The list contains the - * corresponding FootnoteBodyLayoutManagers - * @param pos the Position stored in this box - * @param bAux is this box auxiliary? + * + * @param width block progression dimension of this box + * @param list footnotes cited by elements in this box. The list contains the corresponding + * FootnoteBodyLayoutManagers + * @param pos the Position stored in this box + * @param auxiliary is this box auxiliary? */ - public KnuthBlockBox(int w, List list, Position pos, boolean bAux) { - super(w, pos, bAux); - ipdRange = new MinOptMax(0); + public KnuthBlockBox(int width, List list, Position pos, boolean auxiliary) { + super(width, pos, auxiliary); + ipdRange = MinOptMax.ZERO; bpd = 0; footnoteList = new LinkedList(list); } @@ -85,6 +87,7 @@ public class KnuthBlockBox extends KnuthBox { /** * Adds the given list of Knuth elements to this box' list of elements. + * * @param list elements corresponding to a footnote body */ public void addElementList(List list) { @@ -96,8 +99,8 @@ public class KnuthBlockBox extends KnuthBox { /** * Returns the list of Knuth sequences registered by this box. - * @return a list of KnuthElement sequences corresponding to footnotes cited in this - * box + * + * @return a list of KnuthElement sequences corresponding to footnotes cited in this box */ public List getElementLists() { return elementLists; @@ -107,12 +110,13 @@ public class KnuthBlockBox extends KnuthBox { * @return the inline progression dimension of this box. */ public MinOptMax getIPDRange() { - return (MinOptMax) ipdRange.clone(); + return ipdRange; } /** - * Returns the natural width (without stretching nor shrinking) of the line - * represented by this box. + * Returns the natural width (without stretching nor shrinking) of the line represented by this + * box. + * * @return the line width */ public int getBPD() { diff --git a/src/java/org/apache/fop/layoutmgr/KnuthBox.java b/src/java/org/apache/fop/layoutmgr/KnuthBox.java index d7615dda1..a1d8c095c 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthBox.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthBox.java @@ -35,7 +35,7 @@ package org.apache.fop.layoutmgr; public class KnuthBox extends KnuthElement { /** - * Create a new KnuthBox. + * Creates a new <code>KnuthBox</code>. * * @param width the width of this box * @param pos the Position stored in this box diff --git a/src/java/org/apache/fop/layoutmgr/KnuthElement.java b/src/java/org/apache/fop/layoutmgr/KnuthElement.java index e8ca6d85b..acd95a7d6 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthElement.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthElement.java @@ -36,8 +36,7 @@ public abstract class KnuthElement extends ListElement { private boolean auxiliary; /** - * Create a new KnuthElement. - * This class being abstract, this can be called only by subclasses. + * Creates a new <code>KnuthElement</code>. * * @param width the width of this element * @param pos the Position stored in this element diff --git a/src/java/org/apache/fop/layoutmgr/KnuthGlue.java b/src/java/org/apache/fop/layoutmgr/KnuthGlue.java index 7533a4117..2efea0e61 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthGlue.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthGlue.java @@ -19,6 +19,8 @@ package org.apache.fop.layoutmgr; +import org.apache.fop.traits.MinOptMax; + /** * An instance of this class represents a piece of content with adjustable * width: for example a space between words of justified text. @@ -47,31 +49,49 @@ package org.apache.fop.layoutmgr; */ public class KnuthGlue extends KnuthElement { - private int stretchability; - private int shrinkability; - private int adjustmentClass = -1; + private final int stretch; + private final int shrink; + private final Adjustment adjustmentClass; + + /** + * Creates a new <code>KnuthGlue</code>. + * + * @param minOptMax a <code>MinOptMax</code> where the {@link MinOptMax#getOpt() opt-value} is + * mapped to the width, the {@link MinOptMax#getStretch() + * stretchability} is mapped to the stretchability and the the {@link + * MinOptMax#getShrink() shrinkability} is mapped to the shrinkability + * @param pos the Position stored in this glue + * @param auxiliary is this glue auxiliary? + */ + public KnuthGlue(MinOptMax minOptMax, Position pos, boolean auxiliary) { + super(minOptMax.getOpt(), pos, auxiliary); + this.stretch = minOptMax.getStretch(); + this.shrink = minOptMax.getShrink(); + this.adjustmentClass = Adjustment.NO_ADJUSTMENT; + } /** - * Create a new KnuthGlue. + * Creates a new <code>KnuthGlue</code>. * - * @param width the width of this glue - * @param stretchability the stretchability of this glue - * @param shrinkability the shrinkability of this glue - * @param pos the Position stored in this glue + * @param width the width of this glue + * @param stretch the stretchability of this glue + * @param shrink the shrinkability of this glue + * @param pos the Position stored in this glue * @param auxiliary is this glue auxiliary? */ - public KnuthGlue(int width, int stretchability, int shrinkability, Position pos, + public KnuthGlue(int width, int stretch, int shrink, Position pos, boolean auxiliary) { super(width, pos, auxiliary); - this.stretchability = stretchability; - this.shrinkability = shrinkability; + this.stretch = stretch; + this.shrink = shrink; + this.adjustmentClass = Adjustment.NO_ADJUSTMENT; } - public KnuthGlue(int width, int stretchability, int shrinkability, int adjustmentClass, + public KnuthGlue(int width, int stretch, int shrink, Adjustment adjustmentClass, Position pos, boolean auxiliary) { super(width, pos, auxiliary); - this.stretchability = stretchability; - this.shrinkability = shrinkability; + this.stretch = stretch; + this.shrink = shrink; this.adjustmentClass = adjustmentClass; } @@ -82,16 +102,16 @@ public class KnuthGlue extends KnuthElement { /** @return the stretchability of this glue. */ public int getStretch() { - return stretchability; + return stretch; } /** @return the shrinkability of this glue. */ public int getShrink() { - return shrinkability; + return shrink; } /** @return the adjustment class (or role) of this glue. */ - public int getAdjustmentClass() { + public Adjustment getAdjustmentClass() { return adjustmentClass; } @@ -105,7 +125,7 @@ public class KnuthGlue extends KnuthElement { buffer.append(" w=").append(getWidth()); buffer.append(" stretch=").append(getStretch()); buffer.append(" shrink=").append(getShrink()); - if (getAdjustmentClass() >= 0) { + if (!getAdjustmentClass().equals(Adjustment.NO_ADJUSTMENT)) { buffer.append(" adj-class=").append(getAdjustmentClass()); } return buffer.toString(); diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 81726e57b..752ffd628 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -173,7 +173,7 @@ public class LayoutContext { public LayoutContext(int flags) { this.flags = flags; this.refIPD = 0; - stackLimitBP = new MinOptMax(0); + stackLimitBP = MinOptMax.ZERO; leadingSpace = null; trailingSpace = null; } diff --git a/src/java/org/apache/fop/layoutmgr/LeafPosition.java b/src/java/org/apache/fop/layoutmgr/LeafPosition.java index 8b2a5f4bc..e1d5b2aaa 100644 --- a/src/java/org/apache/fop/layoutmgr/LeafPosition.java +++ b/src/java/org/apache/fop/layoutmgr/LeafPosition.java @@ -23,8 +23,8 @@ public class LeafPosition extends Position { private int leafPos; - public LeafPosition(LayoutManager lm, int pos) { - super(lm); + public LeafPosition(LayoutManager layoutManager, int pos) { + super(layoutManager); leafPos = pos; } diff --git a/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java b/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java deleted file mode 100644 index f029d9082..000000000 --- a/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java +++ /dev/null @@ -1,115 +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.datatypes.PercentBaseContext; -import org.apache.fop.fo.Constants; -import org.apache.fop.fo.properties.LengthRangeProperty; -import org.apache.fop.traits.MinOptMax; - -/** - * Utilities for MinOptMax and LengthRangeProperty. - */ -public class MinOptMaxUtil { - - /** - * Restricts a MinOptMax using the values from a LengthRangeProperty. - * @param mom MinOptMax to restrict - * @param lr restricting source - * @param context Percentage evaluation context - */ - public static void restrict(MinOptMax mom, LengthRangeProperty lr, - PercentBaseContext context) { - if (lr.getEnum() != Constants.EN_AUTO) { - if (lr.getMinimum(context).getEnum() != Constants.EN_AUTO) { - int min = lr.getMinimum(context).getLength().getValue(context); - if (min > mom.min) { - mom.min = min; - fixAfterMinChanged(mom); - } - } - if (lr.getMaximum(context).getEnum() != Constants.EN_AUTO) { - int max = lr.getMaximum(context).getLength().getValue(context); - if (max < mom.max) { - mom.max = max; - if (mom.max < mom.opt) { - mom.opt = mom.max; - mom.min = mom.opt; - } - } - } - if (lr.getOptimum(context).getEnum() != Constants.EN_AUTO) { - int opt = lr.getOptimum(context).getLength().getValue(context); - if (opt > mom.min) { - mom.opt = opt; - if (mom.opt > mom.max) { - mom.max = mom.opt; - } - } - } - } - } - - /** - * Extends the minimum length to the given length if necessary, and adjusts opt and - * max accordingly. - * - * @param mom the min/opt/max trait - * @param len the new minimum length - */ - public static void extendMinimum(MinOptMax mom, int len) { - if (mom.min < len) { - mom.min = len; - mom.opt = Math.max(mom.min, mom.opt); - mom.max = Math.max(mom.opt, mom.max); - } - } - - /** - * After a calculation on a MinOptMax, this can be called to set opt to - * a new effective value. - * @param mom MinOptMax to adjust - */ - public static void fixAfterMinChanged(MinOptMax mom) { - if (mom.min > mom.opt) { - mom.opt = mom.min; - if (mom.opt > mom.max) { - mom.max = mom.opt; - } - } - } - - /** - * Converts a LengthRangeProperty to a MinOptMax. - * @param prop LengthRangeProperty - * @param context Percentage evaluation context - * @return the requested MinOptMax instance - */ - public static MinOptMax toMinOptMax(LengthRangeProperty prop, PercentBaseContext context) { - int min = prop.getMinimum(context).isAuto() ? 0 - : prop.getMinimum(context).getLength().getValue(context); - int opt = prop.getOptimum(context).isAuto() ? min - : prop.getOptimum(context).getLength().getValue(context); - int max = prop.getMaximum(context).isAuto() ? Integer.MAX_VALUE - : prop.getMaximum(context).getLength().getValue(context); - return new MinOptMax(min, opt, max); - } - -} diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index 86c3fccf8..134e69f31 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr; -import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -204,7 +203,7 @@ public class PageBreaker extends AbstractBreaker { pslm, footnoteSeparator, separatorArea); footnoteSeparatorLM.doLayout(); - footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD()); + footnoteSeparatorLength = MinOptMax.getInstance(separatorArea.getBPD()); } } diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java index cab68a13f..8f60e51b7 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java @@ -116,7 +116,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { this.pageProvider = pageProvider; this.layoutListener = layoutListener; best = new BestPageRecords(); - this.footnoteSeparatorLength = (MinOptMax) footnoteSeparatorLength.clone(); + this.footnoteSeparatorLength = footnoteSeparatorLength; this.autoHeight = autoHeight; this.favorSinglePart = favorSinglePart; } @@ -483,7 +483,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { if (allFootnotes > 0) { // this page contains some footnote citations // add the footnote separator width - actualWidth += footnoteSeparatorLength.opt; + actualWidth += footnoteSeparatorLength.getOpt(); if (actualWidth + allFootnotes <= getLineWidth(activeNode.line)) { // there is enough space to insert all footnotes: // add the whole allFootnotes length @@ -757,7 +757,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { int maxAdjustment = totalStretch - activeNode.totalStretch; // add the footnote separator stretch if some footnote content will be added if (((KnuthPageNode) activeNode).totalFootnotes < totalFootnotesLength) { - maxAdjustment += footnoteSeparatorLength.max - footnoteSeparatorLength.opt; + maxAdjustment += footnoteSeparatorLength.getStretch(); } if (maxAdjustment > 0) { return (double) difference / maxAdjustment; @@ -768,7 +768,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { int maxAdjustment = totalShrink - activeNode.totalShrink; // add the footnote separator shrink if some footnote content will be added if (((KnuthPageNode) activeNode).totalFootnotes < totalFootnotesLength) { - maxAdjustment += footnoteSeparatorLength.opt - footnoteSeparatorLength.min; + maxAdjustment += footnoteSeparatorLength.getShrink(); } if (maxAdjustment > 0) { return (double) difference / maxAdjustment; diff --git a/src/java/org/apache/fop/layoutmgr/SpaceElement.java b/src/java/org/apache/fop/layoutmgr/SpaceElement.java index 820cf6506..6590d3a2a 100644 --- a/src/java/org/apache/fop/layoutmgr/SpaceElement.java +++ b/src/java/org/apache/fop/layoutmgr/SpaceElement.java @@ -40,13 +40,10 @@ public class SpaceElement extends UnresolvedListElementWithLength { * @param isLast true if this is a space-after of the last area generated. * @param context the property evaluation context */ - public SpaceElement(Position position, SpaceProperty space, RelSide side, - boolean isFirst, boolean isLast, - PercentBaseContext context) { - super(position, - MinOptMaxUtil.toMinOptMax( - space.getSpace().getLengthRange(), - context), side, space.isDiscard(), isFirst, isLast); + public SpaceElement(Position position, SpaceProperty space, RelSide side, boolean isFirst, + boolean isLast, PercentBaseContext context) { + super(position, space.getSpace().getLengthRange().toMinOptMax(context), side, + space.isDiscard(), isFirst, isLast); int en = space.getSpace().getPrecedence().getEnum(); if (en == Constants.EN_FORCE) { this.precedence = Integer.MAX_VALUE; diff --git a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java index ff464ce6a..6dbf107f3 100644 --- a/src/java/org/apache/fop/layoutmgr/SpaceResolver.java +++ b/src/java/org/apache/fop/layoutmgr/SpaceResolver.java @@ -152,7 +152,7 @@ public class SpaceResolver { } private void removeConditionalBorderAndPadding( - UnresolvedListElement[] elems, MinOptMax[] lengths, boolean reverse) { + UnresolvedListElement[] elems, MinOptMax[] lengths, boolean reverse) { for (int i = 0; i < elems.length; i++) { int effIndex; if (reverse) { @@ -176,7 +176,7 @@ public class SpaceResolver { } private void performSpaceResolutionRule1(UnresolvedListElement[] elems, MinOptMax[] lengths, - boolean reverse) { + boolean reverse) { for (int i = 0; i < elems.length; i++) { int effIndex; if (reverse) { @@ -274,7 +274,7 @@ public class SpaceResolver { } lengths[i] = null; } else { - greatestOptimum = Math.max(greatestOptimum, space.getLength().opt); + greatestOptimum = Math.max(greatestOptimum, space.getLength().getOpt()); remaining++; } } @@ -291,7 +291,7 @@ public class SpaceResolver { continue; } space = (SpaceElement)elems[i]; - if (space.getLength().opt < greatestOptimum) { + if (space.getLength().getOpt() < greatestOptimum) { if (log.isDebugEnabled()) { log.debug("Nulling space-specifier with smaller optimum length " + "using 4.3.1, rule 3: " @@ -313,8 +313,8 @@ public class SpaceResolver { continue; } space = (SpaceElement)elems[i]; - min = Math.max(min, space.getLength().min); - max = Math.min(max, space.getLength().max); + min = Math.max(min, space.getLength().getMin()); + max = Math.min(max, space.getLength().getMax()); if (remaining > 1) { if (log.isDebugEnabled()) { log.debug("Nulling non-last space-specifier using 4.3.1, rule 3, second part: " @@ -323,8 +323,7 @@ public class SpaceResolver { lengths[i] = null; remaining--; } else { - lengths[i].min = min; - lengths[i].max = max; + lengths[i] = MinOptMax.getInstance(min, lengths[i].getOpt(), max); } } @@ -409,54 +408,27 @@ public class SpaceResolver { } private MinOptMax sum(MinOptMax[] lengths) { - MinOptMax sum = new MinOptMax(); + MinOptMax sum = MinOptMax.ZERO; for (int i = 0; i < lengths.length; i++) { if (lengths[i] != null) { - sum.add(lengths[i]); + sum = sum.plus(lengths[i]); } } return sum; } private void generate(ListIterator iter) { - MinOptMax noBreakLength = new MinOptMax(); - MinOptMax glue1; //space before break possibility if break occurs - //MinOptMax glue2; //difference between glue 1 and 3 when no break occurs - MinOptMax glue3; //space after break possibility if break occurs - glue1 = sum(firstPartLengths); - glue3 = sum(secondPartLengths); - noBreakLength = sum(noBreakLengths); - - //This doesn't produce the right glue2 - //glue2 = new MinOptMax(noBreakLength); - //glue2.subtract(glue1); - //glue2.subtract(glue3); - - int glue2w = noBreakLength.opt - glue1.opt - glue3.opt; - int glue2stretch = (noBreakLength.max - noBreakLength.opt); - int glue2shrink = (noBreakLength.opt - noBreakLength.min); - glue2stretch -= glue1.max - glue1.opt; - glue2stretch -= glue3.max - glue3.opt; - glue2shrink -= glue1.opt - glue1.min; - glue2shrink -= glue3.opt - glue3.min; + MinOptMax spaceBeforeBreak = sum(firstPartLengths); + MinOptMax spaceAfterBreak = sum(secondPartLengths); boolean hasPrecedingNonBlock = false; - if (log.isDebugEnabled()) { - log.debug("noBreakLength=" + noBreakLength - + ", glue1=" + glue1 - + ", glue2=" + glue2w + "+" + glue2stretch + "-" + glue2shrink - + ", glue3=" + glue3); - } if (breakPoss != null) { - boolean forcedBreak = breakPoss.isForcedBreak(); - if (glue1.isNonZero()) { - iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, - false, (Position)null, true)); - iter.add(new KnuthGlue(glue1.opt, glue1.max - glue1.opt, glue1.opt - glue1.min, - (Position)null, true)); - if (forcedBreak) { + if (spaceBeforeBreak.isNonZero()) { + iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, null, true)); + iter.add(new KnuthGlue(spaceBeforeBreak, null, true)); + if (breakPoss.isForcedBreak()) { //Otherwise, the preceding penalty and glue will be cut off - iter.add(new KnuthBox(0, (Position)null, true)); + iter.add(new KnuthBox(0, null, true)); } } iter.add(new KnuthPenalty(breakPoss.getPenaltyWidth(), breakPoss.getPenaltyValue(), @@ -465,32 +437,38 @@ public class SpaceResolver { if (breakPoss.getPenaltyValue() <= -KnuthPenalty.INFINITE) { return; //return early. Not necessary (even wrong) to add additional elements } - if (glue2w != 0 || glue2stretch != 0 || glue2shrink != 0) { - iter.add(new KnuthGlue(glue2w, glue2stretch, glue2shrink, - (Position)null, true)); + + // No break + // TODO: We can't use a MinOptMax for glue2, because min <= opt <= max is not always true - why? + MinOptMax noBreakLength = sum(noBreakLengths); + MinOptMax spaceSum = spaceBeforeBreak.plus(spaceAfterBreak); + int glue2width = noBreakLength.getOpt() - spaceSum.getOpt(); + int glue2stretch = noBreakLength.getStretch() - spaceSum.getStretch(); + int glue2shrink = noBreakLength.getShrink() - spaceSum.getShrink(); + + if (glue2width != 0 || glue2stretch != 0 || glue2shrink != 0) { + iter.add(new KnuthGlue(glue2width, glue2stretch, glue2shrink, null, true)); } } else { - if (glue1.isNonZero()) { - throw new IllegalStateException("glue1 should be 0 in this case"); + if (spaceBeforeBreak.isNonZero()) { + throw new IllegalStateException("spaceBeforeBreak should be 0 in this case"); } } Position pos = null; if (breakPoss == null) { pos = new SpaceHandlingPosition(this); } - if (glue3.isNonZero() || pos != null) { + if (spaceAfterBreak.isNonZero() || pos != null) { iter.add(new KnuthBox(0, pos, true)); } - if (glue3.isNonZero()) { - iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, - false, (Position)null, true)); - iter.add(new KnuthGlue(glue3.opt, glue3.max - glue3.opt, glue3.opt - glue3.min, - (Position)null, true)); + if (spaceAfterBreak.isNonZero()) { + iter.add(new KnuthPenalty(0, KnuthPenalty.INFINITE, false, null, true)); + iter.add(new KnuthGlue(spaceAfterBreak, null, true)); hasPrecedingNonBlock = true; } if (isLast && hasPrecedingNonBlock) { //Otherwise, the preceding penalty and glue will be cut off - iter.add(new KnuthBox(0, (Position)null, true)); + iter.add(new KnuthBox(0, null, true)); } } @@ -608,9 +586,7 @@ public class SpaceResolver { /** {@inheritDoc} */ public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("SpaceHandlingPosition"); - return sb.toString(); + return "SpaceHandlingPosition"; } } @@ -741,5 +717,4 @@ public class SpaceResolver { } - } diff --git a/src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java b/src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java index 62a066121..140d90bb8 100644 --- a/src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java +++ b/src/java/org/apache/fop/layoutmgr/SpaceSpecifier.java @@ -31,12 +31,10 @@ import org.apache.fop.traits.MinOptMax; */ public class SpaceSpecifier implements Cloneable { - private boolean startsReferenceArea; private boolean hasForcing = false; private List spaceVals = new ArrayList(); - /** * Creates a new SpaceSpecifier. * @param startsReferenceArea true if it starts a new reference area @@ -76,7 +74,7 @@ public class SpaceSpecifier implements Cloneable { * @return true if any space-specifiers have been added. */ public boolean hasSpaces() { - return (spaceVals.size() > 0); + return !spaceVals.isEmpty(); } /** @@ -84,24 +82,22 @@ public class SpaceSpecifier implements Cloneable { * area, and the added space is conditional, and there are no * non-conditional values in the sequence yet, then ignore it. Otherwise * add it to the sequence. + * + * @param space the space to add. */ - public void addSpace(SpaceVal moreSpace) { - if (!startsReferenceArea - || !moreSpace.isConditional() - || !spaceVals.isEmpty()) { - if (moreSpace.isForcing()) { + public void addSpace(SpaceVal space) { + if (!startsReferenceArea || !space.isConditional() || hasSpaces()) { + if (space.isForcing()) { if (!hasForcing) { // Remove all other values (must all be non-forcing) spaceVals.clear(); hasForcing = true; } - spaceVals.add(moreSpace); + spaceVals.add(space); } else if (!hasForcing) { // Don't bother adding all 0 space-specifier if not forcing - if (moreSpace.getSpace().min != 0 - || moreSpace.getSpace().opt != 0 - || moreSpace.getSpace().max != 0) { - spaceVals.add(moreSpace); + if (space.getSpace().isNonZero()) { + spaceVals.add(space); } } } @@ -109,11 +105,11 @@ public class SpaceSpecifier implements Cloneable { /** - * Resolve the current sequence of space-specifiers, accounting for - * forcing values. - * @param endsReferenceArea True if the sequence should be resolved - * at the trailing edge of reference area. - * @return The resolved value as a min/opt/max triple. + * Resolve the current sequence of space-specifiers, accounting for forcing values. + * + * @param endsReferenceArea whether the sequence should be resolved at the trailing edge of + * reference area. + * @return the resolved value as a min/opt/max triple. */ public MinOptMax resolve(boolean endsReferenceArea) { int lastIndex = spaceVals.size(); @@ -127,24 +123,30 @@ public class SpaceSpecifier implements Cloneable { } } } - MinOptMax resolvedSpace = new MinOptMax(0); + MinOptMax resolvedSpace = MinOptMax.ZERO; int maxPrecedence = -1; for (int index = 0; index < lastIndex; index++) { SpaceVal spaceVal = (SpaceVal) spaceVals.get(index); + MinOptMax space = spaceVal.getSpace(); if (hasForcing) { - resolvedSpace.add(spaceVal.getSpace()); - } else if (spaceVal.getPrecedence() > maxPrecedence) { - maxPrecedence = spaceVal.getPrecedence(); - resolvedSpace = spaceVal.getSpace(); - } else if (spaceVal.getPrecedence() == maxPrecedence) { - if (spaceVal.getSpace().opt > resolvedSpace.opt) { - resolvedSpace = spaceVal.getSpace(); - } else if (spaceVal.getSpace().opt == resolvedSpace.opt) { - if (resolvedSpace.min < spaceVal.getSpace().min) { - resolvedSpace.min = spaceVal.getSpace().min; - } - if (resolvedSpace.max > spaceVal.getSpace().max) { - resolvedSpace.max = spaceVal.getSpace().max; + resolvedSpace = resolvedSpace.plus(space); + } else { + int precedence = spaceVal.getPrecedence(); + if (precedence > maxPrecedence) { + maxPrecedence = precedence; + resolvedSpace = space; + } else if (precedence == maxPrecedence) { + if (space.getOpt() > resolvedSpace.getOpt()) { + resolvedSpace = space; + } else if (space.getOpt() == resolvedSpace.getOpt()) { + if (resolvedSpace.getMin() < space.getMin()) { + resolvedSpace = MinOptMax.getInstance(space.getMin(), + resolvedSpace.getOpt(), resolvedSpace.getMax()); + } + if (resolvedSpace.getMax() > space.getMax()) { + resolvedSpace = MinOptMax.getInstance(resolvedSpace.getMin(), + resolvedSpace.getOpt(), space.getMax()); + } } } } @@ -154,8 +156,7 @@ public class SpaceSpecifier implements Cloneable { } public String toString() { - return "Space Specifier (resolved at begin/end of ref. area:):\n" + - resolve(false).toString() + "\n" + - resolve(true).toString(); + return "Space Specifier (resolved at begin/end of ref. area:):\n" + + resolve(false) + "\n" + resolve(true); } } diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java index d062ba2ca..911b6dcc6 100644 --- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java +++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java @@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.Trait; import org.apache.fop.datatypes.LengthBase; @@ -29,7 +30,6 @@ import org.apache.fop.datatypes.SimplePercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonMarginBlock; -import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.fonts.Font; @@ -46,11 +46,12 @@ public class TraitSetter { /** * Sets border and padding traits on areas. - * @param area area to set the traits on - * @param bpProps border and padding properties + * + * @param area area to set the traits on + * @param bpProps border and padding properties * @param bNotFirst True if the area is not the first area - * @param bNotLast True if the area is not the last area - * @param context Property evaluation context + * @param bNotLast True if the area is not the last area + * @param context Property evaluation context */ public static void setBorderPaddingTraits(Area area, CommonBorderPaddingBackground bpProps, boolean bNotFirst, boolean bNotLast, @@ -74,27 +75,28 @@ public class TraitSetter { } addBorderTrait(area, bpProps, bNotFirst, - CommonBorderPaddingBackground.START, - BorderProps.SEPARATE, Trait.BORDER_START); + CommonBorderPaddingBackground.START, + BorderProps.SEPARATE, Trait.BORDER_START); addBorderTrait(area, bpProps, bNotLast, - CommonBorderPaddingBackground.END, - BorderProps.SEPARATE, Trait.BORDER_END); + CommonBorderPaddingBackground.END, + BorderProps.SEPARATE, Trait.BORDER_END); addBorderTrait(area, bpProps, false, - CommonBorderPaddingBackground.BEFORE, - BorderProps.SEPARATE, Trait.BORDER_BEFORE); + CommonBorderPaddingBackground.BEFORE, + BorderProps.SEPARATE, Trait.BORDER_BEFORE); addBorderTrait(area, bpProps, false, - CommonBorderPaddingBackground.AFTER, - BorderProps.SEPARATE, Trait.BORDER_AFTER); + CommonBorderPaddingBackground.AFTER, + BorderProps.SEPARATE, Trait.BORDER_AFTER); } /** * Sets border traits on an area. - * @param area area to set the traits on + * + * @param area area to set the traits on * @param bpProps border and padding properties - * @param mode the border paint mode (see BorderProps) + * @param mode the border paint mode (see BorderProps) */ private static void addBorderTrait(Area area, CommonBorderPaddingBackground bpProps, @@ -103,9 +105,9 @@ public class TraitSetter { int iBP = bpProps.getBorderWidth(iSide, bDiscard); if (iBP > 0) { area.addTrait(oTrait, - new BorderProps(bpProps.getBorderStyle(iSide), - iBP, bpProps.getBorderColor(iSide), - mode)); + new BorderProps(bpProps.getBorderStyle(iSide), + iBP, bpProps.getBorderColor(iSide), + mode)); } } @@ -119,7 +121,7 @@ public class TraitSetter { * @deprecated Call the other addBorders() method and addPadding separately. */ public static void addBorders(Area area, CommonBorderPaddingBackground bordProps, - PercentBaseContext context) { + PercentBaseContext context) { BorderProps bps = getBorderProps(bordProps, CommonBorderPaddingBackground.BEFORE); if (bps != null) { area.addTrait(Trait.BORDER_BEFORE, bps); @@ -397,9 +399,9 @@ public class TraitSetter { int imageWidthMpt = back.getImageInfo().getSize().getWidthMpt(); int lengthBaseValue = width - imageWidthMpt; SimplePercentBaseContext simplePercentBaseContext - = new SimplePercentBaseContext(context, - LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, - lengthBaseValue); + = new SimplePercentBaseContext(context, + LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL, + lengthBaseValue); int horizontal = backProps.backgroundPositionHorizontal.getValue( simplePercentBaseContext); back.setHoriz(horizontal); @@ -421,7 +423,7 @@ public class TraitSetter { int imageHeightMpt = back.getImageInfo().getSize().getHeightMpt(); int lengthBaseValue = height - imageHeightMpt; SimplePercentBaseContext simplePercentBaseContext - = new SimplePercentBaseContext(context, + = new SimplePercentBaseContext(context, LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL, lengthBaseValue); int vertical = backProps.backgroundPositionVertical.getValue( @@ -459,8 +461,8 @@ public class TraitSetter { } int spaceStart = startIndent - - bpProps.getBorderStartWidth(false) - - bpProps.getPaddingStart(false, context); + - bpProps.getBorderStartWidth(false) + - bpProps.getPaddingStart(false, context); if (spaceStart != 0) { area.addTrait(Trait.SPACE_START, new Integer(spaceStart)); } @@ -469,8 +471,8 @@ public class TraitSetter { area.addTrait(Trait.END_INDENT, new Integer(endIndent)); } int spaceEnd = endIndent - - bpProps.getBorderEndWidth(false) - - bpProps.getPaddingEnd(false, context); + - bpProps.getBorderEndWidth(false) + - bpProps.getPaddingEnd(false, context); if (spaceEnd != 0) { area.addTrait(Trait.SPACE_END, new Integer(spaceEnd)); } @@ -504,14 +506,15 @@ public class TraitSetter { public static int getEffectiveSpace(double adjust, MinOptMax space) { if (space == null) { return 0; - } - int sp = space.opt; - if (adjust > 0) { - sp = sp + (int)(adjust * (space.max - space.opt)); } else { - sp = sp + (int)(adjust * (space.opt - space.min)); + int spaceOpt = space.getOpt(); + if (adjust > 0) { + spaceOpt += (int) (adjust * space.getStretch()); + } else { + spaceOpt += (int) (adjust * space.getShrink()); + } + return spaceOpt; } - return sp; } /** @@ -521,16 +524,17 @@ public class TraitSetter { * @param spaceBefore the space-before space specifier * @param spaceAfter the space-after space specifier */ - public static void addSpaceBeforeAfter(Area area, double adjust, - MinOptMax spaceBefore, MinOptMax spaceAfter) { - int space; - space = getEffectiveSpace(adjust, spaceBefore); - if (space != 0) { - area.addTrait(Trait.SPACE_BEFORE, new Integer(space)); - } - space = getEffectiveSpace(adjust, spaceAfter); - if (space != 0) { - area.addTrait(Trait.SPACE_AFTER, new Integer(space)); + public static void addSpaceBeforeAfter(Area area, double adjust, MinOptMax spaceBefore, + MinOptMax spaceAfter) { + addSpaceTrait(area, Trait.SPACE_BEFORE, spaceBefore, adjust); + addSpaceTrait(area, Trait.SPACE_AFTER, spaceAfter, adjust); + } + + private static void addSpaceTrait(Area area, Integer spaceTrait, + MinOptMax space, double adjust) { + int effectiveSpace = getEffectiveSpace(adjust, space); + if (effectiveSpace != 0) { + area.addTrait(spaceTrait, new Integer(effectiveSpace)); } } @@ -540,7 +544,7 @@ public class TraitSetter { * @param breakBefore the value for break-before * @param breakAfter the value for break-after */ - public static void addBreaks(Area area, int breakBefore, int breakAfter) { + public static void addBreaks(Area area, int breakBefore, int breakAfter) { /* Currently disabled as these traits are never used by the renderers area.addTrait(Trait.BREAK_AFTER, new Integer(breakAfter)); area.addTrait(Trait.BREAK_BEFORE, new Integer(breakBefore)); @@ -593,7 +597,7 @@ public class TraitSetter { area.addTrait(Trait.PTR, ptr); } } - + /** * Sets the producer's ID as a trait on the area. This can be used to track back the * generating FO node. diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index dcd993487..a19680f51 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -23,6 +23,7 @@ import java.util.LinkedList; import java.util.List; import org.apache.fop.area.Trait; +import org.apache.fop.area.inline.TextArea; import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fonts.Font; @@ -67,14 +68,13 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { hyphIPD = fobj.getCommonHyphenation().getHyphIPD(font); borderProps = fobj.getCommonBorderPaddingBackground(); setCommonBorderPaddingBackground(borderProps); - org.apache.fop.area.inline.TextArea chArea = getCharacterInlineArea(fobj); + TextArea chArea = getCharacterInlineArea(fobj); chArea.setBaselineOffset(font.getAscender()); setCurrentArea(chArea); } - private org.apache.fop.area.inline.TextArea getCharacterInlineArea(Character node) { - org.apache.fop.area.inline.TextArea text - = new org.apache.fop.area.inline.TextArea(); + private TextArea getCharacterInlineArea(Character node) { + TextArea text = new TextArea(); char ch = node.getCharacter(); if (CharUtilities.isAnySpace(ch)) { // add space unless it's zero-width: @@ -103,9 +103,9 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { Character fobj = (Character)this.fobj; - ipd = new MinOptMax(font.getCharWidth(fobj.getCharacter())); + ipd = MinOptMax.getInstance(font.getCharWidth(fobj.getCharacter())); - curArea.setIPD(ipd.opt); + curArea.setIPD(ipd.getOpt()); curArea.setBPD(font.getAscender() - font.getDescender()); TraitSetter.addFontTraits(curArea, font); @@ -126,16 +126,16 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { areaInfo = new AreaInfo((short) 0, ipd, false, alignmentContext); // node is a fo:Character - if (letterSpaceIPD.min == letterSpaceIPD.max) { + if (letterSpaceIPD.isStiff()) { // constant letter space, only return a box - seq.add(new KnuthInlineBox(areaInfo.ipdArea.opt, areaInfo.alignmentContext, + seq.add(new KnuthInlineBox(areaInfo.ipdArea.getOpt(), areaInfo.alignmentContext, notifyPos(new LeafPosition(this, 0)), false)); } else { // adjustable letter space, return a sequence of elements; // at the moment the character is supposed to have no letter spaces, // but returning this sequence allows us to change only one element // if addALetterSpaceTo() is called - seq.add(new KnuthInlineBox(areaInfo.ipdArea.opt, areaInfo.alignmentContext, + seq.add(new KnuthInlineBox(areaInfo.ipdArea.getOpt(), areaInfo.alignmentContext, notifyPos(new LeafPosition(this, 0)), false)); seq.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new LeafPosition(this, -1), true)); @@ -154,9 +154,8 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public void getWordChars(StringBuffer sbChars, Position bp) { - sbChars.append - (((org.apache.fop.area.inline.TextArea) curArea).getText()); + public String getWordChars(Position pos) { + return ((TextArea) curArea).getText(); } /** {@inheritDoc} */ @@ -189,10 +188,9 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { addKnuthElementsForBorderPaddingStart(returnList); - if (letterSpaceIPD.min == letterSpaceIPD.max - || areaInfo.iLScount == 0) { + if (letterSpaceIPD.isStiff() || areaInfo.iLScount == 0) { // constant letter space, or no letter space - returnList.add(new KnuthInlineBox(areaInfo.ipdArea.opt, + returnList.add(new KnuthInlineBox(areaInfo.ipdArea.getOpt(), areaInfo.alignmentContext, notifyPos(new LeafPosition(this, 0)), false)); if (areaInfo.bHyphenated) { @@ -202,24 +200,17 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { } } else { // adjustable letter space - returnList.add - (new KnuthInlineBox(areaInfo.ipdArea.opt - - areaInfo.iLScount * letterSpaceIPD.opt, - areaInfo.alignmentContext, - notifyPos(new LeafPosition(this, 0)), false)); + returnList.add(new KnuthInlineBox(areaInfo.ipdArea.getOpt() + - areaInfo.iLScount * letterSpaceIPD.getOpt(), areaInfo.alignmentContext, + notifyPos(new LeafPosition(this, 0)), false)); returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); - returnList.add - (new KnuthGlue(areaInfo.iLScount * letterSpaceIPD.opt, - areaInfo.iLScount * letterSpaceIPD.max - letterSpaceIPD.opt, - areaInfo.iLScount * letterSpaceIPD.opt - letterSpaceIPD.min, - new LeafPosition(this, -1), true)); - returnList.add(new KnuthInlineBox(0, null, - notifyPos(new LeafPosition(this, -1)), true)); + new LeafPosition(this, -1), true)); + returnList.add(new KnuthGlue(letterSpaceIPD.mult(areaInfo.iLScount), + new LeafPosition(this, -1), true)); + returnList.add(new KnuthInlineBox(0, null, notifyPos(new LeafPosition(this, -1)), true)); if (areaInfo.bHyphenated) { - returnList.add - (new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true, - new LeafPosition(this, -1), false)); + returnList.add(new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true, + new LeafPosition(this, -1), false)); } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index 4680f642e..d0dcc2bb8 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -296,7 +296,8 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager log.warn(this.getClass().getName() + " should not receive a call to removeWordSpace(list)"); } - public void getWordChars(StringBuffer sbChars, Position pos) { + public String getWordChars(Position pos) { + return ""; } public void hyphenate(Position pos, HyphContext hc) { diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index 6e0c34a82..26f8e3b97 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -19,6 +19,7 @@ package org.apache.fop.layoutmgr.inline; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -144,7 +145,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { padding += borderProps.getPadding(CommonBorderPaddingBackground.AFTER, false, this); padding += borderProps.getBorderWidth(CommonBorderPaddingBackground.AFTER, false); } - extraBPD = new MinOptMax(padding); + extraBPD = MinOptMax.getInstance(padding); } @@ -161,7 +162,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { borderAndPadding += borderProps.getBorderWidth(CommonBorderPaddingBackground.END, isNotLast); } - return new MinOptMax(borderAndPadding); + return MinOptMax.getInstance(borderAndPadding); } @@ -325,16 +326,20 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { KnuthSequence sequence = (KnuthSequence) seqIter.next(); sequence.wrapPositions(this); } + int insertionStartIndex = 0; if (lastSequence != null && lastSequence.appendSequenceOrClose ((KnuthSequence) returnedList.get(0))) { - returnedList.remove(0); + insertionStartIndex = 1; } // add border and padding to the first complete sequence of this LM if (!borderAdded && !returnedList.isEmpty()) { addKnuthElementsForBorderPaddingStart((KnuthSequence) returnedList.get(0)); borderAdded = true; } - returnList.addAll(returnedList); + for (Iterator iter = returnedList.listIterator(insertionStartIndex); + iter.hasNext();) { + returnList.add(iter.next()); + } } else { // A block LM BlockKnuthSequence sequence = new BlockKnuthSequence(returnedList); sequence.wrapPositions(this); @@ -488,8 +493,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { boolean isLast = (getContext().isLastArea() && prevLM == lastChildLM); if (hasTrailingFence(isLast)) { - addSpace(getCurrentArea(), - getContext().getTrailingSpace().resolve(false), + addSpace(getCurrentArea(), getContext().getTrailingSpace().resolve(false), getContext().getSpaceAdjust()); context.setTrailingSpace(new SpaceSpecifier(false)); } else { @@ -504,7 +508,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { // Not sure if lastPos can legally be null or if that masks a different problem. // But it seems to fix bug 38053. setTraits(areaCreated, lastPos == null || !isLast(lastPos)); - parentLM.addChildArea(getCurrentArea()); + parentLayoutManager.addChildArea(getCurrentArea()); addMarkersToPage( false, @@ -520,8 +524,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { public void addChildArea(Area childArea) { Area parent = getCurrentArea(); if (getContext().resolveLeadingSpace()) { - addSpace(parent, - getContext().getLeadingSpace().resolve(false), + addSpace(parent, getContext().getLeadingSpace().resolve(false), getContext().getSpaceAdjust()); } parent.addChildArea(childArea); diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLevelLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLevelLayoutManager.java index b080f926b..525f0407d 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLevelLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLevelLayoutManager.java @@ -48,20 +48,19 @@ public interface InlineLevelLayoutManager extends LayoutManager { void removeWordSpace(List oldList); /** - * Get the word chars corresponding to the given position + * Get the word chars corresponding to the given position. * - * @param sbChars the StringBuffer used to append word chars - * @param pos the Position referring to the needed word chars + * @param pos the position referring to the needed word chars. */ - void getWordChars(StringBuffer sbChars, Position pos); + String getWordChars(Position pos); /** * Tell the LM to hyphenate a word * * @param pos the Position referring to the word - * @param hc the HyphContext storing hyphenation information + * @param hyphContext the HyphContext storing hyphenation information */ - void hyphenate(Position pos, HyphContext hc); + void hyphenate(Position pos, HyphContext hyphContext); /** * Tell the LM to apply the changes due to hyphenation diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java index 65e59554f..375afb82f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java @@ -80,7 +80,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager */ protected InlineStackingLayoutManager(FObj node) { super(node); - extraBPD = new MinOptMax(0); + extraBPD = MinOptMax.ZERO; } /** @@ -100,7 +100,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager * @return the extra IPD as a MinOptMax spec */ protected MinOptMax getExtraIPD(boolean bNotFirst, boolean bNotLast) { - return new MinOptMax(0); + return MinOptMax.ZERO; } @@ -179,23 +179,21 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager } /** - * Adds a space to the area + * Adds a space to the area. + * * @param parentArea the area to which to add the space * @param spaceRange the space range specifier - * @param dSpaceAdjust the factor by which to stretch or shrink the space + * @param spaceAdjust the factor by which to stretch or shrink the space */ - protected void addSpace(Area parentArea, MinOptMax spaceRange, - double dSpaceAdjust) { + protected void addSpace(Area parentArea, MinOptMax spaceRange, double spaceAdjust) { if (spaceRange != null) { - int iAdjust = spaceRange.opt; - if (dSpaceAdjust > 0.0) { + int iAdjust = spaceRange.getOpt(); + if (spaceAdjust > 0.0) { // Stretch by factor - iAdjust += (int) ((double) (spaceRange.max - - spaceRange.opt) * dSpaceAdjust); - } else if (dSpaceAdjust < 0.0) { + iAdjust += (int) (spaceRange.getStretch() * spaceAdjust); + } else if (spaceAdjust < 0.0) { // Shrink by factor - iAdjust += (int) ((double) (spaceRange.opt - - spaceRange.min) * dSpaceAdjust); + iAdjust += (int) (spaceRange.getShrink() * spaceAdjust); } if (iAdjust != 0) { //getLogger().debug("Add leading space: " + iAdjust); @@ -257,10 +255,9 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager } /** {@inheritDoc} */ - public void getWordChars(StringBuffer sbChars, Position pos) { + public String getWordChars(Position pos) { Position newPos = pos.getPosition(); - ((InlineLevelLayoutManager) - newPos.getLM()).getWordChars(sbChars, newPos); + return ((InlineLevelLayoutManager) newPos.getLM()).getWordChars(newPos); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java b/src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java index 6c8c7354b..7b08a67db 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java +++ b/src/java/org/apache/fop/layoutmgr/inline/KnuthInlineBox.java @@ -19,7 +19,6 @@ package org.apache.fop.layoutmgr.inline; -import org.apache.fop.layoutmgr.inline.AlignmentContext; import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.Position; @@ -32,13 +31,13 @@ public class KnuthInlineBox extends KnuthBox { /** * Create a new KnuthBox. * - * @param w the width of this box + * @param width the width of this box * @param alignmentContext the alignmentContext for this box - * @param pos the Position stored in this box - * @param bAux is this box auxiliary? + * @param pos the Position stored in this box + * @param auxiliary is this box auxiliary? */ - public KnuthInlineBox(int w, AlignmentContext alignmentContext, Position pos, boolean bAux) { - super(w, pos, bAux); + public KnuthInlineBox(int width, AlignmentContext alignmentContext, Position pos, boolean auxiliary) { + super(width, pos, auxiliary); this.alignmentContext = alignmentContext; } @@ -69,11 +68,4 @@ public class KnuthInlineBox extends KnuthBox { public boolean isAnchor() { return (footnoteBodyLM != null); } - - - /** {@inheritDoc} */ - public String toString() { - StringBuffer sb = new StringBuffer(super.toString()); - return sb.toString(); - } -}
\ No newline at end of file +} diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index fe82245b9..c5f38134b 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -19,6 +19,7 @@ package org.apache.fop.layoutmgr.inline; +import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -109,7 +110,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { - borderPaddingWidth; int max = fobj.getLeaderLength().getMaximum(this).getLength().getValue(this) - borderPaddingWidth; - return new MinOptMax(min, opt, max); + return MinOptMax.getInstance(min, opt, max); } private InlineArea getLeaderInlineArea(LayoutContext context) { @@ -226,7 +227,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { KnuthPossPosIter contentIter = new KnuthPossPosIter(contentList, 0, contentList.size()); clm.addAreas(contentIter, context); - parentLM.addChildArea(curArea); + parentLayoutManager.addChildArea(curArea); while (posIter.hasNext()) { posIter.next(); @@ -235,8 +236,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public List getNextKnuthElements(LayoutContext context, - int alignment) { + public List getNextKnuthElements(LayoutContext context, int alignment) { MinOptMax ipd; curArea = get(context); KnuthSequence seq = new InlineKnuthSequence(); @@ -256,45 +256,34 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { ipd = getAllocationIPD(context.getRefIPD()); if (fobj.getLeaderPattern() == EN_USECONTENT && curArea instanceof FilledArea) { // If we have user supplied content make it fit if we can - int unitWidth = ((FilledArea)curArea).getUnitWidth(); - if (ipd.opt < unitWidth && ipd.max >= unitWidth) { - ipd.opt = unitWidth; + int unitWidth = ((FilledArea) curArea).getUnitWidth(); + if (ipd.getOpt() < unitWidth && unitWidth <= ipd.getMax()) { + ipd = MinOptMax.getInstance(ipd.getMin(), unitWidth, ipd.getMax()); } } // create the AreaInfo object to store the computed values areaInfo = new AreaInfo((short) 0, ipd, false, context.getAlignmentContext()); - curArea.setAdjustingInfo(ipd.max - ipd.opt, ipd.opt - ipd.min, 0); + curArea.setAdjustingInfo(ipd.getStretch(), ipd.getShrink(), 0); addKnuthElementsForBorderPaddingStart(seq); // node is a fo:Leader - seq.add(new KnuthInlineBox(0, alignmentContext, - new LeafPosition(this, -1), true)); + seq.add(new KnuthInlineBox(0, alignmentContext, new LeafPosition(this, -1), true)); seq.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, - new LeafPosition(this, -1), true)); + new LeafPosition(this, -1), true)); if (alignment == EN_JUSTIFY || alignment == 0) { - seq.add - (new KnuthGlue(areaInfo.ipdArea.opt, - areaInfo.ipdArea.max - areaInfo.ipdArea.opt, - areaInfo.ipdArea.opt - areaInfo.ipdArea.min, - new LeafPosition(this, 0), false)); + seq.add(new KnuthGlue(areaInfo.ipdArea, new LeafPosition(this, 0), false)); } else { - seq.add - (new KnuthGlue(areaInfo.ipdArea.opt, - 0, - 0, - new LeafPosition(this, 0), false)); + seq.add(new KnuthGlue(areaInfo.ipdArea.getOpt(), 0, 0, + new LeafPosition(this, 0), false)); } - seq.add(new KnuthInlineBox(0, alignmentContext, - new LeafPosition(this, -1), true)); + seq.add(new KnuthInlineBox(0, alignmentContext, new LeafPosition(this, -1), true)); addKnuthElementsForBorderPaddingEnd(seq); - LinkedList returnList = new LinkedList(); - returnList.add(seq); setFinished(true); - return returnList; + return Collections.singletonList(seq); } /** {@inheritDoc} */ @@ -310,8 +299,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { } /** {@inheritDoc} */ - public List getChangedKnuthElements(List oldList, - int alignment) { + public List getChangedKnuthElements(List oldList, int alignment) { if (isFinished()) { return null; } @@ -325,17 +313,10 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, new LeafPosition(this, -1), true)); if (alignment == EN_JUSTIFY || alignment == 0) { - returnList.add - (new KnuthGlue(areaInfo.ipdArea.opt, - areaInfo.ipdArea.max - areaInfo.ipdArea.opt, - areaInfo.ipdArea.opt - areaInfo.ipdArea.min, - new LeafPosition(this, 0), false)); + returnList.add(new KnuthGlue(areaInfo.ipdArea, new LeafPosition(this, 0), false)); } else { - returnList.add - (new KnuthGlue(areaInfo.ipdArea.opt, - 0, - 0, - new LeafPosition(this, 0), false)); + returnList.add(new KnuthGlue(areaInfo.ipdArea.getOpt(), 0, 0, + new LeafPosition(this, 0), false)); } returnList.add(new KnuthInlineBox(0, areaInfo.alignmentContext, new LeafPosition(this, -1), true)); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index ac501abb7..e74b51d96 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr.inline; import java.util.LinkedList; import java.util.List; +import java.util.Collections; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -163,7 +164,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager * @return the min/opt/max ipd of the inline area */ protected MinOptMax getAllocationIPD(int refIPD) { - return new MinOptMax(curArea.getIPD()); + return MinOptMax.getInstance(curArea.getIPD()); } /** @@ -186,7 +187,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager false, false, this); TraitSetter.addBackground(area, commonBorderPaddingBackground, this); } - parentLM.addChildArea(area); + parentLayoutManager.addChildArea(area); } while (posIter.hasNext()) { @@ -236,16 +237,14 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager */ protected void widthAdjustArea(InlineArea area, LayoutContext context) { double dAdjust = context.getIPDAdjust(); - int width = areaInfo.ipdArea.opt; + int adjustment = 0; if (dAdjust < 0) { - width = (int) (width + dAdjust * (areaInfo.ipdArea.opt - - areaInfo.ipdArea.min)); + adjustment += (int) (dAdjust * areaInfo.ipdArea.getShrink()); } else if (dAdjust > 0) { - width = (int) (width + dAdjust * (areaInfo.ipdArea.max - - areaInfo.ipdArea.opt)); + adjustment += (int) (dAdjust * areaInfo.ipdArea.getStretch()); } - area.setIPD(width); - area.setAdjustment(width - areaInfo.ipdArea.opt); + area.setIPD(areaInfo.ipdArea.getOpt() + adjustment); + area.setAdjustment(adjustment); } /** {@inheritDoc} */ @@ -270,16 +269,13 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager addKnuthElementsForBorderPaddingStart(seq); - seq.add(new KnuthInlineBox(areaInfo.ipdArea.opt, alignmentContext, + seq.add(new KnuthInlineBox(areaInfo.ipdArea.getOpt(), alignmentContext, notifyPos(new LeafPosition(this, 0)), false)); addKnuthElementsForBorderPaddingEnd(seq); - LinkedList returnList = new LinkedList(); - - returnList.add(seq); setFinished(true); - return returnList; + return Collections.singletonList(seq); } /** {@inheritDoc} */ @@ -299,11 +295,12 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager } /** {@inheritDoc} */ - public void getWordChars(StringBuffer sbChars, Position pos) { + public String getWordChars(Position pos) { + return ""; } /** {@inheritDoc} */ - public void hyphenate(Position pos, HyphContext hc) { + public void hyphenate(Position pos, HyphContext hyphContext) { } /** {@inheritDoc} */ @@ -325,7 +322,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager // fobj is a fo:ExternalGraphic, fo:InstreamForeignObject, // fo:PageNumber or fo:PageNumberCitation - returnList.add(new KnuthInlineBox(areaInfo.ipdArea.opt, areaInfo.alignmentContext, + returnList.add(new KnuthInlineBox(areaInfo.ipdArea.getOpt(), areaInfo.alignmentContext, notifyPos(new LeafPosition(this, 0)), true)); addKnuthElementsForBorderPaddingEnd(returnList); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 0b95ef859..0ece70cac 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -43,6 +43,7 @@ import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.hyphenation.Hyphenation; import org.apache.fop.hyphenation.Hyphenator; +import org.apache.fop.layoutmgr.Adjustment; import org.apache.fop.layoutmgr.BlockLevelLayoutManager; import org.apache.fop.layoutmgr.BreakElement; import org.apache.fop.layoutmgr.BreakingAlgorithm; @@ -235,11 +236,10 @@ public class LineLayoutManager extends InlineStackingLayoutManager // set the minimum amount of empty space at the end of the // last line if (textAlignment == EN_CENTER) { - lineFiller = new MinOptMax(lastLineEndIndent); + lineFiller = MinOptMax.getInstance(lastLineEndIndent); } else { - lineFiller = new MinOptMax(lastLineEndIndent, - lastLineEndIndent, - layoutManager.ipd); + lineFiller = MinOptMax.getInstance(lastLineEndIndent, lastLineEndIndent, + layoutManager.ipd); } // add auxiliary elements at the beginning of the paragraph @@ -272,7 +272,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager && textAlignmentLast != EN_JUSTIFY) { this.add(new KnuthGlue(0, 3 * DEFAULT_SPACE_WIDTH, 0, null, false)); - this.add(new KnuthPenalty(lineFiller.opt, -KnuthElement.INFINITE, + this.add(new KnuthPenalty(lineFiller.getOpt(), -KnuthElement.INFINITE, false, null, false)); ignoreAtEnd = 2; } else if (textAlignmentLast != EN_JUSTIFY) { @@ -282,14 +282,14 @@ public class LineLayoutManager extends InlineStackingLayoutManager this.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, null, false)); this.add(new KnuthGlue(0, - lineFiller.max - lineFiller.opt, - lineFiller.opt - lineFiller.min, null, false)); - this.add(new KnuthPenalty(lineFiller.opt, -KnuthElement.INFINITE, + lineFiller.getStretch(), + lineFiller.getShrink(), null, false)); + this.add(new KnuthPenalty(lineFiller.getOpt(), -KnuthElement.INFINITE, false, null, false)); ignoreAtEnd = 3; } else { // add only the element representing the forced break - this.add(new KnuthPenalty(lineFiller.opt, -KnuthElement.INFINITE, + this.add(new KnuthPenalty(lineFiller.getOpt(), -KnuthElement.INFINITE, false, null, false)); ignoreAtEnd = 1; } @@ -393,7 +393,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager (bestActiveNode.line > 1 ? bestActiveNode.previous.position + 1 : 0), bestActiveNode.position, bestActiveNode.availableShrink - (addedPositions > 0 - ? 0 : ((Paragraph)par).lineFiller.opt - ((Paragraph)par).lineFiller.min), + ? 0 : ((Paragraph) par).lineFiller.getShrink()), bestActiveNode.availableStretch, difference, ratio, indent), activePossibility); addedPositions++; @@ -784,7 +784,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager int iBPcount = 0; LineBreakingAlgorithm alg = new LineBreakingAlgorithm(alignment, textAlignment, textAlignmentLast, - textIndent.getValue(this), currPar.lineFiller.opt, + textIndent.getValue(this), currPar.lineFiller.getOpt(), lineHeight.getValue(this), lead, follow, (knuthParagraphs.indexOf(currPar) == 0), hyphenationLadderCount.getEnum() == EN_NO_LIMIT @@ -1057,12 +1057,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager breaker.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false)); breaker.add(new KnuthGlue(0, -nConditionalOptionalLines * constantLineHeight, -nConditionalEliminableLines * constantLineHeight, - LINE_NUMBER_ADJUSTMENT, elementPosition, false)); + Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false)); breaker.add(new KnuthPenalty(nConditionalOptionalLines * constantLineHeight, 0, false, elementPosition, false)); breaker.add(new KnuthGlue(0, nConditionalOptionalLines * constantLineHeight, nConditionalEliminableLines * constantLineHeight, - LINE_NUMBER_ADJUSTMENT, elementPosition, false)); + Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false)); } else if (nLastLines != 0) { breaker.add(new KnuthPenalty(0, 0, false, elementPosition, false)); } @@ -1083,7 +1083,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager list.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false)); list.add(new KnuthGlue(0, nConditionalOptionalLines * constantLineHeight, nConditionalEliminableLines * constantLineHeight, - LINE_NUMBER_ADJUSTMENT, elementPosition, false)); + Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false)); list.add(new KnuthBox(0, elementPosition, (nLastLines == 0 ? true : false))); } @@ -1094,7 +1094,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager list.add(new KnuthBox(0, elementPosition, false)); list.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false)); list.add(new KnuthGlue(0, 1 * constantLineHeight, 0, - LINE_NUMBER_ADJUSTMENT, elementPosition, false)); + Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false)); list.add(new KnuthBox(0, elementPosition, false)); } @@ -1104,7 +1104,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager list.add(new KnuthBox(1 * constantLineHeight, elementPosition, false)); list.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false)); list.add(new KnuthGlue(0, 0, 1 * constantLineHeight, - LINE_NUMBER_ADJUSTMENT, elementPosition, false)); + Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false)); list.add(new KnuthBox(0, elementPosition, false)); } @@ -1200,7 +1200,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager llPoss = (LineLayoutPossibilities)lineLayoutsList.get(p); //log.debug("demerits of the chosen layout: " + llPoss.getChosenDemerits()); for (int i = 0; i < llPoss.getChosenLineCount(); i++) { - if (!((BlockLevelLayoutManager) parentLM).mustKeepTogether() + if (!((BlockLevelLayoutManager) parentLayoutManager).mustKeepTogether() && i >= fobj.getOrphans() && i <= llPoss.getChosenLineCount() - fobj.getWidows()) { // null penalty allowing a page break between lines @@ -1213,21 +1213,19 @@ public class LineLayoutManager extends InlineStackingLayoutManager //log.debug("linewidth= " + lbp.lineWidth + " difference= " + lbp.difference + " indent= " + lbp.startIndent); MinOptMax contentIPD; if (alignment == EN_JUSTIFY) { - contentIPD = new MinOptMax( + contentIPD = MinOptMax.getInstance( lbp.lineWidth - lbp.difference - lbp.availableShrink, lbp.lineWidth - lbp.difference, lbp.lineWidth - lbp.difference + lbp.availableStretch); } else if (alignment == EN_CENTER) { - contentIPD = new MinOptMax(lbp.lineWidth - 2 * lbp.startIndent); + contentIPD = MinOptMax.getInstance(lbp.lineWidth - 2 * lbp.startIndent); } else if (alignment == EN_END) { - contentIPD = new MinOptMax(lbp.lineWidth - lbp.startIndent); + contentIPD = MinOptMax.getInstance(lbp.lineWidth - lbp.startIndent); } else { - contentIPD = new MinOptMax(lbp.lineWidth - lbp.difference + lbp.startIndent); + contentIPD = MinOptMax.getInstance(lbp.lineWidth - lbp.difference + lbp.startIndent); } - returnList.add(new KnuthBlockBox(lbp.lineHeight, - contentIPD, - (lbp.ipdAdjust != 0 - ? lbp.lineWidth - lbp.difference : 0), + returnList.add(new KnuthBlockBox(lbp.lineHeight, contentIPD, (lbp.ipdAdjust != 0 + ? lbp.lineWidth - lbp.difference : 0), lbp, false)); } } @@ -1277,7 +1275,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager boxCount = 1; auxCount = 0; sbChars = new StringBuffer(); - currLM.getWordChars(sbChars, firstElement.getPosition()); + sbChars.append(currLM.getWordChars(firstElement.getPosition())); // look if next elements are boxes too while (currParIterator.hasNext()) { nextElement = (KnuthElement) currParIterator.next(); @@ -1289,7 +1287,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager } // append text to recreate the whole word boxCount++; - currLM.getWordChars(sbChars, nextElement.getPosition()); + sbChars.append(currLM.getWordChars(nextElement.getPosition())); } else if (!nextElement.isAuxiliary()) { // a non-auxiliary non-box KnuthElement: stop // go back to the last box or auxiliary element @@ -1583,7 +1581,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter()); } lineArea.finalise(); - parentLM.addChildArea(lineArea); + parentLayoutManager.addChildArea(lineArea); } /** @@ -1633,7 +1631,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager blocklc.setTrailingSpace(new SpaceSpecifier(false)); } lineArea.updateExtentsFromChildren(); - parentLM.addChildArea(lineArea); + parentLayoutManager.addChildArea(lineArea); } /** @@ -1644,9 +1642,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager if (childArea instanceof InlineArea) { Area parent = getCurrentArea(); if (getContext().resolveLeadingSpace()) { - addSpace(parent, - getContext().getLeadingSpace().resolve(false), - getContext().getSpaceAdjust()); + addSpace(parent, getContext().getLeadingSpace().resolve(false), + getContext().getSpaceAdjust()); } parent.addChildArea(childArea); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java index d33f2cca1..a38e3e2d8 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java @@ -46,7 +46,7 @@ public class PageNumberCitationLastLayoutManager extends AbstractPageNumberCitat /** {@inheritDoc} */ public InlineArea get(LayoutContext context) { - curArea = getPageNumberCitationLastInlineArea(parentLM); + curArea = getPageNumberCitationLastInlineArea(parentLayoutManager); return curArea; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java index 5cae07207..d8cfe6cda 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java @@ -116,7 +116,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { // update the ipd of the area area.handleIPDVariation(getStringWidth(area.getText()) - area.getIPD()); // update the width stored in the AreaInfo object - areaInfo.ipdArea = new MinOptMax(area.getIPD()); + areaInfo.ipdArea = MinOptMax.getInstance(area.getIPD()); } /** diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index f793bb3bb..43e8c5a31 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -19,6 +19,7 @@ package org.apache.fop.layoutmgr.inline; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; @@ -59,6 +60,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { //TODO: remove all final modifiers at local variables + // static final int SOFT_HYPHEN_PENALTY = KnuthPenalty.FLAGGED_PENALTY / 10; + private static final int SOFT_HYPHEN_PENALTY = 1; + /** * Store information about each potential text area. * Index of character which ends the area, IPD of area, including @@ -66,25 +70,27 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * Number of word-spaces? */ private class AreaInfo { + private final int startIndex; private final int breakIndex; private final int wordSpaceCount; private int letterSpaceCount; - private final MinOptMax areaIPD; + private MinOptMax areaIPD; private final boolean isHyphenated; private final boolean isSpace; private boolean breakOppAfter; private final Font font; AreaInfo(final int startIndex, - final int breakIndex, - final int wordSpaceCount, - final int letterSpaceCount, - final MinOptMax areaIPD, - final boolean isHyphenated, - final boolean isSpace, - final boolean breakOppAfter, - final Font font) { + final int breakIndex, + final int wordSpaceCount, + final int letterSpaceCount, + final MinOptMax areaIPD, + final boolean isHyphenated, + final boolean isSpace, + final boolean breakOppAfter, + final Font font) { + assert startIndex <= breakIndex; this.startIndex = startIndex; this.breakIndex = breakIndex; this.wordSpaceCount = wordSpaceCount; @@ -96,28 +102,38 @@ public class TextLayoutManager extends LeafNodeLayoutManager { this.font = font; } - public String toString() { - return "[ lscnt=" + this.letterSpaceCount - + ", wscnt=" + this.wordSpaceCount - + ", ipd=" + this.areaIPD.toString() - + ", sidx=" + this.startIndex - + ", bidx=" + this.breakIndex - + ", hyph=" + this.isHyphenated - + ", space=" + this.isSpace - + ", font=" + this.font - + "]"; + private int getCharLength() { + return breakIndex - startIndex; + } + + private void addToAreaIPD(MinOptMax idp) { + areaIPD = areaIPD.plus(idp); } + public String toString() { + return "AreaInfo[" + + "letterSpaceCount = " + letterSpaceCount + + ", wordSpaceCount = " + wordSpaceCount + + ", areaIPD = " + areaIPD + + ", startIndex = " + startIndex + + ", breakIndex = " + breakIndex + + ", isHyphenated = " + isHyphenated + + ", isSpace = " + isSpace + + ", font = " + font + + "]"; + } } - // this class stores information about changes in vecAreaInfo - // which are not yet applied + /** + * this class stores information about changes in vecAreaInfo which are not yet applied + */ private final class PendingChange { - private final AreaInfo ai; + + private final AreaInfo areaInfo; private final int index; - private PendingChange(final AreaInfo ai, final int index) { - this.ai = ai; + private PendingChange(final AreaInfo areaInfo, final int index) { + this.areaInfo = areaInfo; this.index = index; } } @@ -128,14 +144,11 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private static final Log LOG = LogFactory.getLog(TextLayoutManager.class); // Hold all possible breaks for the text in this LM's FO. - private final List vecAreaInfo; + private final List areaInfos; /** Non-space characters on which we can end a line. */ private static final String BREAK_CHARS = "-/"; - /** Used to reduce instantiation of MinOptMax with zero length. Do not modify! */ - private static final MinOptMax ZERO_MINOPTMAX = new MinOptMax(0); - private final FOText foText; /** @@ -155,18 +168,23 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private MinOptMax letterSpaceIPD; /** size of the hyphen character glyph in current font */ private int hyphIPD; - /** 1/1 of word-spacing value */ - private SpaceVal ws; private boolean hasChanged = false; private int returnedIndex = 0; private int thisStart = 0; private int tempStart = 0; - private List changeList = null; + private List changeList = new LinkedList(); private AlignmentContext alignmentContext = null; + /** + * The width to be reserved for border and padding at the start of the line. + */ private int lineStartBAP = 0; + + /** + * The width to be reserved for border and padding at the end of the line. + */ private int lineEndBAP = 0; private boolean keepTogether; @@ -178,49 +196,37 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * * @param node The FOText object to be rendered */ - public TextLayoutManager(final FOText node) { - super(); - this.foText = node; - - this.letterAdjustArray = new MinOptMax[node.length() + 1]; - - this.vecAreaInfo = new java.util.ArrayList(); + public TextLayoutManager(FOText node) { + foText = node; + letterAdjustArray = new MinOptMax[node.length() + 1]; + areaInfos = new ArrayList(); } - private KnuthPenalty makeZeroWidthPenalty(final int penaltyValue) { - return new KnuthPenalty( - 0, - penaltyValue, - false, - this.auxiliaryPosition, - true); + private KnuthPenalty makeZeroWidthPenalty(int penaltyValue) { + return new KnuthPenalty(0, penaltyValue, false, auxiliaryPosition, true); } private KnuthBox makeAuxiliaryZeroWidthBox() { - return new KnuthInlineBox( - 0, - null, - this.notifyPos(new LeafPosition(this, -1)), - true); + return new KnuthInlineBox(0, null, notifyPos(new LeafPosition(this, -1)), true); } /** {@inheritDoc} */ public void initialize() { - this.foText.resetBuffer(); + foText.resetBuffer(); - this.spaceFont = FontSelector.selectFontForCharacterInText(' ', this.foText, this); + spaceFont = FontSelector.selectFontForCharacterInText(' ', foText, this); - // With CID fonts, space isn't neccesary currentFontState.width(32) - this.spaceCharIPD = this.spaceFont.getCharWidth(' '); - // Use hyphenationChar property + // With CID fonts, space isn't necessary currentFontState.width(32) + spaceCharIPD = spaceFont.getCharWidth(' '); + // Use hyphenationChar property // TODO: Use hyphen based on actual font used! - this.hyphIPD = this.foText.getCommonHyphenation().getHyphIPD(this.spaceFont); + hyphIPD = foText.getCommonHyphenation().getHyphIPD(spaceFont); - final SpaceVal ls = SpaceVal.makeLetterSpacing(this.foText.getLetterSpacing()); - - this.ws = SpaceVal.makeWordSpacing(this.foText.getWordSpacing(), ls, this.spaceFont); + SpaceVal letterSpacing = SpaceVal.makeLetterSpacing(foText.getLetterSpacing()); + SpaceVal wordSpacing = SpaceVal.makeWordSpacing(foText.getWordSpacing(), letterSpacing, + spaceFont); // letter space applies only to consecutive non-space characters, // while word space applies to space characters; @@ -233,12 +239,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // set letter space and word space dimension; // the default value "normal" was converted into a MinOptMax value // in the SpaceVal.makeWordSpacing() method - this.letterSpaceIPD = ls.getSpace(); - this.wordSpaceIPD = MinOptMax.add(new MinOptMax(this.spaceCharIPD), this.ws.getSpace()); - - this.keepTogether = this.foText.getKeepTogether().getWithinLine() - .getEnum() == Constants.EN_ALWAYS; - + letterSpaceIPD = letterSpacing.getSpace(); + wordSpaceIPD = MinOptMax.getInstance(spaceCharIPD).plus(wordSpacing.getSpace()); + keepTogether = foText.getKeepTogether().getWithinLine().getEnum() == Constants.EN_ALWAYS; } /** @@ -254,111 +257,103 @@ public class TextLayoutManager extends LeafNodeLayoutManager { public void addAreas(final PositionIterator posIter, final LayoutContext context) { // Add word areas - AreaInfo ai; + AreaInfo areaInfo; int wordSpaceCount = 0; int letterSpaceCount = 0; int firstAreaInfoIndex = -1; int lastAreaInfoIndex = 0; - MinOptMax realWidth = new MinOptMax(0); + MinOptMax realWidth = MinOptMax.ZERO; /* On first area created, add any leading space. * Calculate word-space stretch value. */ - AreaInfo lastAi = null; + AreaInfo lastAreaInfo = null; while (posIter.hasNext()) { final LeafPosition tbpNext = (LeafPosition) posIter.next(); if (tbpNext == null) { continue; //Ignore elements without Positions } if (tbpNext.getLeafPos() != -1) { - ai = (AreaInfo) this.vecAreaInfo.get(tbpNext.getLeafPos()); - if (lastAi == null || ai.font != lastAi.font) { - if (lastAi != null) { - this.addAreaInfoAreas(lastAi, wordSpaceCount, + areaInfo = (AreaInfo) areaInfos.get(tbpNext.getLeafPos()); + if (lastAreaInfo == null || areaInfo.font != lastAreaInfo.font) { + if (lastAreaInfo != null) { + addAreaInfoAreas(lastAreaInfo, wordSpaceCount, letterSpaceCount, firstAreaInfoIndex, lastAreaInfoIndex, realWidth, context); } firstAreaInfoIndex = tbpNext.getLeafPos(); wordSpaceCount = 0; letterSpaceCount = 0; - realWidth = new MinOptMax(0); + realWidth = MinOptMax.ZERO; } - wordSpaceCount += ai.wordSpaceCount; - letterSpaceCount += ai.letterSpaceCount; - realWidth.add(ai.areaIPD); + wordSpaceCount += areaInfo.wordSpaceCount; + letterSpaceCount += areaInfo.letterSpaceCount; + realWidth = realWidth.plus(areaInfo.areaIPD); lastAreaInfoIndex = tbpNext.getLeafPos(); - lastAi = ai; + lastAreaInfo = areaInfo; } } - if (lastAi != null) { - this.addAreaInfoAreas(lastAi, wordSpaceCount, letterSpaceCount, - firstAreaInfoIndex, lastAreaInfoIndex, realWidth, context); + if (lastAreaInfo != null) { + addAreaInfoAreas(lastAreaInfo, wordSpaceCount, letterSpaceCount, firstAreaInfoIndex, + lastAreaInfoIndex, realWidth, context); } } - private void addAreaInfoAreas(final AreaInfo ai, final int wordSpaceCount, - int letterSpaceCount, final int firstAreaInfoIndex, - final int lastAreaInfoIndex, final MinOptMax realWidth, final LayoutContext context) { + private void addAreaInfoAreas(AreaInfo areaInfo, int wordSpaceCount, int letterSpaceCount, + int firstAreaInfoIndex, int lastAreaInfoIndex, + MinOptMax realWidth, LayoutContext context) { // TODO: These two statements (if, for) were like this before my recent // changes. However, it seems as if they should use the AreaInfo from - // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last ai. + // firstAreaInfoIndex.. lastAreaInfoIndex rather than just the last areaInfo. // This needs to be checked. - final int textLength = ai.breakIndex - ai.startIndex; - if (ai.letterSpaceCount == textLength && !ai.isHyphenated - && context.isLastArea()) { + int textLength = areaInfo.getCharLength(); + if (areaInfo.letterSpaceCount == textLength && !areaInfo.isHyphenated + && context.isLastArea()) { // the line ends at a character like "/" or "-"; // remove the letter space after the last character - realWidth.add(MinOptMax.multiply(this.letterSpaceIPD, -1)); + realWidth = realWidth.minus(letterSpaceIPD); letterSpaceCount--; } - for (int i = ai.startIndex; i < ai.breakIndex; i++) { - final MinOptMax ladj = this.letterAdjustArray[i + 1]; - if (ladj != null && ladj.isElastic()) { + for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { + MinOptMax letterAdjustment = letterAdjustArray[i + 1]; + if (letterAdjustment != null && letterAdjustment.isElastic()) { letterSpaceCount++; } } // add hyphenation character if the last word is hyphenated - if (context.isLastArea() && ai.isHyphenated) { - realWidth.add(new MinOptMax(this.hyphIPD)); + if (context.isLastArea() && areaInfo.isHyphenated) { + realWidth = realWidth.plus(hyphIPD); } - // Calculate adjustments - int difference = 0; - int totalAdjust = 0; - int wordSpaceDim = this.wordSpaceIPD.opt; - int letterSpaceDim = this.letterSpaceIPD.opt; - final double ipdAdjust = context.getIPDAdjust(); + /* Calculate adjustments */ + double ipdAdjust = context.getIPDAdjust(); // calculate total difference between real and available width + int difference; if (ipdAdjust > 0.0) { - difference = (int) ((realWidth.max - realWidth.opt) - * ipdAdjust); + difference = (int) (realWidth.getStretch() * ipdAdjust); } else { - difference = (int) ((realWidth.opt - realWidth.min) - * ipdAdjust); + difference = (int) (realWidth.getShrink() * ipdAdjust); } // set letter space adjustment + int letterSpaceDim = letterSpaceIPD.getOpt(); if (ipdAdjust > 0.0) { - letterSpaceDim - += (int) ((this.letterSpaceIPD.max - this.letterSpaceIPD.opt) - * ipdAdjust); - } else { - letterSpaceDim - += (int) ((this.letterSpaceIPD.opt - this.letterSpaceIPD.min) - * ipdAdjust); + letterSpaceDim += (int) (letterSpaceIPD.getStretch() * ipdAdjust); + } else { + letterSpaceDim += (int) (letterSpaceIPD.getShrink() * ipdAdjust); } - totalAdjust += (letterSpaceDim - this.letterSpaceIPD.opt) * letterSpaceCount; + int totalAdjust = (letterSpaceDim - letterSpaceIPD.getOpt()) * letterSpaceCount; // set word space adjustment - // + int wordSpaceDim = wordSpaceIPD.getOpt(); if (wordSpaceCount > 0) { wordSpaceDim += (difference - totalAdjust) / wordSpaceCount; } - totalAdjust += (wordSpaceDim - this.wordSpaceIPD.opt) * wordSpaceCount; + totalAdjust += (wordSpaceDim - wordSpaceIPD.getOpt()) * wordSpaceCount; if (totalAdjust != difference) { // the applied adjustment is greater or smaller than the needed one TextLayoutManager.LOG @@ -370,9 +365,8 @@ public class TextLayoutManager extends LeafNodeLayoutManager { totalAdjust = difference; } - final TextArea t = this.createTextArea(realWidth, totalAdjust, context, - this.wordSpaceIPD.opt - this.spaceCharIPD, firstAreaInfoIndex, - lastAreaInfoIndex, context.isLastArea(), ai.font); + TextArea textArea = new TextAreaBuilder(realWidth, totalAdjust, context, firstAreaInfoIndex, + lastAreaInfoIndex, context.isLastArea(), areaInfo.font).build(); // wordSpaceDim is computed in relation to wordSpaceIPD.opt // but the renderer needs to know the adjustment in relation @@ -386,133 +380,205 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // = spaceCharIPD + letterSpaceAdjust + // + (wordSpaceDim - spaceCharIPD - 2 * letterSpaceAdjust) // = wordSpaceDim - letterSpaceAdjust - t.setTextLetterSpaceAdjust(letterSpaceDim); - t.setTextWordSpaceAdjust(wordSpaceDim - this.spaceCharIPD - - 2 * t.getTextLetterSpaceAdjust()); + textArea.setTextLetterSpaceAdjust(letterSpaceDim); + textArea.setTextWordSpaceAdjust(wordSpaceDim - spaceCharIPD + - 2 * textArea.getTextLetterSpaceAdjust()); if (context.getIPDAdjust() != 0) { // add information about space width - t.setSpaceDifference(this.wordSpaceIPD.opt - this.spaceCharIPD - - 2 * t.getTextLetterSpaceAdjust()); + textArea.setSpaceDifference(wordSpaceIPD.getOpt() - spaceCharIPD + - 2 * textArea.getTextLetterSpaceAdjust()); } - this.parentLM.addChildArea(t); + parentLayoutManager.addChildArea(textArea); } - /** - * Create an inline word area. - * This creates a TextArea and sets up the various attributes. - * - * @param width the MinOptMax width of the content - * @param adjust the total ipd adjustment with respect to the optimal width - * @param context the layout context - * @param spaceDiff unused - * @param firstIndex the index of the first AreaInfo used for the TextArea - * @param lastIndex the index of the last AreaInfo used for the TextArea - * @param isLastArea is this TextArea the last in a line? - * @param font Font to be used in this particular TextArea - * @return the new text area - */ - protected TextArea createTextArea(final MinOptMax width, final int adjust, - final LayoutContext context, final int spaceDiff, final int firstIndex, - final int lastIndex, final boolean isLastArea, final Font font) { - TextArea textArea; - if (context.getIPDAdjust() == 0.0) { - // create just a TextArea - textArea = new TextArea(); - } else { - // justified area: create a TextArea with extra info - // about potential adjustments - textArea = new TextArea(width.max - width.opt, - width.opt - width.min, - adjust); + private final class TextAreaBuilder { + + private final MinOptMax width; + private final int adjust; + private final LayoutContext context; + private final int firstIndex; + private final int lastIndex; + private final boolean isLastArea; + private final Font font; + + private int blockProgressionDimension; + private AreaInfo areaInfo; + private StringBuffer wordChars; + private int[] letterAdjust; + private int letterAdjustIndex; + + private TextArea textArea; + + /** + * Creates a new <code>TextAreaBuilder</code> which itself builds an inline word area. This + * creates a TextArea and sets up the various attributes. + * + * @param width the MinOptMax width of the content + * @param adjust the total ipd adjustment with respect to the optimal width + * @param context the layout context + * @param firstIndex the index of the first AreaInfo used for the TextArea + * @param lastIndex the index of the last AreaInfo used for the TextArea + * @param isLastArea is this TextArea the last in a line? + * @param font Font to be used in this particular TextArea + */ + private TextAreaBuilder(MinOptMax width, int adjust, LayoutContext context, + int firstIndex, int lastIndex, boolean isLastArea, Font font) { + this.width = width; + this.adjust = adjust; + this.context = context; + this.firstIndex = firstIndex; + this.lastIndex = lastIndex; + this.isLastArea = isLastArea; + this.font = font; } - textArea.setIPD(width.opt + adjust); - textArea.setBPD(font.getAscender() - font.getDescender()); - textArea.setBaselineOffset(font.getAscender()); - if (textArea.getBPD() == this.alignmentContext.getHeight()) { - textArea.setOffset(0); - } else { - textArea.setOffset(this.alignmentContext.getOffset()); + private TextArea build() { + createTextArea(); + setInlineProgressionDimension(); + calcBlockProgressionDimension(); + setBlockProgressionDimension(); + setBaselineOffset(); + setOffset(); + setText(); + TraitSetter.addFontTraits(textArea, font); + textArea.addTrait(Trait.COLOR, foText.getColor()); + TraitSetter.addPtr(textArea, getPtr()); // used for accessibility + TraitSetter.addTextDecoration(textArea, foText.getTextDecoration()); + TraitSetter.addFontTraits(textArea, font); + return textArea; } - // set the text of the TextArea, split into words and spaces - int wordStartIndex = -1; - AreaInfo areaInfo; - int len = 0; - for (int i = firstIndex; i <= lastIndex; i++) { - areaInfo = (AreaInfo) this.vecAreaInfo.get(i); - if (areaInfo.isSpace) { - // areaInfo stores information about spaces - // add the spaces - except zero-width spaces - to the TextArea - for (int j = areaInfo.startIndex; j < areaInfo.breakIndex; j++) { - final char spaceChar = this.foText.charAt(j); - if (!CharUtilities.isZeroWidthSpace(spaceChar)) { - textArea.addSpace(spaceChar, 0, - CharUtilities.isAdjustableSpace(spaceChar)); - } - } + /** + * Creates an plain <code>TextArea</code> or a justified <code>TextArea</code> with + * additional information. + */ + private void createTextArea() { + if (context.getIPDAdjust() == 0.0) { + textArea = new TextArea(); } else { - // areaInfo stores information about a word fragment - if (wordStartIndex == -1) { - // here starts a new word - wordStartIndex = i; - len = 0; - } - len += areaInfo.breakIndex - areaInfo.startIndex; - if (i == lastIndex || ((AreaInfo) this.vecAreaInfo.get(i + 1)).isSpace) { - // here ends a new word - // add a word to the TextArea - if (isLastArea - && i == lastIndex - && areaInfo.isHyphenated) { - len++; - } - final StringBuffer wordChars = new StringBuffer(len); - final int[] letterAdjust = new int[len]; - int letter = 0; - for (int j = wordStartIndex; j <= i; j++) { - final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(j); - int lsCount = ai.letterSpaceCount; - /* TODO: in Java 5, StringBuffer has an append() variant - * for CharSequence, so the below iteration can be replaced - * by: - * wordChars.append(this.foText, ai.startIndex, - * ai.breakIndex - ai.startIndex); - */ - for (int ci = ai.startIndex; ci < ai.breakIndex; ci++) { - wordChars.append(this.foText.charAt(ci)); - } - for (int k = 0; k < ai.breakIndex - ai.startIndex; k++) { - final MinOptMax adj = this.letterAdjustArray[ai.startIndex + k]; - if (letter > 0) { - letterAdjust[letter] = adj == null ? 0 - : adj.opt; - } - if (lsCount > 0) { - letterAdjust[letter] += textArea.getTextLetterSpaceAdjust(); - lsCount--; - } - letter++; - } + textArea = new TextArea(width.getStretch(), width.getShrink(), + adjust); + } + } + + private void setInlineProgressionDimension() { + textArea.setIPD(width.getOpt() + adjust); + } + + private void calcBlockProgressionDimension() { + blockProgressionDimension = font.getAscender() - font.getDescender(); + } + + private void setBlockProgressionDimension() { + textArea.setBPD(blockProgressionDimension); + } + + private void setBaselineOffset() { + textArea.setBaselineOffset(font.getAscender()); + } + + private void setOffset() { + if (blockProgressionDimension == alignmentContext.getHeight()) { + textArea.setOffset(0); + } else { + textArea.setOffset(alignmentContext.getOffset()); + } + } + + /** + * Sets the text of the TextArea, split into words and spaces. + */ + private void setText() { + int wordStartIndex = -1; + int wordCharLength = 0; + for (int wordIndex = firstIndex; wordIndex <= lastIndex; wordIndex++) { + areaInfo = getAreaInfo(wordIndex); + if (areaInfo.isSpace) { + addSpaces(); + } else { + // areaInfo stores information about a word fragment + if (wordStartIndex == -1) { + // here starts a new word + wordStartIndex = wordIndex; + wordCharLength = 0; } - // String wordChars = new String(textArray, wordStartIndex, len); - if (isLastArea - && i == lastIndex - && areaInfo.isHyphenated) { - // add the hyphenation character - wordChars.append(this.foText.getCommonHyphenation().getHyphChar(font)); + wordCharLength += areaInfo.getCharLength(); + if (isWordEnd(wordIndex)) { + addWord(wordStartIndex, wordIndex, wordCharLength); + wordStartIndex = -1; } - textArea.addWord(wordChars.toString(), 0, letterAdjust); - wordStartIndex = -1; } } } - TraitSetter.addFontTraits(textArea, font); - textArea.addTrait(Trait.COLOR, this.foText.getColor()); - TraitSetter.addPtr(textArea, getPtr()); // used for accessibility - TraitSetter.addTextDecoration(textArea, this.foText.getTextDecoration()); - return textArea; + private boolean isWordEnd(int areaInfoIndex) { + return areaInfoIndex == lastIndex || getAreaInfo(areaInfoIndex + 1).isSpace; + } + + private void addWord(int startIndex, int endIndex, int charLength) { + if (isHyphenated(endIndex)) { + charLength++; + } + initWord(charLength); + for (int i = startIndex; i <= endIndex; i++) { + AreaInfo wordAreaInfo = getAreaInfo(i); + addWordChars(wordAreaInfo); + addLetterAdjust(wordAreaInfo); + } + if (isHyphenated(endIndex)) { + addHyphenationChar(); + } + textArea.addWord(wordChars.toString(), 0, letterAdjust); + } + + private void initWord(int charLength) { + wordChars = new StringBuffer(charLength); + letterAdjust = new int[charLength]; + letterAdjustIndex = 0; + } + + private boolean isHyphenated(int endIndex) { + return isLastArea && endIndex == lastIndex && areaInfo.isHyphenated; + } + + private void addHyphenationChar() { + wordChars.append(foText.getCommonHyphenation().getHyphChar(font)); + } + + private void addWordChars(AreaInfo wordAreaInfo) { + for (int i = wordAreaInfo.startIndex; i < wordAreaInfo.breakIndex; i++) { + wordChars.append(foText.charAt(i)); + } + } + + private void addLetterAdjust(AreaInfo wordAreaInfo) { + int letterSpaceCount = wordAreaInfo.letterSpaceCount; + for (int i = wordAreaInfo.startIndex; i < wordAreaInfo.breakIndex; i++) { + if (letterAdjustIndex > 0) { + MinOptMax adj = letterAdjustArray[i]; + letterAdjust[letterAdjustIndex] = adj == null ? 0 : adj.getOpt(); + } + if (letterSpaceCount > 0) { + letterAdjust[letterAdjustIndex] += textArea.getTextLetterSpaceAdjust(); + letterSpaceCount--; + } + letterAdjustIndex++; + } + } + + /** + * The <code>AreaInfo</code> stores information about spaces. + * <p/> + * Add the spaces - except zero-width spaces - to the TextArea. + */ + private void addSpaces() { + for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { + char spaceChar = foText.charAt(i); + if (!CharUtilities.isZeroWidthSpace(spaceChar)) { + textArea.addSpace(spaceChar, 0, CharUtilities.isAdjustableSpace(spaceChar)); + } + } + } } /** @@ -520,7 +586,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { * @return ptr of fobj */ private String getPtr() { - FObj fobj = this.parentLM.getFObj(); + FObj fobj = parentLayoutManager.getFObj(); if (fobj instanceof StructurePointerPropertySet) { return (((StructurePointerPropertySet) fobj).getPtr()); } else { @@ -529,11 +595,15 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - private void addToLetterAdjust(final int index, final int width) { - if (this.letterAdjustArray[index] == null) { - this.letterAdjustArray[index] = new MinOptMax(width); + private AreaInfo getAreaInfo(int index) { + return (AreaInfo) areaInfos.get(index); + } + + private void addToLetterAdjust(int index, int width) { + if (letterAdjustArray[index] == null) { + letterAdjustArray[index] = MinOptMax.getInstance(width); } else { - this.letterAdjustArray[index].add(width); + letterAdjustArray[index] = letterAdjustArray[index].plus(width); } } @@ -544,32 +614,33 @@ public class TextLayoutManager extends LeafNodeLayoutManager { */ private static boolean isSpace(final char ch) { return ch == CharUtilities.SPACE - || CharUtilities.isNonBreakableSpace(ch) - || CharUtilities.isFixedWidthSpace(ch); + || CharUtilities.isNonBreakableSpace(ch) + || CharUtilities.isFixedWidthSpace(ch); } /** {@inheritDoc} */ public List getNextKnuthElements(final LayoutContext context, final int alignment) { - this.lineStartBAP = context.getLineStartBorderAndPaddingWidth(); - this.lineEndBAP = context.getLineEndBorderAndPaddingWidth(); - this.alignmentContext = context.getAlignmentContext(); + lineStartBAP = context.getLineStartBorderAndPaddingWidth(); + lineEndBAP = context.getLineEndBorderAndPaddingWidth(); + alignmentContext = context.getAlignmentContext(); final List returnList = new LinkedList(); KnuthSequence sequence = new InlineKnuthSequence(); - AreaInfo ai = null; - AreaInfo prevAi = null; + AreaInfo areaInfo = null; + AreaInfo prevAreaInfo = null; returnList.add(sequence); - final LineBreakStatus lbs = new LineBreakStatus(); - this.thisStart = this.nextStart; + LineBreakStatus lineBreakStatus = new LineBreakStatus(); + thisStart = nextStart; boolean inWord = false; boolean inWhitespace = false; char ch = 0; - while (this.nextStart < this.foText.length()) { - ch = this.foText.charAt(this.nextStart); + while (nextStart < foText.length()) { + ch = foText.charAt(nextStart); boolean breakOpportunity = false; - final byte breakAction = this.keepTogether ? LineBreakStatus.PROHIBITED_BREAK - : lbs.nextChar(ch); + byte breakAction = keepTogether + ? LineBreakStatus.PROHIBITED_BREAK + : lineBreakStatus.nextChar(ch); switch (breakAction) { case LineBreakStatus.COMBINING_PROHIBITED_BREAK: case LineBreakStatus.PROHIBITED_BREAK: @@ -589,62 +660,58 @@ public class TextLayoutManager extends LeafNodeLayoutManager { || TextLayoutManager.isSpace(ch) || CharUtilities.isExplicitBreak(ch)) { // this.foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN - prevAi = this.processWord(alignment, sequence, prevAi, ch, + prevAreaInfo = processWord(alignment, sequence, prevAreaInfo, ch, breakOpportunity, true); } } else if (inWhitespace) { if (ch != CharUtilities.SPACE || breakOpportunity) { - prevAi = this.processWhitespace(alignment, sequence, - breakOpportunity); + prevAreaInfo = processWhitespace(alignment, sequence, breakOpportunity); } } else { - if (ai != null) { - prevAi = ai; - ai = this.processLeftoverAi(alignment, sequence, ai, ch, + if (areaInfo != null) { + prevAreaInfo = areaInfo; + processLeftoverAreaInfo(alignment, sequence, areaInfo, ch == CharUtilities.SPACE || breakOpportunity); + areaInfo = null; } if (breakAction == LineBreakStatus.EXPLICIT_BREAK) { - sequence = this.processLinebreak(returnList, sequence); + sequence = processLinebreak(returnList, sequence); } } if (ch == CharUtilities.SPACE - && this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE + && foText.getWhitespaceTreatment() == Constants.EN_PRESERVE || ch == CharUtilities.NBSPACE) { // preserved space or non-breaking space: // create the AreaInfo object - ai = new AreaInfo(this.nextStart, this.nextStart + 1, - 1, 0, this.wordSpaceIPD, false, true, - breakOpportunity, this.spaceFont); - this.thisStart = this.nextStart + 1; + areaInfo = new AreaInfo(nextStart, nextStart + 1, 1, 0, wordSpaceIPD, false, true, + breakOpportunity, spaceFont); + thisStart = nextStart + 1; } else if (CharUtilities.isFixedWidthSpace(ch) || CharUtilities.isZeroWidthSpace(ch)) { // create the AreaInfo object - final Font font = FontSelector.selectFontForCharacterInText(ch, - this.foText, this); - final MinOptMax ipd = new MinOptMax(font.getCharWidth(ch)); - ai = new AreaInfo(this.nextStart, this.nextStart + 1, - 0, 0, ipd, false, true, + Font font = FontSelector.selectFontForCharacterInText(ch, foText, this); + MinOptMax ipd = MinOptMax.getInstance(font.getCharWidth(ch)); + areaInfo = new AreaInfo(nextStart, nextStart + 1, 0, 0, ipd, false, true, breakOpportunity, font); - this.thisStart = this.nextStart + 1; + thisStart = nextStart + 1; } else if (CharUtilities.isExplicitBreak(ch)) { //mandatory break-character: only advance index - this.thisStart = this.nextStart + 1; + thisStart = nextStart + 1; } - inWord = !TextLayoutManager.isSpace(ch) - && !CharUtilities.isExplicitBreak(ch); + inWord = !TextLayoutManager.isSpace(ch) && !CharUtilities.isExplicitBreak(ch); inWhitespace = ch == CharUtilities.SPACE - && this.foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; - this.nextStart++; - } // end of while + && foText.getWhitespaceTreatment() != Constants.EN_PRESERVE; + nextStart++; + } // Process any last elements if (inWord) { - this.processWord(alignment, sequence, prevAi, ch, false, false); + processWord(alignment, sequence, prevAreaInfo, ch, false, false); } else if (inWhitespace) { - this.processWhitespace(alignment, sequence, true); - } else if (ai != null) { - this.processLeftoverAi(alignment, sequence, ai, ch, + processWhitespace(alignment, sequence, true); + } else if (areaInfo != null) { + processLeftoverAreaInfo(alignment, sequence, areaInfo, ch == CharUtilities.ZERO_WIDTH_SPACE); } else if (CharUtilities.isExplicitBreak(ch)) { this.processLinebreak(returnList, sequence); @@ -655,7 +722,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { ListUtil.removeLast(returnList); } - this.setFinished(true); + setFinished(true); if (returnList.isEmpty()) { return null; } else { @@ -663,12 +730,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } } - private KnuthSequence processLinebreak(final List returnList, - KnuthSequence sequence) { - if (this.lineEndBAP != 0) { - sequence.add( - new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, true)); + private KnuthSequence processLinebreak(List returnList, KnuthSequence sequence) { + if (lineEndBAP != 0) { + sequence.add(new KnuthGlue(lineEndBAP, 0, 0, auxiliaryPosition, true)); } sequence.endSequence(); sequence = new InlineKnuthSequence(); @@ -676,32 +740,29 @@ public class TextLayoutManager extends LeafNodeLayoutManager { return sequence; } - private AreaInfo processLeftoverAi(final int alignment, - final KnuthSequence sequence, AreaInfo ai, final char ch, - final boolean breakOpportunityAfter) { - this.vecAreaInfo.add(ai); - ai.breakOppAfter = breakOpportunityAfter; - this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); - ai = null; - return ai; + private void processLeftoverAreaInfo(int alignment, + KnuthSequence sequence, AreaInfo areaInfo, + boolean breakOpportunityAfter) { + areaInfos.add(areaInfo); + areaInfo.breakOppAfter = breakOpportunityAfter; + addElementsForASpace(sequence, alignment, areaInfo, areaInfos.size() - 1); } private AreaInfo processWhitespace(final int alignment, final KnuthSequence sequence, final boolean breakOpportunity) { // End of whitespace // create the AreaInfo object - AreaInfo ai = new AreaInfo(this.thisStart, this.nextStart, - this.nextStart - this.thisStart, 0, - MinOptMax.multiply(this.wordSpaceIPD, this.nextStart - - this.thisStart), false, true, - breakOpportunity, this.spaceFont); - this.vecAreaInfo.add(ai); + assert nextStart >= thisStart; + AreaInfo areaInfo = new AreaInfo(thisStart, nextStart, nextStart - thisStart, 0, + wordSpaceIPD.mult(nextStart - thisStart), false, true, breakOpportunity, spaceFont); + + areaInfos.add(areaInfo); // create the elements - this.addElementsForASpace(sequence, alignment, ai, this.vecAreaInfo.size() - 1); + addElementsForASpace(sequence, alignment, areaInfo, areaInfos.size() - 1); - this.thisStart = this.nextStart; - return ai; + thisStart = nextStart; + return areaInfo; } private AreaInfo processWord(final int alignment, final KnuthSequence sequence, @@ -709,39 +770,36 @@ public class TextLayoutManager extends LeafNodeLayoutManager { final boolean checkEndsWithHyphen) { //Word boundary found, process widths and kerning - int lastIndex = this.nextStart; - while (lastIndex > 0 - && foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { + int lastIndex = nextStart; + while (lastIndex > 0 && foText.charAt(lastIndex - 1) == CharUtilities.SOFT_HYPHEN) { lastIndex--; } final boolean endsWithHyphen = checkEndsWithHyphen && foText.charAt(lastIndex) == CharUtilities.SOFT_HYPHEN; - final Font font = FontSelector - .selectFontForCharactersInText(foText, - this.thisStart, lastIndex, foText, this); - final int wordLength = lastIndex - this.thisStart; - final boolean kerning = font.hasKerning(); - final MinOptMax wordIPD = new MinOptMax(0); - for (int i = this.thisStart; i < lastIndex; i++) { - final char currentChar = foText.charAt(i); + Font font = FontSelector.selectFontForCharactersInText(foText, thisStart, lastIndex, foText, this); + int wordLength = lastIndex - thisStart; + boolean kerning = font.hasKerning(); + MinOptMax wordIPD = MinOptMax.ZERO; + for (int i = thisStart; i < lastIndex; i++) { + char currentChar = foText.charAt(i); //character width - final int charWidth = font.getCharWidth(currentChar); - wordIPD.add(charWidth); + int charWidth = font.getCharWidth(currentChar); + wordIPD = wordIPD.plus(charWidth); //kerning if (kerning) { int kern = 0; - if (i > this.thisStart) { - final char previousChar = foText.charAt(i - 1); + if (i > thisStart) { + char previousChar = foText.charAt(i - 1); kern = font.getKernValue(previousChar, currentChar); } else if (prevAreaInfo != null && !prevAreaInfo.isSpace && prevAreaInfo.breakIndex > 0) { - final char previousChar = foText.charAt(prevAreaInfo.breakIndex - 1); + char previousChar = foText.charAt(prevAreaInfo.breakIndex - 1); kern = font.getKernValue(previousChar, currentChar); } if (kern != 0) { - this.addToLetterAdjust(i, kern); - wordIPD.add(kern); + addToLetterAdjust(i, kern); + wordIPD = wordIPD.plus(kern); } } } @@ -752,7 +810,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { && endsWithHyphen) { final int kern = font.getKernValue(foText.charAt(lastIndex - 1), ch); if (kern != 0) { - this.addToLetterAdjust(lastIndex, kern); + addToLetterAdjust(lastIndex, kern); //TODO: add kern to wordIPD? } } @@ -763,21 +821,21 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (breakOpportunity && !TextLayoutManager.isSpace(ch)) { iLetterSpaces++; } - wordIPD.add(MinOptMax.multiply(this.letterSpaceIPD, iLetterSpaces)); + assert iLetterSpaces >= 0; + wordIPD = wordIPD.plus(letterSpaceIPD.mult(iLetterSpaces)); // create the AreaInfo object - AreaInfo areaInfo = new AreaInfo(this.thisStart, lastIndex, 0, + AreaInfo areaInfo = new AreaInfo(thisStart, lastIndex, 0, iLetterSpaces, wordIPD, endsWithHyphen, false, breakOpportunity, font); prevAreaInfo = areaInfo; - this.vecAreaInfo.add(areaInfo); - this.tempStart = this.nextStart; + areaInfos.add(areaInfo); + tempStart = nextStart; //add the elements - this.addElementsForAWordFragment(sequence, alignment, areaInfo, - this.vecAreaInfo.size() - 1, this.letterSpaceIPD); - this.thisStart = this.nextStart; + addElementsForAWordFragment(sequence, alignment, areaInfo, areaInfos.size() - 1); + thisStart = nextStart; return prevAreaInfo; } @@ -788,49 +846,39 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // look at the Position stored in the first element in oldList // which is always a box ListIterator oldListIterator = oldList.listIterator(); - final KnuthElement el = (KnuthElement)oldListIterator.next(); - final LeafPosition pos = (LeafPosition) ((KnuthBox) el).getPosition(); - final int idx = pos.getLeafPos(); + KnuthElement knuthElement = (KnuthElement) oldListIterator.next(); + LeafPosition pos = (LeafPosition) ((KnuthBox) knuthElement).getPosition(); + int index = pos.getLeafPos(); //element could refer to '-1' position, for non-collapsed spaces (?) - if (idx > -1) { - final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(idx); - ai.letterSpaceCount++; - ai.areaIPD.add(this.letterSpaceIPD); - if (TextLayoutManager.BREAK_CHARS.indexOf(this.foText.charAt(this.tempStart - 1)) >= 0) { + if (index > -1) { + AreaInfo areaInfo = getAreaInfo(index); + areaInfo.letterSpaceCount++; + areaInfo.addToAreaIPD(letterSpaceIPD); + if (TextLayoutManager.BREAK_CHARS.indexOf(foText.charAt(tempStart - 1)) >= 0) { // the last character could be used as a line break // append new elements to oldList oldListIterator = oldList.listIterator(oldList.size()); oldListIterator.add(new KnuthPenalty(0, KnuthPenalty.FLAGGED_PENALTY, true, - this.auxiliaryPosition, false)); - oldListIterator.add(new KnuthGlue(this.letterSpaceIPD.opt, - this.letterSpaceIPD.max - this.letterSpaceIPD.opt, - this.letterSpaceIPD.opt - this.letterSpaceIPD.min, - this.auxiliaryPosition, false)); - } else if (this.letterSpaceIPD.min == this.letterSpaceIPD.max) { + auxiliaryPosition, false)); + oldListIterator.add(new KnuthGlue(letterSpaceIPD, auxiliaryPosition, false)); + } else if (letterSpaceIPD.isStiff()) { // constant letter space: replace the box - oldListIterator.set(new KnuthInlineBox(ai.areaIPD.opt, - this.alignmentContext, pos, false)); + oldListIterator.set(new KnuthInlineBox(areaInfo.areaIPD.getOpt(), + alignmentContext, pos, false)); } else { // adjustable letter space: replace the glue oldListIterator.next(); // this would return the penalty element oldListIterator.next(); // this would return the glue element - oldListIterator - .set(new KnuthGlue( - ai.letterSpaceCount * this.letterSpaceIPD.opt, - ai.letterSpaceCount - * (this.letterSpaceIPD.max - this.letterSpaceIPD.opt), - ai.letterSpaceCount - * (this.letterSpaceIPD.opt - this.letterSpaceIPD.min), - this.auxiliaryPosition, true)); + oldListIterator.set(new KnuthGlue(letterSpaceIPD.mult(areaInfo.letterSpaceCount), + auxiliaryPosition, true)); } } return oldList; } /** - * remove the AreaInfo object represented by the given elements, - * so that it won't generate any element when getChangedKnuthElements - * will be called + * Removes the <code>AreaInfo</code> object represented by the given elements, so that it won't + * generate any element when <code>getChangedKnuthElements</code> is called. * * @param oldList the elements representing the word space */ @@ -848,99 +896,91 @@ public class TextLayoutManager extends LeafNodeLayoutManager { oldListIterator.next(); oldListIterator.next(); } - final int leafValue = ((LeafPosition) ((KnuthElement) oldListIterator - .next()).getPosition()).getLeafPos(); + KnuthElement knuthElement = (KnuthElement) oldListIterator.next(); + int leafValue = ((LeafPosition) knuthElement.getPosition()).getLeafPos(); // only the last word space can be a trailing space! - if (leafValue == this.vecAreaInfo.size() - 1) { - this.vecAreaInfo.remove(leafValue); + if (leafValue == areaInfos.size() - 1) { + areaInfos.remove(leafValue); } else { TextLayoutManager.LOG.error("trying to remove a non-trailing word space"); } } - /** {@inheritDoc} */ - public void hyphenate(final Position pos, final HyphContext hc) { - final AreaInfo ai - = (AreaInfo) this.vecAreaInfo.get(((LeafPosition) pos).getLeafPos()); - int startIndex = ai.startIndex; + /** + * {@inheritDoc} + */ + public void hyphenate(Position pos, HyphContext hyphContext) { + AreaInfo areaInfo = getAreaInfo(((LeafPosition) pos).getLeafPos()); + int startIndex = areaInfo.startIndex; int stopIndex; boolean nothingChanged = true; - final Font font = ai.font; + Font font = areaInfo.font; - while (startIndex < ai.breakIndex) { - final MinOptMax newIPD = new MinOptMax(0); + while (startIndex < areaInfo.breakIndex) { + MinOptMax newIPD = MinOptMax.ZERO; boolean hyphenFollows; - stopIndex = startIndex + hc.getNextHyphPoint(); - if (hc.hasMoreHyphPoints() && stopIndex <= ai.breakIndex) { + stopIndex = startIndex + hyphContext.getNextHyphPoint(); + if (hyphContext.hasMoreHyphPoints() && stopIndex <= areaInfo.breakIndex) { // stopIndex is the index of the first character // after a hyphenation point hyphenFollows = true; } else { // there are no more hyphenation points, - // or the next one is after ai.breakIndex + // or the next one is after areaInfo.breakIndex hyphenFollows = false; - stopIndex = ai.breakIndex; + stopIndex = areaInfo.breakIndex; } - hc.updateOffset(stopIndex - startIndex); + hyphContext.updateOffset(stopIndex - startIndex); //log.info("Word: " + new String(textArray, startIndex, stopIndex - startIndex)); for (int i = startIndex; i < stopIndex; i++) { - final char c = this.foText.charAt(i); - newIPD.add(new MinOptMax(font.getCharWidth(c))); + char ch = foText.charAt(i); + newIPD = newIPD.plus(font.getCharWidth(ch)); //if (i > startIndex) { if (i < stopIndex) { - MinOptMax la = this.letterAdjustArray[i + 1]; + MinOptMax letterAdjust = letterAdjustArray[i + 1]; if (i == stopIndex - 1 && hyphenFollows) { //the letter adjust here needs to be handled further down during //element generation because it depends on hyph/no-hyph condition - la = null; + letterAdjust = null; } - if (la != null) { - newIPD.add(la); + if (letterAdjust != null) { + newIPD = newIPD.plus(letterAdjust); } } } + // add letter spaces - final boolean isWordEnd - = stopIndex == ai.breakIndex - && ai.letterSpaceCount < ai.breakIndex - ai.startIndex; - newIPD.add(MinOptMax.multiply(this.letterSpaceIPD, - (isWordEnd - ? stopIndex - startIndex - 1 - : stopIndex - startIndex))); - - if (!(nothingChanged - && stopIndex == ai.breakIndex - && !hyphenFollows)) { + boolean isWordEnd = stopIndex == areaInfo.breakIndex && areaInfo.letterSpaceCount < areaInfo.getCharLength(); + int letterSpaceCount = isWordEnd ? stopIndex - startIndex - 1 : stopIndex - startIndex; + + assert letterSpaceCount >= 0; + newIPD = newIPD.plus(letterSpaceIPD.mult(letterSpaceCount)); + + if (!(nothingChanged && stopIndex == areaInfo.breakIndex && !hyphenFollows)) { // the new AreaInfo object is not equal to the old one - if (this.changeList == null) { - this.changeList = new LinkedList(); - } - this.changeList.add(new PendingChange(new AreaInfo( - startIndex, stopIndex, 0, - (isWordEnd ? stopIndex - startIndex - 1 - : stopIndex - startIndex), newIPD, - hyphenFollows, false, false, font), + changeList.add(new PendingChange(new AreaInfo(startIndex, stopIndex, 0, + letterSpaceCount, newIPD, hyphenFollows, false, false, font), ((LeafPosition) pos).getLeafPos())); nothingChanged = false; } startIndex = stopIndex; } - this.hasChanged = (this.hasChanged || !nothingChanged); + hasChanged |= !nothingChanged; } /** {@inheritDoc} */ public boolean applyChanges(final List oldList) { - this.setFinished(false); + setFinished(false); - if (this.changeList != null && !this.changeList.isEmpty()) { + if (!changeList.isEmpty()) { int areaInfosAdded = 0; int areaInfosRemoved = 0; int oldIndex = -1, changeIndex; PendingChange currChange; - final ListIterator changeListIterator = this.changeList.listIterator(); + ListIterator changeListIterator = changeList.listIterator(); while (changeListIterator.hasNext()) { currChange = (PendingChange) changeListIterator.next(); if (currChange.index == oldIndex) { @@ -951,111 +991,109 @@ public class TextLayoutManager extends LeafNodeLayoutManager { areaInfosAdded++; oldIndex = currChange.index; changeIndex = currChange.index + areaInfosAdded - areaInfosRemoved; - this.vecAreaInfo.remove(changeIndex); + areaInfos.remove(changeIndex); } - this.vecAreaInfo.add(changeIndex, currChange.ai); + areaInfos.add(changeIndex, currChange.areaInfo); } - this.changeList.clear(); + changeList.clear(); } - this.returnedIndex = 0; - return this.hasChanged; + returnedIndex = 0; + return hasChanged; } /** {@inheritDoc} */ - public List getChangedKnuthElements(final List oldList, - final int alignment) { - if (this.isFinished()) { + public List getChangedKnuthElements(final List oldList, final int alignment) { + if (isFinished()) { return null; } final LinkedList returnList = new LinkedList(); - while (this.returnedIndex < this.vecAreaInfo.size()) { - final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(this.returnedIndex); - if (ai.wordSpaceCount == 0) { - // ai refers either to a word or a word fragment - this.addElementsForAWordFragment(returnList, alignment, ai, - this.returnedIndex, this.letterSpaceIPD); + while (returnedIndex < areaInfos.size()) { + AreaInfo areaInfo = getAreaInfo(returnedIndex); + if (areaInfo.wordSpaceCount == 0) { + // areaInfo refers either to a word or a word fragment + addElementsForAWordFragment(returnList, alignment, areaInfo, returnedIndex); } else { - // ai refers to a space - this.addElementsForASpace(returnList, alignment, ai, this.returnedIndex); + // areaInfo refers to a space + addElementsForASpace(returnList, alignment, areaInfo, returnedIndex); } - this.returnedIndex++; - } // end of while - this.setFinished(true); + returnedIndex++; + } + setFinished(true); //ElementListObserver.observe(returnList, "text-changed", null); return returnList; } - /** {@inheritDoc} */ - public void getWordChars(final StringBuffer sbChars, final Position pos) { - final int leafValue = ((LeafPosition) pos).getLeafPos(); + /** + * {@inheritDoc} + */ + public String getWordChars(Position pos) { + int leafValue = ((LeafPosition) pos).getLeafPos(); if (leafValue != -1) { - final AreaInfo ai = (AreaInfo) this.vecAreaInfo.get(leafValue); - for (int i = ai.startIndex; i < ai.breakIndex; ++i) { - sbChars.append(this.foText.charAt(i)); + AreaInfo areaInfo = getAreaInfo(leafValue); + StringBuffer buffer = new StringBuffer(areaInfo.getCharLength()); + for (int i = areaInfo.startIndex; i < areaInfo.breakIndex; i++) { + buffer.append(foText.charAt(i)); } + return buffer.toString(); + } else { + return ""; } } - private void addElementsForASpace(final List baseList, - final int alignment, - final AreaInfo ai, - final int leafValue) { - final LeafPosition mainPosition = new LeafPosition(this, leafValue); + private void addElementsForASpace(List baseList, int alignment, AreaInfo areaInfo, + int leafValue) { + LeafPosition mainPosition = new LeafPosition(this, leafValue); - if (!ai.breakOppAfter) { + if (!areaInfo.breakOppAfter) { // a non-breaking space if (alignment == Constants.EN_JUSTIFY) { // the space can stretch and shrink, and must be preserved // when starting a line - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - ai.areaIPD.opt, - ai.areaIPD.opt - ai.areaIPD.min, mainPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(areaInfo.areaIPD, mainPosition, false)); } else { // the space does not need to stretch or shrink, and must be // preserved when starting a line - baseList.add(new KnuthInlineBox(ai.areaIPD.opt, null, - mainPosition, true)); + baseList.add(new KnuthInlineBox(areaInfo.areaIPD.getOpt(), null, mainPosition, + true)); } } else { - if (this.foText.charAt(ai.startIndex) != CharUtilities.SPACE - || this.foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { + if (foText.charAt(areaInfo.startIndex) != CharUtilities.SPACE + || foText.getWhitespaceTreatment() == Constants.EN_PRESERVE) { // a breaking space that needs to be preserved - this.addElementsForBreakingSpace(baseList, alignment, ai, - this.auxiliaryPosition, 0, mainPosition, - ai.areaIPD.opt, true); + baseList.addAll(getElementsForBreakingSpace(alignment, areaInfo, auxiliaryPosition, 0, + mainPosition, areaInfo.areaIPD.getOpt(), true)); } else { // a (possible block) of breaking spaces - this.addElementsForBreakingSpace(baseList, alignment, ai, - mainPosition, ai.areaIPD.opt, - this.auxiliaryPosition, 0, false); + baseList.addAll(getElementsForBreakingSpace(alignment, areaInfo, mainPosition, + areaInfo.areaIPD.getOpt(), auxiliaryPosition, 0, false)); } } } - private void addElementsForBreakingSpace(final List baseList, - final int alignment, final AreaInfo ai, final Position pos2, - final int p2WidthOffset, final Position pos3, - final int p3WidthOffset, final boolean skipZeroCheck) { + private List getElementsForBreakingSpace(int alignment, AreaInfo areaInfo, Position pos2, + int p2WidthOffset, Position pos3, + int p3WidthOffset, boolean skipZeroCheck) { + List elements = new ArrayList(); + switch (alignment) { case EN_CENTER: // centered text: // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line and at the // beginning of the next one, otherwise they don't add any stretch - baseList.add(new KnuthGlue(this.lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(p2WidthOffset - - (this.lineStartBAP + this.lineEndBAP), -6 + elements.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + auxiliaryPosition, false)); + elements.add(makeZeroWidthPenalty(0)); + elements.add(new KnuthGlue(p2WidthOffset - (lineStartBAP + lineEndBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, + elements.add(makeAuxiliaryZeroWidthBox()); + elements.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + elements.add(new KnuthGlue(lineStartBAP + p3WidthOffset, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos3, false)); break; @@ -1065,246 +1103,203 @@ public class TextLayoutManager extends LeafNodeLayoutManager { // if the second element is chosen as a line break these elements // add a constant amount of stretch at the end of a line, otherwise // they don't add any stretch - if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { - baseList.add(new KnuthGlue(this.lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(p2WidthOffset - - (this.lineStartBAP + this.lineEndBAP), -3 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - pos2, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, - 0, 0, pos3, false)); + if (skipZeroCheck || lineStartBAP != 0 || lineEndBAP != 0) { + elements.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, auxiliaryPosition, false)); + elements.add(makeZeroWidthPenalty(0)); + elements.add(new KnuthGlue(p2WidthOffset - (lineStartBAP + lineEndBAP), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); + elements.add(makeAuxiliaryZeroWidthBox()); + elements.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + elements.add(new KnuthGlue(lineStartBAP + p3WidthOffset, 0, 0, pos3, false)); } else { - baseList.add(new KnuthGlue(0, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(ai.areaIPD.opt, -3 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - pos2, false)); + elements.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, auxiliaryPosition, false)); + elements.add(makeZeroWidthPenalty(0)); + elements.add(new KnuthGlue(areaInfo.areaIPD.getOpt(), -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, pos2, false)); } break; case EN_JUSTIFY: // justified text: // the stretch and shrink depends on the space width - if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { - baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(p2WidthOffset - - (this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max - - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, - pos2, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, - 0, 0, pos3, false)); - } else { - baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - - ai.areaIPD.opt, ai.areaIPD.opt - ai.areaIPD.min, - pos2, false)); - } + elements.addAll(getElementsForJustifiedText(areaInfo, pos2, p2WidthOffset, pos3, + p3WidthOffset, skipZeroCheck, areaInfo.areaIPD.getShrink())); break; default: // last line justified, the other lines unjustified: // use only the space stretch - if (skipZeroCheck || this.lineStartBAP != 0 || this.lineEndBAP != 0) { - baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeZeroWidthPenalty(0)); - baseList.add(new KnuthGlue(p2WidthOffset - - (this.lineStartBAP + this.lineEndBAP), ai.areaIPD.max - - ai.areaIPD.opt, 0, pos2, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP + p3WidthOffset, - 0, 0, pos3, false)); - } else { - baseList.add(new KnuthGlue(ai.areaIPD.opt, ai.areaIPD.max - - ai.areaIPD.opt, 0, pos2, false)); - } + elements.addAll(getElementsForJustifiedText(areaInfo, pos2, p2WidthOffset, pos3, + p3WidthOffset, skipZeroCheck, 0)); } + return elements; } - private void addElementsForAWordFragment(final List baseList, - final int alignment, - final AreaInfo ai, - final int leafValue, - final MinOptMax letterSpaceWidth) { + private List getElementsForJustifiedText(AreaInfo areaInfo, Position pos2, int p2WidthOffset, + Position pos3, int p3WidthOffset, boolean skipZeroCheck, + int shrinkability) { + + int stretchability = areaInfo.areaIPD.getStretch(); + + List elements = new ArrayList(); + if (skipZeroCheck || lineStartBAP != 0 || lineEndBAP != 0) { + elements.add(new KnuthGlue(lineEndBAP, 0, 0, auxiliaryPosition, false)); + elements.add(makeZeroWidthPenalty(0)); + elements.add(new KnuthGlue(p2WidthOffset - (lineStartBAP + lineEndBAP), + stretchability, shrinkability, pos2, false)); + elements.add(makeAuxiliaryZeroWidthBox()); + elements.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + elements.add(new KnuthGlue(lineStartBAP + p3WidthOffset, 0, 0, pos3, false)); + } else { + elements.add(new KnuthGlue(areaInfo.areaIPD.getOpt(), stretchability, shrinkability, + pos2, false)); + } + return elements; + } - final LeafPosition mainPosition = new LeafPosition(this, leafValue); + private void addElementsForAWordFragment(List baseList, int alignment, AreaInfo areaInfo, + int leafValue) { + LeafPosition mainPosition = new LeafPosition(this, leafValue); // if the last character of the word fragment is '-' or '/', // the fragment could end a line; in this case, it loses one // of its letter spaces; - final boolean suppressibleLetterSpace = ai.breakOppAfter && !ai.isHyphenated; + boolean suppressibleLetterSpace = areaInfo.breakOppAfter && !areaInfo.isHyphenated; - if (letterSpaceWidth.min == letterSpaceWidth.max) { + if (letterSpaceIPD.isStiff()) { // constant letter spacing - baseList.add(new KnuthInlineBox( - suppressibleLetterSpace - ? ai.areaIPD.opt - letterSpaceWidth.opt - : ai.areaIPD.opt, - this.alignmentContext, - this.notifyPos(mainPosition), false)); + baseList.add(new KnuthInlineBox(suppressibleLetterSpace + ? areaInfo.areaIPD.getOpt() - letterSpaceIPD.getOpt() + : areaInfo.areaIPD.getOpt(), + alignmentContext, notifyPos(mainPosition), false)); } else { // adjustable letter spacing - final int unsuppressibleLetterSpaces - = suppressibleLetterSpace ? ai.letterSpaceCount - 1 : ai.letterSpaceCount; - baseList.add - (new KnuthInlineBox(ai.areaIPD.opt - - ai.letterSpaceCount * letterSpaceWidth.opt, - this.alignmentContext, - this.notifyPos(mainPosition), false)); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add - (new KnuthGlue(unsuppressibleLetterSpaces * letterSpaceWidth.opt, - unsuppressibleLetterSpaces * (letterSpaceWidth.max - letterSpaceWidth.opt), - unsuppressibleLetterSpaces * (letterSpaceWidth.opt - letterSpaceWidth.min), - this.auxiliaryPosition, true)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); + int unsuppressibleLetterSpaces = suppressibleLetterSpace + ? areaInfo.letterSpaceCount - 1 + : areaInfo.letterSpaceCount; + baseList.add(new KnuthInlineBox(areaInfo.areaIPD.getOpt() + - areaInfo.letterSpaceCount * letterSpaceIPD.getOpt(), + alignmentContext, notifyPos(mainPosition), false)); + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(letterSpaceIPD.mult(unsuppressibleLetterSpaces), + auxiliaryPosition, true)); + baseList.add(makeAuxiliaryZeroWidthBox()); } // extra-elements if the word fragment is the end of a syllable, // or it ends with a character that can be used as a line break - if (ai.isHyphenated) { + if (areaInfo.isHyphenated) { MinOptMax widthIfNoBreakOccurs = null; - if (ai.breakIndex < this.foText.length()) { + if (areaInfo.breakIndex < foText.length()) { //Add in kerning in no-break condition - widthIfNoBreakOccurs = this.letterAdjustArray[ai.breakIndex]; + widthIfNoBreakOccurs = letterAdjustArray[areaInfo.breakIndex]; } - //if (ai.breakIndex) + //if (areaInfo.breakIndex) // the word fragment ends at the end of a syllable: // if a break occurs the content width increases, // otherwise nothing happens - this.addElementsForAHyphen(baseList, alignment, this.hyphIPD, - widthIfNoBreakOccurs, ai.breakOppAfter && ai.isHyphenated); + addElementsForAHyphen(baseList, alignment, hyphIPD, widthIfNoBreakOccurs, + areaInfo.breakOppAfter && areaInfo.isHyphenated); } else if (suppressibleLetterSpace) { // the word fragment ends with a character that acts as a hyphen // if a break occurs the width does not increase, // otherwise there is one more letter space - this.addElementsForAHyphen(baseList, alignment, 0, letterSpaceWidth, true); + addElementsForAHyphen(baseList, alignment, 0, letterSpaceIPD, true); } } - // static final int SOFT_HYPHEN_PENALTY = KnuthPenalty.FLAGGED_PENALTY / 10; - private static final int SOFT_HYPHEN_PENALTY = 1; + private void addElementsForAHyphen(List baseList, int alignment, int widthIfBreakOccurs, + MinOptMax widthIfNoBreakOccurs, boolean unflagged) { - private void addElementsForAHyphen(final List baseList, - final int alignment, - final int widthIfBreakOccurs, - MinOptMax widthIfNoBreakOccurs, - final boolean unflagged) { if (widthIfNoBreakOccurs == null) { - widthIfNoBreakOccurs = TextLayoutManager.ZERO_MINOPTMAX; + widthIfNoBreakOccurs = MinOptMax.ZERO; } switch (alignment) { - case EN_CENTER : + case EN_CENTER: // centered text: - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineEndBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, true)); - baseList.add(new KnuthPenalty(this.hyphIPD, - unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY - : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - this.auxiliaryPosition, false)); - baseList.add(new KnuthGlue(-(this.lineEndBAP + this.lineStartBAP), + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + auxiliaryPosition, true)); + baseList.add(new KnuthPenalty(hyphIPD, unflagged + ? TextLayoutManager.SOFT_HYPHEN_PENALTY + : KnuthPenalty.FLAGGED_PENALTY, !unflagged, auxiliaryPosition, false)); + baseList.add(new KnuthGlue(-(lineEndBAP + lineStartBAP), -6 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP, - 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, true)); + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, + 0, auxiliaryPosition, true)); break; - case EN_START : // fall through - case EN_END : + case EN_START: // fall through + case EN_END: // left- or right-aligned text: - if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineEndBAP, + if (lineStartBAP != 0 || lineEndBAP != 0) { + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(lineEndBAP, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); + auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - this.auxiliaryPosition, false)); - baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt - - (this.lineStartBAP + this.lineEndBAP), -3 - * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, - this.auxiliaryPosition, false)); + auxiliaryPosition, false)); + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.getOpt() + - (lineStartBAP + lineEndBAP), + -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, auxiliaryPosition, false)); } else { - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); baseList.add(new KnuthGlue(0, 3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); + auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - this.auxiliaryPosition, false)); - baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, - -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, - this.auxiliaryPosition, false)); + auxiliaryPosition, false)); + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.getOpt(), + -3 * LineLayoutManager.DEFAULT_SPACE_WIDTH, 0, + auxiliaryPosition, false)); } break; default: // justified text, or last line justified: // just a flagged penalty - if (this.lineStartBAP != 0 || this.lineEndBAP != 0) { - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineEndBAP, 0, 0, - this.auxiliaryPosition, false)); + if (lineStartBAP != 0 || lineEndBAP != 0) { + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(lineEndBAP, 0, 0, auxiliaryPosition, false)); baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - this.auxiliaryPosition, false)); + auxiliaryPosition, false)); // extra elements representing a letter space that is suppressed // if a break occurs - if (widthIfNoBreakOccurs.min != 0 - || widthIfNoBreakOccurs.max != 0) { - baseList - .add(new KnuthGlue(widthIfNoBreakOccurs.opt - - (this.lineStartBAP + this.lineEndBAP), - widthIfNoBreakOccurs.max - - widthIfNoBreakOccurs.opt, - widthIfNoBreakOccurs.opt - - widthIfNoBreakOccurs.min, - this.auxiliaryPosition, false)); + if (widthIfNoBreakOccurs.isNonZero()) { + baseList.add(new KnuthGlue(widthIfNoBreakOccurs.getOpt() + - (lineStartBAP + lineEndBAP), + widthIfNoBreakOccurs.getStretch(), + widthIfNoBreakOccurs.getShrink(), + auxiliaryPosition, false)); } else { - baseList.add(new KnuthGlue(-(this.lineStartBAP + this.lineEndBAP), 0, 0, - this.auxiliaryPosition, false)); + baseList.add(new KnuthGlue(-(lineStartBAP + lineEndBAP), 0, 0, + auxiliaryPosition, false)); } - baseList.add(this.makeAuxiliaryZeroWidthBox()); - baseList.add(this.makeZeroWidthPenalty(KnuthElement.INFINITE)); - baseList.add(new KnuthGlue(this.lineStartBAP, 0, 0, - this.auxiliaryPosition, false)); + baseList.add(makeAuxiliaryZeroWidthBox()); + baseList.add(makeZeroWidthPenalty(KnuthElement.INFINITE)); + baseList.add(new KnuthGlue(lineStartBAP, 0, 0, + auxiliaryPosition, false)); } else { baseList.add(new KnuthPenalty(widthIfBreakOccurs, unflagged ? TextLayoutManager.SOFT_HYPHEN_PENALTY : KnuthPenalty.FLAGGED_PENALTY, !unflagged, - this.auxiliaryPosition, false)); + auxiliaryPosition, false)); // extra elements representing a letter space that is suppressed // if a break occurs - if (widthIfNoBreakOccurs.min != 0 - || widthIfNoBreakOccurs.max != 0) { - baseList.add(new KnuthGlue(widthIfNoBreakOccurs.opt, - widthIfNoBreakOccurs.max - widthIfNoBreakOccurs.opt, - widthIfNoBreakOccurs.opt - widthIfNoBreakOccurs.min, - this.auxiliaryPosition, false)); + if (widthIfNoBreakOccurs.isNonZero()) { + baseList.add(new KnuthGlue(widthIfNoBreakOccurs, auxiliaryPosition, false)); } } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index 97f07da54..4b93bcdac 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -28,8 +28,6 @@ import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; -import java.util.LinkedList; - /** * This is the layout manager for the fo:wrapper formatting object. */ @@ -67,14 +65,14 @@ public class WrapperLayoutManager extends LeafNodeLayoutManager { public void addAreas(PositionIterator posIter, LayoutContext context) { if (fobj.hasId()) { addId(); - if (parentLM instanceof BlockStackingLayoutManager - && !(parentLM instanceof BlockLayoutManager)) { + if (parentLayoutManager instanceof BlockStackingLayoutManager + && !(parentLayoutManager instanceof BlockLayoutManager)) { Block helperBlock = new Block(); TraitSetter.setProducerID(helperBlock, fobj.getId()); - parentLM.addChildArea(helperBlock); + parentLayoutManager.addChildArea(helperBlock); } else { InlineArea area = getEffectiveArea(); - parentLM.addChildArea(area); + parentLayoutManager.addChildArea(area); } } while (posIter.hasNext()) { diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index a9f2eeb27..8ab79d2c4 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -154,7 +154,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager // if this will create the first block area in a page // and display-align is after or center, add space before if (layoutContext.getSpaceBefore() > 0) { - addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); + addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore())); } addId(); @@ -241,7 +241,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager // Set up dimensions // Must get dimensions from parent area - /*Area parentArea =*/ parentLM.getParentArea(curBlockArea); + /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); // set traits TraitSetter.setProducerID(curBlockArea, getListBlockFO().getId()); diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index 7fd2219ea..246c57094 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -201,7 +201,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { TraitSetter.setProducerID(curBlockArea, getPartFO().getId()); // Set up dimensions - Area parentArea = parentLM.getParentArea(curBlockArea); + Area parentArea = parentLayoutManager.getParentArea(curBlockArea); int referenceIPD = parentArea.getIPD(); curBlockArea.setIPD(referenceIPD); // Get reference IPD from parentArea diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index 9848584c0..206d0ae1c 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -604,7 +604,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager curBlockArea = new Block(); // Set up dimensions - /*Area parentArea =*/ parentLM.getParentArea(curBlockArea); + /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); // set traits TraitSetter.setProducerID(curBlockArea, getListItemFO().getId()); diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java index abcde41c7..36d42dbbe 100644 --- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java +++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java @@ -38,7 +38,6 @@ import org.apache.fop.layoutmgr.KnuthBlockBox; import org.apache.fop.layoutmgr.KnuthBox; import org.apache.fop.layoutmgr.KnuthElement; import org.apache.fop.layoutmgr.KnuthPenalty; -import org.apache.fop.layoutmgr.MinOptMaxUtil; import org.apache.fop.traits.MinOptMax; /** @@ -211,8 +210,7 @@ class ActiveCell { bpAfterNormal = paddingAfterNormal + pgu.getAfterBorderWidth(ConditionalBorder.NORMAL); bpAfterTrailing = paddingAfterTrailing + pgu.getAfterBorderWidth(0, ConditionalBorder.REST); elementList = pgu.getElements(); - handleExplicitHeight( - MinOptMaxUtil.toMinOptMax(pgu.getCell().getBlockProgressionDimension(), tableLM), + handleExplicitHeight(pgu.getCell().getBlockProgressionDimension().toMinOptMax(tableLM), row.getExplicitHeight()); knuthIter = elementList.listIterator(); includedLength = -1; // Avoid troubles with cells having content of zero length @@ -239,7 +237,7 @@ class ActiveCell { * occurs. The list of elements needs to be re-adjusted after each break. */ private void handleExplicitHeight(MinOptMax cellBPD, MinOptMax rowBPD) { - int minBPD = Math.max(cellBPD.min, rowBPD.min); + int minBPD = Math.max(cellBPD.getMin(), rowBPD.getMin()); if (minBPD > 0) { ListIterator iter = elementList.listIterator(); int cumulateLength = 0; @@ -264,7 +262,7 @@ class ActiveCell { } } } - int optBPD = Math.max(minBPD, Math.max(cellBPD.opt, rowBPD.opt)); + int optBPD = Math.max(minBPD, Math.max(cellBPD.getOpt(), rowBPD.getOpt())); if (pgu.getContentLength() < optBPD) { elementList.add(new FillerBox(optBPD - pgu.getContentLength())); } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index 83e71bb21..7c11db17d 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -35,7 +35,6 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.LengthRangeProperty; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.MinOptMaxUtil; import org.apache.fop.traits.MinOptMax; import org.apache.fop.util.BreakUtil; @@ -43,6 +42,8 @@ class RowGroupLayoutManager { private static Log log = LogFactory.getLog(RowGroupLayoutManager.class); + private static final MinOptMax MAX_STRETCH = MinOptMax.getInstance(0, 0, Integer.MAX_VALUE); + private EffRow[] rowGroup; private TableLayoutManager tableLM; @@ -146,12 +147,12 @@ class RowGroupLayoutManager { MinOptMax explicitRowHeight; TableRow tableRowFO = rowGroup[rgi].getTableRow(); if (tableRowFO == null) { - rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE); - explicitRowHeight = new MinOptMax(0, 0, Integer.MAX_VALUE); + rowHeights[rgi] = MAX_STRETCH; + explicitRowHeight = MAX_STRETCH; } else { LengthRangeProperty rowBPD = tableRowFO.getBlockProgressionDimension(); - rowHeights[rgi] = MinOptMaxUtil.toMinOptMax(rowBPD, tableLM); - explicitRowHeight = MinOptMaxUtil.toMinOptMax(rowBPD, tableLM); + rowHeights[rgi] = rowBPD.toMinOptMax(tableLM); + explicitRowHeight = rowBPD.toMinOptMax(tableLM); } for (Iterator iter = row.getGridUnits().iterator(); iter.hasNext();) { GridUnit gu = (GridUnit) iter.next(); @@ -168,7 +169,7 @@ class RowGroupLayoutManager { .getValue(tableLM); } if (gu.getRowSpanIndex() == 0) { - effectiveCellBPD = Math.max(effectiveCellBPD, explicitRowHeight.opt); + effectiveCellBPD = Math.max(effectiveCellBPD, explicitRowHeight.getOpt()); } effectiveCellBPD = Math.max(effectiveCellBPD, primary.getContentLength()); int borderWidths = primary.getBeforeAfterBorderWidth(); @@ -179,11 +180,11 @@ class RowGroupLayoutManager { padding += cbpb.getPaddingAfter(false, primary.getCellLM()); int effRowHeight = effectiveCellBPD + padding + borderWidths; for (int prev = rgi - 1; prev >= rgi - gu.getRowSpanIndex(); prev--) { - effRowHeight -= rowHeights[prev].opt; + effRowHeight -= rowHeights[prev].getOpt(); } - if (effRowHeight > rowHeights[rgi].min) { + if (effRowHeight > rowHeights[rgi].getMin()) { // This is the new height of the (grid) row - MinOptMaxUtil.extendMinimum(rowHeights[rgi], effRowHeight); + rowHeights[rgi] = rowHeights[rgi].extendMinimum(effRowHeight); } } } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index edf73acab..e28126c3e 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -181,7 +181,7 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { curBlockArea = new Block(); // Set up dimensions // Must get dimensions from parent area - Area parentArea = parentLM.getParentArea(curBlockArea); + Area parentArea = parentLayoutManager.getParentArea(curBlockArea); int referenceIPD = parentArea.getIPD(); curBlockArea.setIPD(referenceIPD); // Get reference IPD from parentArea diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 9d9255e0c..c7d0d0da4 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -177,7 +177,7 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { curBlockArea = new Block(); // Set up dimensions // Must get dimensions from parent area - Area parentArea = parentLM.getParentArea(curBlockArea); + Area parentArea = parentLayoutManager.getParentArea(curBlockArea); int referenceIPD = parentArea.getIPD(); curBlockArea.setIPD(referenceIPD); // Get reference IPD from parentArea diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index ea2e64afb..0599b430c 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -131,7 +131,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager * {@inheritDoc} */ public List getNextKnuthElements(LayoutContext context, int alignment) { - MinOptMax stackLimit = new MinOptMax(context.getStackLimitBP()); + MinOptMax stackLimit = context.getStackLimitBP(); referenceIPD = context.getRefIPD(); cellIPD = referenceIPD; @@ -146,8 +146,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager while ((curLM = getChildLM()) != null) { LayoutContext childLC = new LayoutContext(0); // curLM is a ? - childLC.setStackLimitBP(MinOptMax.subtract(context - .getStackLimitBP(), stackLimit)); + childLC.setStackLimitBP(context.getStackLimitBP().minus(stackLimit)); childLC.setRefIPD(cellIPD); // get elements from curLM @@ -387,7 +386,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager adjustXOffset(block, dx); adjustIPD(block, ipd); adjustBPD(block, bpd); - parentLM.addChildArea(block); + parentLayoutManager.addChildArea(block); } dx += ipd; } @@ -439,8 +438,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager TableColumn column = getTable().getColumn(primaryGridUnit.getColIndex()); if (column.getCommonBorderPaddingBackground().hasBackground()) { Block colBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); - ((TableLayoutManager) parentLM).registerColumnBackgroundArea(column, colBackgroundArea, - -startIndent); + ((TableLayoutManager) parentLayoutManager).registerColumnBackgroundArea(column, + colBackgroundArea, -startIndent); } TablePart body = primaryGridUnit.getTablePart(); @@ -452,11 +451,11 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager TableRow row = primaryGridUnit.getRow(); if (row != null && row.getCommonBorderPaddingBackground().hasBackground()) { Block rowBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth); - ((TableLayoutManager) parentLM).addBackgroundArea(rowBackgroundArea); + ((TableLayoutManager) parentLayoutManager).addBackgroundArea(rowBackgroundArea); TraitSetter.addBackground(rowBackgroundArea, row.getCommonBorderPaddingBackground(), - parentLM, + parentLayoutManager, -xoffset - startIndent, -borderBeforeWidth, - parentLM.getContentAreaIPD(), firstRowHeight); + parentLayoutManager.getContentAreaIPD(), firstRowHeight); } } @@ -526,7 +525,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager curBlockArea.setYOffset(yoffset); curBlockArea.setIPD(cellIPD); - /*Area parentArea =*/ parentLM.getParentArea(curBlockArea); + /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); // Get reference IPD from parentArea setCurrentArea(curBlockArea); // ??? for generic operations } diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 9ccca8b9e..e12839b0b 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -327,7 +327,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager // add space before, in order to implement display-align = "center" or "after" if (layoutContext.getSpaceBefore() != 0) { - addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); + addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore())); } int startXOffset = getTable().getCommonMarginBlock().startIndent.getValue(this); @@ -404,7 +404,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager curBlockArea = new Block(); // Set up dimensions // Must get dimensions from parent area - /*Area parentArea =*/ parentLM.getParentArea(curBlockArea); + /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea); TraitSetter.setProducerID(curBlockArea, getTable().getId()); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java index 92a641ed0..92e8ba5dd 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableStepper.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableStepper.java @@ -122,7 +122,7 @@ public class TableStepper { private void calcTotalHeight() { totalHeight = 0; for (int i = 0; i < rowGroup.length; i++) { - totalHeight += rowGroup[i].getHeight().opt; + totalHeight += rowGroup[i].getHeight().getOpt(); } if (log.isDebugEnabled()) { log.debug("totalHeight=" + totalHeight); @@ -137,12 +137,12 @@ public class TableStepper { PrimaryGridUnit pgu = activeCell.getPrimaryGridUnit(); for (int i = activeRowIndex + 1; i < pgu.getRowIndex() - rowGroup[0].getIndex() + pgu.getCell().getNumberRowsSpanned(); i++) { - remain -= rowGroup[i].getHeight().opt; + remain -= rowGroup[i].getHeight().getOpt(); } maxW = Math.max(maxW, remain); } for (int i = activeRowIndex + 1; i < rowGroup.length; i++) { - maxW += rowGroup[i].getHeight().opt; + maxW += rowGroup[i].getHeight().getOpt(); } return maxW; } @@ -315,7 +315,7 @@ public class TableStepper { if (delayingNextRow) { int minStep = computeMinStep(); if (minStep < 0 || minStep >= rowFirstStep - || minStep > rowGroup[activeRowIndex].getExplicitHeight().max) { + || minStep > rowGroup[activeRowIndex].getExplicitHeight().getMax()) { if (log.isTraceEnabled()) { log.trace("Step = " + minStep); } @@ -462,7 +462,7 @@ public class TableStepper { */ private void prepareNextRow() { if (activeRowIndex < rowGroup.length - 1) { - previousRowsLength += rowGroup[activeRowIndex].getHeight().opt; + previousRowsLength += rowGroup[activeRowIndex].getHeight().getOpt(); activateCells(nextActiveCells, activeRowIndex + 1); if (log.isTraceEnabled()) { log.trace("Computing first step for row " + (activeRowIndex + 2)); diff --git a/src/java/org/apache/fop/traits/MinOptMax.java b/src/java/org/apache/fop/traits/MinOptMax.java index a4719f896..0f0422799 100644 --- a/src/java/org/apache/fop/traits/MinOptMax.java +++ b/src/java/org/apache/fop/traits/MinOptMax.java @@ -19,175 +19,326 @@ package org.apache.fop.traits; +import java.io.Serializable; + +import org.apache.fop.fo.properties.LengthRangeProperty; +import org.apache.fop.fo.properties.SpaceProperty; + /** - * This class holds the resolved (as mpoints) form of a LengthRange or - * Space type Property value. - * MinOptMax values are used during layout calculations. The instance - * variables are package visible. + * This class holds the resolved (as mpoints) form of a {@link LengthRangeProperty LengthRange} or + * {@link SpaceProperty Space} type property value. + * <p/> + * Instances of this class are immutable. All arithmetic methods like {@link #plus(MinOptMax) plus}, + * {@link #minus(MinOptMax) minus} or {@link #mult(int) mult} return a different instance. So it is + * possible to pass around instances without copying. + * <p/> + * <code>MinOptMax</code> values are used during layout calculations. */ -public class MinOptMax implements java.io.Serializable, Cloneable { +public final class MinOptMax implements Serializable { - /** Publicly visible min(imum), opt(imum) and max(imum) values.*/ - public int min; - public int opt; - public int max; + private static final long serialVersionUID = -4791524475122206142L; /** - * New min/opt/max with zero values. + * The zero <code>MinOptMax</code> instance with <code>min == opt == max == 0</code>. */ - public MinOptMax() { - this(0); - } + public static final MinOptMax ZERO = getInstance(0); + + private final int min; + private final int opt; + private final int max; /** - * New min/opt/max with one fixed value. + * Returns an instance of <code>MinOptMax</code> with the given values. * - * @param val the value for min, opt and max + * @param min the minimum value + * @param opt the optimum value + * @param max the maximum value + * @return the corresponding instance + * @throws IllegalArgumentException if <code>min > opt || max < opt</code>. */ - public MinOptMax(int val) { - this(val, val, val); + public static MinOptMax getInstance(int min, int opt, int max) { + if (min > opt) { + throw new IllegalArgumentException("min (" + min + ") > opt (" + opt + ")"); + } + if (max < opt) { + throw new IllegalArgumentException("max (" + max + ") < opt (" + opt + ")"); + } + return new MinOptMax(min, opt, max); } /** - * New min/opt/max with the three values. + * Returns an instance of <code>MinOptMax</code> with one fixed value for all three + * properties (min, opt, max). * - * @param min the minimum value - * @param opt the optimum value - * @param max the maximum value + * @param value the value for min, opt and max + * @return the corresponding instance + * @see #isStiff() */ - public MinOptMax(int min, int opt, int max) { - // TODO: assert min<=opt<=max + public static MinOptMax getInstance(int value) { + return new MinOptMax(value, value, value); + } + + // Private constructor without consistency checks + private MinOptMax(int min, int opt, int max) { + assert min <= opt && opt <= max; this.min = min; this.opt = opt; this.max = max; } /** - * Copy constructor. + * Returns the minimum value of this <code>MinOptMax</code>. * - * @param op the MinOptMax object to copy + * @return the minimum value of this <code>MinOptMax</code>. */ - public MinOptMax(MinOptMax op) { - this.min = op.min; - this.opt = op.opt; - this.max = op.max; + public int getMin() { + return min; } - // TODO: remove this. /** - * {@inheritDoc} + * Returns the optimum value of this <code>MinOptMax</code>. + * + * @return the optimum value of this <code>MinOptMax</code>. */ - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException ex) { - // SHOULD NEVER OCCUR - all members are primitive types! - return null; - } + public int getOpt() { + return opt; + } + + /** + * Returns the maximum value of this <code>MinOptMax</code>. + * + * @return the maximum value of this <code>MinOptMax</code>. + */ + public int getMax() { + return max; } /** - * Subtracts one MinOptMax instance from another returning a new one. - * @param op1 first instance to subtract from - * @param op2 second instance - * @return MinOptMax new instance + * Returns the shrinkability of this <code>MinOptMax</code> which is the absolute difference + * between <code>min</code> and <code>opt</code>. + * + * @return the shrinkability of this <code>MinOptMax</code> which is always non-negative. */ - public static MinOptMax subtract(MinOptMax op1, MinOptMax op2) { - return new MinOptMax(op1.min - op2.max, op1.opt - op2.opt, - op1.max - op2.min); + public int getShrink() { + return opt - min; } /** - * Adds one MinOptMax instance to another returning a new one. - * @param op1 first instance - * @param op2 second instance - * @return MinOptMax new instance + * Returns the stretchability of this <code>MinOptMax</code> which is the absolute difference + * between <code>opt</code> and <code>max</code>. + * + * @return the stretchability of this <code>MinOptMax</code> which is always non-negative. */ - public static MinOptMax add(MinOptMax op1, MinOptMax op2) { - return new MinOptMax(op1.min + op2.min, op1.opt + op2.opt, - op1.max + op2.max); + public int getStretch() { + return max - opt; } /** - * Multiplies a MinOptMax instance with a factor returning a new instance. - * @param op1 MinOptMax instance - * @param mult multiplier - * @return MinOptMax new instance + * Returns the sum of this <code>MinOptMax</code> and the given <code>MinOptMax</code>. + * + * @param operand the second operand of the sum (the first is this instance itself), + * @return the sum of this <code>MinOptMax</code> and the given <code>MinOptMax</code>. */ - public static MinOptMax multiply(MinOptMax op1, double mult) { - // TODO: assert mult>0 - return new MinOptMax((int)(op1.min * mult), - (int)(op1.opt * mult), (int)(op1.max * mult)); + public MinOptMax plus(MinOptMax operand) { + return new MinOptMax(min + operand.min, opt + operand.opt, max + operand.max); } + /** - * Adds another MinOptMax instance to this one. - * @param op the other instance + * Adds the given value to all three components of this instance and returns the result. + * + * @param value value to add to the min, opt, max components + * @return the result of the addition */ - public void add(MinOptMax op) { - min += op.min; - opt += op.opt; - max += op.max; + public MinOptMax plus(int value) { + return new MinOptMax(min + value, opt + value, max + value); + } + + /** + * Returns the difference of this <code>MinOptMax</code> and the given + * <code>MinOptMax</code>. This instance must be a compound of the operand and another + * <code>MinOptMax</code>, that is, there must exist a <code>MinOptMax</code> <i>m</i> + * such that <code>this.equals(m.plus(operand))</code>. In other words, the operand + * must have less shrink and stretch than this instance. + * + * @param operand the value to be subtracted + * @return the difference of this <code>MinOptMax</code> and the given + * <code>MinOptMax</code>. + * @throws ArithmeticException if this instance has strictly less shrink or stretch + * than the operand + */ + public MinOptMax minus(MinOptMax operand) { + checkCompatibility(getShrink(), operand.getShrink(), "shrink"); + checkCompatibility(getStretch(), operand.getStretch(), "stretch"); + return new MinOptMax(min - operand.min, opt - operand.opt, max - operand.max); + } + + private void checkCompatibility(int thisElasticity, int operandElasticity, String msge) { + if (thisElasticity < operandElasticity) { + throw new ArithmeticException( + "Cannot subtract a MinOptMax from another MinOptMax that has less " + msge + + " (" + thisElasticity + " < " + operandElasticity + ")"); + } } /** - * Adds min, opt and max to their counterpart components. - * @param min the value to add to the minimum value - * @param opt the value to add to the optimum value - * @param max the value to add to the maximum value + * Subtracts the given value from all three components of this instance and returns the result. + * + * @param value value to subtract from the min, opt, max components + * @return the result of the subtraction */ - public void add(int min, int opt, int max) { - this.min += min; - this.opt += opt; - this.max += max; - // TODO: assert min<=opt<=max + public MinOptMax minus(int value) { + return new MinOptMax(min - value, opt - value, max - value); } /** - * Adds a length to all components. - * @param len the length to add + * Returns an instance with the given value added to the minimal value. + * + * @param minOperand the minimal value to be added. + * @return an instance with the given value added to the minimal value. + * @throws IllegalArgumentException if <code>min + minOperand > opt || max < opt</code>. + * @deprecated Do not use! It's only for backwards compatibility. */ - public void add(int len) { - this.min += len; - this.opt += len; - this.max += len; + public MinOptMax plusMin(int minOperand) { + return getInstance(min + minOperand, opt, max); } + /** + * Returns an instance with the given value subtracted to the minimal value. + * + * @param minOperand the minimal value to be subtracted. + * @return an instance with the given value subtracted to the minimal value. + * @throws IllegalArgumentException if <code>min - minOperand > opt || max < opt</code>. + * @deprecated Do not use! It's only for backwards compatibility. + */ + public MinOptMax minusMin(int minOperand) { + return getInstance(min - minOperand, opt, max); + } /** - * Subtracts another MinOptMax instance from this one. - * @param op the other instance + * Returns an instance with the given value added to the maximal value. + * + * @param maxOperand the maximal value to be added. + * @return an instance with the given value added to the maximal value. + * @throws IllegalArgumentException if <code>min > opt || max < opt + maxOperand</code>. + * @deprecated Do not use! It's only for backwards compatibility. */ - public void subtract(MinOptMax op) { - min -= op.max; - opt -= op.opt; - max -= op.min; + public MinOptMax plusMax(int maxOperand) { + return getInstance(min, opt, max + maxOperand); } - /** @return true if this instance represents a zero-width length (min=opt=max=0) */ + /** + * Returns an instance with the given value subtracted to the maximal value. + * + * @param maxOperand the maximal value to be subtracted. + * @return an instance with the given value subtracted to the maximal value. + * @throws IllegalArgumentException if <code>min > opt || max < opt - maxOperand</code>. + * @deprecated Do not use! It's only for backwards compatibility. + */ + public MinOptMax minusMax(int maxOperand) { + return getInstance(min, opt, max - maxOperand); + } + + /** + * Returns the product of this <code>MinOptMax</code> and the given factor. + * + * @param factor the factor + * @return the product of this <code>MinOptMax</code> and the given factor + * @throws IllegalArgumentException if the factor is negative + */ + public MinOptMax mult(int factor) { + if (factor < 0) { + throw new IllegalArgumentException("factor < 0; was: " + factor); + } else if (factor == 1) { + return this; + } else { + return getInstance(min * factor, opt * factor, max * factor); + } + } + + /** + * Determines whether this <code>MinOptMax</code> represents a non-zero dimension, which means + * that not all values (min, opt, max) are zero. + * + * @return <code>true</code> if this <code>MinOptMax</code> represents a non-zero dimension; + * <code>false</code> otherwise. + */ public boolean isNonZero() { - return (min != 0 || max != 0); + return min != 0 || max != 0; + } + + /** + * Determines whether this <code>MinOptMax</code> doesn't allow for shrinking or stretching, + * which means that all values (min, opt, max) are the same. + * + * @return <code>true</code> if whether this <code>MinOptMax</code> doesn't allow for shrinking + * or stretching; <code>false</code> otherwise. + * @see #isElastic() + */ + public boolean isStiff() { + return min == max; } - /** @return true if this instance allows for shrinking or stretching */ + /** + * Determines whether this <code>MinOptMax</code> allows for shrinking or stretching, which + * means that at least one of the min or max values isn't equal to the opt value. + * + * @return <code>true</code> if this <code>MinOptMax</code> allows for shrinking or stretching; + * <code>false</code> otherwise. + * @see #isStiff() + */ public boolean isElastic() { - return (min != opt || opt != max); + return min != opt || opt != max; } - /** {@inheritDoc} */ - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("MinOptMax[min="); - if (min != opt) { - sb.append(min).append("; "); + /** + * Extends the minimum length to the given length if necessary, and adjusts opt and max + * accordingly. + * + * @param newMin the new minimum length + * @return a <code>MinOptMax</code> instance with the minimum length extended + */ + public MinOptMax extendMinimum(int newMin) { + if (min < newMin) { + int newOpt = Math.max(newMin, opt); + int newMax = Math.max(newOpt, max); + return getInstance(newMin, newOpt, newMax); + } else { + return this; } - sb.append("opt="); - if (opt != max) { - sb.append(opt).append("; "); + } + + /** + * {@inheritDoc} + */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; } - sb.append("max=").append(max); - sb.append("]"); - return sb.toString(); + + MinOptMax minOptMax = (MinOptMax) obj; + + return opt == minOptMax.opt && max == minOptMax.max && min == minOptMax.min; + } + + /** + * {@inheritDoc} + */ + public int hashCode() { + int result = min; + result = 31 * result + opt; + result = 31 * result + max; + return result; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return "MinOptMax[min = " + min + ", opt = " + opt + ", max = " + max + "]"; } } diff --git a/src/java/org/apache/fop/traits/SpaceVal.java b/src/java/org/apache/fop/traits/SpaceVal.java index e2ac6fb1c..cb709c73e 100644 --- a/src/java/org/apache/fop/traits/SpaceVal.java +++ b/src/java/org/apache/fop/traits/SpaceVal.java @@ -32,9 +32,9 @@ import org.apache.fop.fonts.Font; public class SpaceVal { private final MinOptMax space; - private final boolean bConditional; - private final boolean bForcing; - private final int iPrecedence; // Numeric only, if forcing, set to 0 + private final boolean conditional; + private final boolean forcing; + private final int precedence; // Numeric only, if forcing, set to 0 /** * Constructor for SpaceVal objects based on Space objects. @@ -42,21 +42,26 @@ public class SpaceVal { * @param context Percentage evaluation context */ public SpaceVal(SpaceProperty spaceprop, PercentBaseContext context) { - space = new MinOptMax(spaceprop.getMinimum(context).getLength().getValue(context), - spaceprop.getOptimum(context).getLength().getValue(context), - spaceprop.getMaximum(context).getLength().getValue(context)); - bConditional = - (spaceprop.getConditionality().getEnum() == Constants.EN_DISCARD); + space = createSpaceProperty(spaceprop, context); + conditional = (spaceprop.getConditionality().getEnum() == Constants.EN_DISCARD); Property precProp = spaceprop.getPrecedence(); if (precProp.getNumber() != null) { - iPrecedence = precProp.getNumber().intValue(); - bForcing = false; + precedence = precProp.getNumber().intValue(); + forcing = false; } else { - bForcing = (precProp.getEnum() == Constants.EN_FORCE); - iPrecedence = 0; + forcing = (precProp.getEnum() == Constants.EN_FORCE); + precedence = 0; } } + private static MinOptMax createSpaceProperty(SpaceProperty spaceprop, + PercentBaseContext context) { + int min = spaceprop.getMinimum(context).getLength().getValue(context); + int opt = spaceprop.getOptimum(context).getLength().getValue(context); + int max = spaceprop.getMaximum(context).getLength().getValue(context); + return MinOptMax.getInstance(min, opt, max); + } + /** * Constructor for SpaceVal objects based on the full set of properties. * @param space space to use @@ -64,36 +69,30 @@ public class SpaceVal { * @param bForcing Forcing value * @param iPrecedence Precedence value */ - public SpaceVal(MinOptMax space, boolean bConditional, - boolean bForcing, int iPrecedence) { + public SpaceVal(MinOptMax space, boolean conditional, boolean forcing, int precedence) { this.space = space; - this.bConditional = bConditional; - this.bForcing = bForcing; - this.iPrecedence = iPrecedence; + this.conditional = conditional; + this.forcing = forcing; + this.precedence = precedence; } - static public SpaceVal makeWordSpacing(Property wordSpacing, - SpaceVal letterSpacing, - Font fs) { + public static SpaceVal makeWordSpacing(Property wordSpacing, SpaceVal letterSpacing, Font fs) { if (wordSpacing.getEnum() == Constants.EN_NORMAL) { // give word spaces the possibility to shrink by a third, // and stretch by a half; int spaceCharIPD = fs.getCharWidth(' '); - MinOptMax space = new MinOptMax(-spaceCharIPD / 3, 0, spaceCharIPD / 2); + MinOptMax space = MinOptMax.getInstance(-spaceCharIPD / 3, 0, spaceCharIPD / 2); //TODO Adding 2 letter spaces here is not 100% correct. Spaces don't have letter spacing - return new SpaceVal( - MinOptMax.add - (space, MinOptMax.multiply(letterSpacing.getSpace(), 2)), - true, true, 0); + return new SpaceVal(space.plus(letterSpacing.getSpace().mult(2)), true, true, 0); } else { return new SpaceVal(wordSpacing.getSpace(), null); } } - static public SpaceVal makeLetterSpacing(Property letterSpacing) { + public static SpaceVal makeLetterSpacing(Property letterSpacing) { if (letterSpacing.getEnum() == Constants.EN_NORMAL) { // letter spaces are set to zero (or use different values?) - return new SpaceVal(new MinOptMax(0), true, true, 0); + return new SpaceVal(MinOptMax.ZERO, true, true, 0); } else { return new SpaceVal(letterSpacing.getSpace(), null); } @@ -104,7 +103,7 @@ public class SpaceVal { * @return the Conditionality value */ public boolean isConditional() { - return bConditional; + return conditional; } /** @@ -112,7 +111,7 @@ public class SpaceVal { * @return the Forcing value */ public boolean isForcing() { - return bForcing; + return forcing; } /** @@ -120,7 +119,7 @@ public class SpaceVal { * @return the Precedence value */ public int getPrecedence() { - return iPrecedence; + return precedence; } /** @@ -131,6 +130,7 @@ public class SpaceVal { return space; } + /** {@inheritDoc} */ public String toString() { return "SpaceVal: " + getSpace().toString(); } diff --git a/test/java/org/apache/fop/StandardTestSuite.java b/test/java/org/apache/fop/StandardTestSuite.java index 250ddaad6..281301789 100644 --- a/test/java/org/apache/fop/StandardTestSuite.java +++ b/test/java/org/apache/fop/StandardTestSuite.java @@ -34,6 +34,7 @@ import org.apache.fop.render.pdf.PDFCMapTestCase; import org.apache.fop.render.pdf.PDFEncodingTestCase; import org.apache.fop.render.pdf.PDFsRGBSettingsTestCase; import org.apache.fop.render.rtf.RichTextFormatTestSuite; +import org.apache.fop.traits.MinOptMaxTest; /** * Test suite for basic functionality of FOP. @@ -45,8 +46,7 @@ public class StandardTestSuite { * @return the test suite */ public static Test suite() { - TestSuite suite = new TestSuite( - "Basic functionality test suite for FOP"); + TestSuite suite = new TestSuite("Basic functionality test suite for FOP"); //$JUnit-BEGIN$ suite.addTest(BasicDriverTestSuite.suite()); suite.addTest(UtilityCodeTestSuite.suite()); @@ -62,6 +62,7 @@ public class StandardTestSuite { suite.addTest(new TestSuite(IFMimickingTestCase.class)); suite.addTest(new TestSuite(PageBoundariesTest.class)); suite.addTest(new TestSuite(PageScaleTest.class)); + suite.addTest(new TestSuite(MinOptMaxTest.class)); //$JUnit-END$ return suite; } diff --git a/test/java/org/apache/fop/traits/MinOptMaxTest.java b/test/java/org/apache/fop/traits/MinOptMaxTest.java new file mode 100644 index 000000000..17f46b7b0 --- /dev/null +++ b/test/java/org/apache/fop/traits/MinOptMaxTest.java @@ -0,0 +1,199 @@ +/* + * 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.traits; + +import junit.framework.TestCase; + +/** + * Tests the {@link MinOptMaxTest} class. + */ +public class MinOptMaxTest extends TestCase { + + /** + * Tests that the constant <code>MinOptMax.ZERO</code> is really zero. + */ + public void testZero() { + assertEquals(MinOptMax.getInstance(0), MinOptMax.ZERO); + } + + public void testNewStiffMinOptMax() { + MinOptMax value = MinOptMax.getInstance(1); + assertTrue(value.isStiff()); + assertEquals(1, value.getMin()); + assertEquals(1, value.getOpt()); + assertEquals(1, value.getMax()); + } + + public void testNewMinOptMax() { + MinOptMax value = MinOptMax.getInstance(1, 2, 3); + assertTrue(value.isElastic()); + assertEquals(1, value.getMin()); + assertEquals(2, value.getOpt()); + assertEquals(3, value.getMax()); + } + + /** + * Test that it is possible to create stiff instances with the normal factory method. + */ + public void testNewMinOptMaxStiff() { + MinOptMax value = MinOptMax.getInstance(1, 1, 1); + assertTrue(value.isStiff()); + assertEquals(1, value.getMin()); + assertEquals(1, value.getOpt()); + assertEquals(1, value.getMax()); + } + + public void testNewMinOptMaxMinGreaterOpt() { + try { + MinOptMax.getInstance(1, 0, 2); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("min (1) > opt (0)", e.getMessage()); + } + } + + public void testNewMinOptMaxMaxSmallerOpt() { + try { + MinOptMax.getInstance(0, 1, 0); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("max (0) < opt (1)", e.getMessage()); + } + } + + public void testShrinkablility() { + assertEquals(0, MinOptMax.getInstance(1).getShrink()); + assertEquals(1, MinOptMax.getInstance(1, 2, 2).getShrink()); + assertEquals(2, MinOptMax.getInstance(1, 3, 3).getShrink()); + } + + public void testStrechablilty() { + assertEquals(0, MinOptMax.getInstance(1).getStretch()); + assertEquals(1, MinOptMax.getInstance(1, 1, 2).getStretch()); + assertEquals(2, MinOptMax.getInstance(1, 1, 3).getStretch()); + } + + public void testPlus() { + assertEquals(MinOptMax.ZERO, + MinOptMax.ZERO.plus(MinOptMax.ZERO)); + assertEquals(MinOptMax.getInstance(1, 2, 3), + MinOptMax.ZERO.plus(MinOptMax.getInstance(1, 2, 3))); + assertEquals(MinOptMax.getInstance(2, 4, 6), + MinOptMax.getInstance(1, 2, 3).plus(MinOptMax.getInstance(1, 2, 3))); + assertEquals(MinOptMax.getInstance(4, 5, 6), MinOptMax.getInstance(1, 2, 3).plus(3)); + } + + public void testMinus() { + assertEquals(MinOptMax.ZERO, + MinOptMax.ZERO.minus(MinOptMax.ZERO)); + assertEquals(MinOptMax.getInstance(1, 2, 3), + MinOptMax.getInstance(1, 2, 3).plus(MinOptMax.ZERO)); + assertEquals(MinOptMax.getInstance(1, 2, 3), + MinOptMax.getInstance(2, 4, 6).minus(MinOptMax.getInstance(1, 2, 3))); + assertEquals(MinOptMax.getInstance(1, 2, 3), MinOptMax.getInstance(5, 6, 7).minus(4)); + } + + public void testMinusFail1() { + try { + MinOptMax.ZERO.minus(MinOptMax.getInstance(1, 2, 3)); + fail(); + } catch (ArithmeticException e) { + // Ok + } + } + + public void testMinusFail2() { + try { + MinOptMax.getInstance(1, 2, 3).minus(MinOptMax.getInstance(1, 3, 3)); + fail(); + } catch (ArithmeticException e) { + // Ok + } + } + + public void testMinusFail3() { + try { + MinOptMax.ZERO.minus(MinOptMax.getInstance(1, 1, 2)); + fail(); + } catch (ArithmeticException e) { + // Ok + } + } + + public void testMinusFail4() { + try { + MinOptMax.getInstance(1, 2, 3).minus(MinOptMax.getInstance(1, 1, 3)); + fail(); + } catch (ArithmeticException e) { + // Ok + } + } + + public void testMult() { + assertEquals(MinOptMax.ZERO, MinOptMax.ZERO.mult(0)); + assertEquals(MinOptMax.getInstance(1, 2, 3), MinOptMax.getInstance(1, 2, 3).mult(1)); + assertEquals(MinOptMax.getInstance(2, 4, 6), MinOptMax.getInstance(1, 2, 3).mult(2)); + } + + public void testMultFail() { + try { + MinOptMax.getInstance(1, 2, 3).mult(-1); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("factor < 0; was: -1", e.getMessage()); + } + } + + public void testNonZero() { + assertFalse(MinOptMax.ZERO.isNonZero()); + assertTrue(MinOptMax.getInstance(1).isNonZero()); + assertTrue(MinOptMax.getInstance(1, 2, 3).isNonZero()); + } + + public void testExtendMinimum() { + assertEquals(MinOptMax.getInstance(1, 1, 1), + MinOptMax.ZERO.extendMinimum(1)); + assertEquals(MinOptMax.getInstance(1, 2, 3), + MinOptMax.getInstance(1, 2, 3).extendMinimum(1)); + assertEquals(MinOptMax.getInstance(2, 2, 3), + MinOptMax.getInstance(1, 2, 3).extendMinimum(2)); + assertEquals(MinOptMax.getInstance(3, 3, 3), + MinOptMax.getInstance(1, 2, 3).extendMinimum(3)); + assertEquals(MinOptMax.getInstance(4, 4, 4), + MinOptMax.getInstance(1, 2, 3).extendMinimum(4)); + } + + public void testEquals() { + MinOptMax number = MinOptMax.getInstance(1, 3, 5); + assertEquals(number, number); + assertEquals(number, MinOptMax.getInstance(1, 3, 5)); + assertFalse(number.equals(MinOptMax.getInstance(2, 3, 5))); + assertFalse(number.equals(MinOptMax.getInstance(1, 4, 5))); + assertFalse(number.equals(MinOptMax.getInstance(1, 3, 4))); + assertFalse(number.equals(null)); + assertFalse(number.equals(new Integer(1))); + } + + public void testHashCode() { + MinOptMax number = MinOptMax.getInstance(1, 2, 3); + assertEquals(number.hashCode(), number.hashCode()); + assertEquals(number.hashCode(), MinOptMax.getInstance(1, 2, 3).hashCode()); + } +} |