public static final int CLASS_MAX = CLASS_SIDE_FLOAT + 1;
private int areaClass = CLASS_NORMAL;
-
+
/** the area's inline-progression-dimension */
protected int ipd;
* @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;
}
/**
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
private int bfSet = 0; // bit field
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
*/
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();
*/
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)
int averageLineLength = optimizeLineLength(effectiveList,
startElementIndex, endElementIndex);
if (averageLineLength != 0) {
- childLC.setStackLimitBP(new MinOptMax(averageLineLength));
+ childLC.setStackLimitBP(MinOptMax.getInstance(averageLineLength));
}
}
/* *** *** non-standard extension *** *** */
* @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;
accumulatedLineLength += ((KnuthBlockBox) tempEl)
.getBPD();
}
- if (blockBox.getIPDRange().min > greatestMinimumLength) {
+ if (blockBox.getIPDRange().getMin() > greatestMinimumLength) {
greatestMinimumLength = blockBox
- .getIPDRange().min;
+ .getIPDRange().getMin();
}
}
}
* @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,*/
// 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();
// 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) {
// 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);
}
}
}
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"
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"
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 */
/** {@inheritDoc} */
public void setParent(LayoutManager lm) {
- this.parentLM = lm;
+ this.parentLayoutManager = lm;
}
/** {@inheritDoc} */
public LayoutManager getParent() {
- return this.parentLM;
+ return this.parentLayoutManager;
}
/** {@inheritDoc} */
/** {@inheritDoc} */
public PageSequenceLayoutManager getPSLM() {
- return parentLM.getPSLM();
+ return parentLayoutManager.getPSLM();
}
/**
* 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();
--- /dev/null
+/*
+ * 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;
+ }
+}
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()
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?
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)) {
getBlockContainerFO().getLocator());
}
- MinOptMax stackLimit = new MinOptMax(relDims.bpd);
+ MinOptMax stackLimit = MinOptMax.getInstance(relDims.bpd);
List returnedList;
List contentList = new LinkedList();
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)) {
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);
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) {
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)) {
getBlockContainerFO().getLocator());
}
- MinOptMax stackLimit = new MinOptMax(relDims.bpd);
+ MinOptMax stackLimit = MinOptMax.getInstance(relDims.bpd);
List returnedList;
List contentList = new LinkedList();
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)) {
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)) {
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)) {
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);
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
if (isFixed()) {
availHeight = (int)getCurrentPV().getViewArea().getHeight();
} else {
- availHeight = context.getStackLimitBP().opt;
+ availHeight = context.getStackLimitBP().getOpt();
}
allocBPD = availHeight;
allocBPD -= offset.y;
}
}
} else {
- allocBPD = context.getStackLimitBP().opt;
- if (!switchedProgressionDirection) {
+ allocBPD = context.getStackLimitBP().getOpt();
+ if (!bpDirectionChanges) {
autoHeight = true;
}
}
*/
allocIPD = 0;
}
- if (switchedProgressionDirection) {
+ if (bpDirectionChanges) {
autoHeight = true;
}
}
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;
protected LayoutContext createLayoutContext() {
LayoutContext lc = super.createLayoutContext();
- lc.setRefIPD(ipd.opt);
+ lc.setRefIPD(ipd.getOpt());
lc.setWritingMode(getBlockContainerFO().getWritingMode());
return lc;
}
// 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;
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
*/
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);
// 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
// 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;
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
// 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());
*/
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);
if (sp != 0) {
Block spacer = new Block();
spacer.setBPD(sp);
- parentLM.addChildArea(spacer);
+ parentLayoutManager.addChildArea(spacer);
}
}
*/
protected void flush() {
if (getCurrentArea() != null) {
- parentLM.addChildArea(getCurrentArea());
+ parentLayoutManager.addChildArea(getCurrentArea());
}
}
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);
// 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 {
}
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));
}
}
}
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));
}
bAddedBoxAfter = true;
}
- MinOptMax totalLength = new MinOptMax(0);
- MinOptMax totalUnits = new MinOptMax(0);
+ MinOptMax totalLength = MinOptMax.ZERO;
LinkedList newList = new LinkedList();
//log.debug(" Prima scansione");
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() + " - "
}
}
// 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);
// 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;
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 {
}
}
// 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 + "-"
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
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");
}
}
newList.add(new KnuthGlue(0,
uStretchChange * bpUnit,
uShrinkChange * bpUnit,
- LINE_NUMBER_ADJUSTMENT,
+ Adjustment.LINE_NUMBER_ADJUSTMENT,
mappingPos,
false));
newList.add(new KnuthPenalty(uLengthChange * bpUnit,
newList.add(new KnuthGlue(0,
-uStretchChange * bpUnit,
-uShrinkChange * bpUnit,
- LINE_NUMBER_ADJUSTMENT,
+ Adjustment.LINE_NUMBER_ADJUSTMENT,
mappingPos,
false));
//log.debug(" PENALTY");
}
if (element.isPenalty()) {
- lengthBeforeBreak.add(new MinOptMax(-element.getWidth()));
+ lengthBeforeBreak = lengthBeforeBreak.minus(element.getWidth());
}
}
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");
// 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,
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(
*/
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);
}
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);
}
* @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());
}
/**
}
} else if (el instanceof UnresolvedListElementWithLength) {
UnresolvedListElementWithLength uel = (UnresolvedListElementWithLength)el;
- len += uel.getLength().opt;
+ len += uel.getLength().getOpt();
}
} else {
KnuthElement kel = (KnuthElement)el;
return prevBreak;
}
-}
\ No newline at end of file
+}
/** {@inheritDoc} */
public void addChildArea(Area childArea) {
childArea.setAreaClass(Area.CLASS_FOOTNOTE);
- parentLM.addChildArea(childArea);
+ parentLayoutManager.addChildArea(childArea);
}
/** @return the FootnoteBody node */
/**
* 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);
}
/**
* 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) {
/**
* 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;
* @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() {
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
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
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.
*/
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;
}
/** @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;
}
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();
public LayoutContext(int flags) {
this.flags = flags;
this.refIPD = 0;
- stackLimitBP = new MinOptMax(0);
+ stackLimitBP = MinOptMax.ZERO;
leadingSpace = null;
trailingSpace = null;
}
private int leafPos;
- public LeafPosition(LayoutManager lm, int pos) {
- super(lm);
+ public LeafPosition(LayoutManager layoutManager, int pos) {
+ super(layoutManager);
leafPos = pos;
}
+++ /dev/null
-/*
- * 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);
- }
-
-}
package org.apache.fop.layoutmgr;
-import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
pslm, footnoteSeparator, separatorArea);
footnoteSeparatorLM.doLayout();
- footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
+ footnoteSeparatorLength = MinOptMax.getInstance(separatorArea.getBPD());
}
}
this.pageProvider = pageProvider;
this.layoutListener = layoutListener;
best = new BestPageRecords();
- this.footnoteSeparatorLength = (MinOptMax) footnoteSeparatorLength.clone();
+ this.footnoteSeparatorLength = footnoteSeparatorLength;
this.autoHeight = autoHeight;
this.favorSinglePart = favorSinglePart;
}
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
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;
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;
* @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;
}
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) {
}
private void performSpaceResolutionRule1(UnresolvedListElement[] elems, MinOptMax[] lengths,
- boolean reverse) {
+ boolean reverse) {
for (int i = 0; i < elems.length; i++) {
int effIndex;
if (reverse) {
}
lengths[i] = null;
} else {
- greatestOptimum = Math.max(greatestOptimum, space.getLength().opt);
+ greatestOptimum = Math.max(greatestOptimum, space.getLength().getOpt());
remaining++;
}
}
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: "
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: "
lengths[i] = null;
remaining--;
} else {
- lengths[i].min = min;
- lengths[i].max = max;
+ lengths[i] = MinOptMax.getInstance(min, lengths[i].getOpt(), max);
}
}
}
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(),
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));
}
}
/** {@inheritDoc} */
public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append("SpaceHandlingPosition");
- return sb.toString();
+ return "SpaceHandlingPosition";
}
}
}
-
}
*/
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
* @return true if any space-specifiers have been added.
*/
public boolean hasSpaces() {
- return (spaceVals.size() > 0);
+ return !spaceVals.isEmpty();
}
/**
* 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);
}
}
}
/**
- * 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();
}
}
}
- 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());
+ }
}
}
}
}
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);
}
}
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;
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;
/**
* 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,
}
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,
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));
}
}
* @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);
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);
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(
}
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));
}
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));
}
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;
}
/**
* @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));
}
}
* @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));
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.
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;
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:
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);
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));
}
/** {@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} */
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) {
}
} 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));
}
}
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) {
package org.apache.fop.layoutmgr.inline;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
padding += borderProps.getPadding(CommonBorderPaddingBackground.AFTER, false, this);
padding += borderProps.getBorderWidth(CommonBorderPaddingBackground.AFTER, false);
}
- extraBPD = new MinOptMax(padding);
+ extraBPD = MinOptMax.getInstance(padding);
}
borderAndPadding
+= borderProps.getBorderWidth(CommonBorderPaddingBackground.END, isNotLast);
}
- return new MinOptMax(borderAndPadding);
+ return MinOptMax.getInstance(borderAndPadding);
}
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);
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 {
// 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,
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);
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
*/
protected InlineStackingLayoutManager(FObj node) {
super(node);
- extraBPD = new MinOptMax(0);
+ extraBPD = MinOptMax.ZERO;
}
/**
* @return the extra IPD as a MinOptMax spec
*/
protected MinOptMax getExtraIPD(boolean bNotFirst, boolean bNotLast) {
- return new MinOptMax(0);
+ return MinOptMax.ZERO;
}
}
/**
- * 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);
}
/** {@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} */
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;
/**
* 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;
}
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
+}
package org.apache.fop.layoutmgr.inline;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
- 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) {
KnuthPossPosIter contentIter = new KnuthPossPosIter(contentList, 0, contentList.size());
clm.addAreas(contentIter, context);
- parentLM.addChildArea(curArea);
+ parentLayoutManager.addChildArea(curArea);
while (posIter.hasNext()) {
posIter.next();
}
/** {@inheritDoc} */
- public List getNextKnuthElements(LayoutContext context,
- int alignment) {
+ public List getNextKnuthElements(LayoutContext context, int alignment) {
MinOptMax ipd;
curArea = get(context);
KnuthSequence seq = new InlineKnuthSequence();
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} */
}
/** {@inheritDoc} */
- public List getChangedKnuthElements(List oldList,
- int alignment) {
+ public List getChangedKnuthElements(List oldList, int alignment) {
if (isFinished()) {
return null;
}
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));
import java.util.LinkedList;
import java.util.List;
+import java.util.Collections;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
* @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());
}
/**
false, false, this);
TraitSetter.addBackground(area, commonBorderPaddingBackground, this);
}
- parentLM.addChildArea(area);
+ parentLayoutManager.addChildArea(area);
}
while (posIter.hasNext()) {
*/
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} */
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} */
}
/** {@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} */
// 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);
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;
// 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
&& 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) {
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;
}
(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++;
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
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));
}
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)));
}
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));
}
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));
}
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
//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));
}
}
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();
}
// 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
lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter());
}
lineArea.finalise();
- parentLM.addChildArea(lineArea);
+ parentLayoutManager.addChildArea(lineArea);
}
/**
blocklc.setTrailingSpace(new SpaceSpecifier(false));
}
lineArea.updateExtentsFromChildren();
- parentLM.addChildArea(lineArea);
+ parentLayoutManager.addChildArea(lineArea);
}
/**
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);
}
/** {@inheritDoc} */
public InlineArea get(LayoutContext context) {
- curArea = getPageNumberCitationLastInlineArea(parentLM);
+ curArea = getPageNumberCitationLastInlineArea(parentLayoutManager);
return curArea;
}
// 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());
}
/**
package org.apache.fop.layoutmgr.inline;
+import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
//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
* 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;
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;
}
}
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;
/**
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;
*
* @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;
// 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;
}
/**
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
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
// = 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));
+ }
+ }
+ }
}
/**
* @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 {
}
}
- 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);
}
}
*/
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:
|| 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);
ListUtil.removeLast(returnList);
}
- this.setFinished(true);
+ setFinished(true);
if (returnList.isEmpty()) {
return null;
} else {
}
}
- 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();
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,
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);
}
}
}
&& 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?
}
}
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;
}
// 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
*/
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) {
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;
// 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));
}
}
}
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.
*/
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()) {
// 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();
// 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());
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
curBlockArea = new Block();
// Set up dimensions
- /*Area parentArea =*/ parentLM.getParentArea(curBlockArea);
+ /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea);
// set traits
TraitSetter.setProducerID(curBlockArea, getListItemFO().getId());
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;
/**
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
* 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;
}
}
}
- 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()));
}
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;
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;
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();
.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();
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);
}
}
}
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
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
* {@inheritDoc}
*/
public List getNextKnuthElements(LayoutContext context, int alignment) {
- MinOptMax stackLimit = new MinOptMax(context.getStackLimitBP());
+ MinOptMax stackLimit = context.getStackLimitBP();
referenceIPD = context.getRefIPD();
cellIPD = referenceIPD;
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
adjustXOffset(block, dx);
adjustIPD(block, ipd);
adjustBPD(block, bpd);
- parentLM.addChildArea(block);
+ parentLayoutManager.addChildArea(block);
}
dx += ipd;
}
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();
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);
}
}
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
}
// 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);
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());
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);
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;
}
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);
}
*/
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));
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 + "]";
}
}
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.
* @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
* @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);
}
* @return the Conditionality value
*/
public boolean isConditional() {
- return bConditional;
+ return conditional;
}
/**
* @return the Forcing value
*/
public boolean isForcing() {
- return bForcing;
+ return forcing;
}
/**
* @return the Precedence value
*/
public int getPrecedence() {
- return iPrecedence;
+ return precedence;
}
/**
return space;
}
+ /** {@inheritDoc} */
public String toString() {
return "SpaceVal: " + getSpace().toString();
}
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.
* @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());
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;
}
--- /dev/null
+/*
+ * 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());
+ }
+}