public List<Position> getPositionList() {
List<Position> positions = new LinkedList<Position>();
- if (knuthList != null) {
+ if (knuthList != null && !knuthList.isEmpty()) {
SpaceResolver.performConditionalsNotification(knuthList, 0, knuthList.size() - 1, -1);
- for (ListElement elem : knuthList) {
- positions.add(elem.getPosition());
+ for (ListElement el : knuthList) {
+ if (el.getPosition() != null) {
+ positions.add(el.getPosition());
+ }
}
}
return positions;
// when they are at the end of the Knuth list.
knuthList.add(new KnuthBox(0, new Position(lm), false));
knuthList.add(bestFitPenalty);
- Variant firstVariant = bestFitPenalty.getVariants().get(0);
- BestFitPosition pos = new BestFitPosition(lm);
- pos.setKnuthList(firstVariant.knuthList);
- knuthList.add(new KnuthGlue(firstVariant.width, 0, 0, pos, false));
knuthList.add(new KnuthBox(0, new Position(lm), false));
return knuthList;
}
public final List<ListElement> knuthList;
public final int width;
+ public int penaltyIndex;
public Variant(List<ListElement> knuthList, int width) {
this.knuthList = knuthList;
this.width = width;
+ this.penaltyIndex = -1;
}
public KnuthElement toPenalty() {
package org.apache.fop.layoutmgr;
import org.apache.fop.area.Area;
-import org.apache.fop.area.Block;
-import org.apache.fop.area.LineArea;
import org.apache.fop.fo.FObj;
public class MultiCaseLayoutManager extends BlockStackingLayoutManager {
- private Block curBlockArea;
-
public MultiCaseLayoutManager(FObj node) {
super(node);
}
@Override
public Area getParentArea(Area childArea) {
- if (curBlockArea == null) {
- curBlockArea = new Block();
- curBlockArea.setIPD(super.getContentAreaIPD());
- // Set up dimensions
- // Must get dimensions from parent area
- /*Area parentArea = */parentLayoutManager.getParentArea(curBlockArea);
- setCurrentArea(curBlockArea);
- }
- return curBlockArea;
+ return parentLayoutManager.getParentArea(childArea);
}
@Override
public void addChildArea(Area childArea) {
- if (curBlockArea != null) {
- if (childArea instanceof LineArea) {
- curBlockArea.addLineArea((LineArea) childArea);
- } else {
- curBlockArea.addBlock((Block) childArea);
- }
- }
- }
-
- /**
- * Force current area to be added to parent area.
- */
- @Override
- protected void flush() {
- if (getCurrentArea() != null) {
- super.flush();
- }
+ parentLayoutManager.addChildArea(childArea);
}
/** {@inheritDoc} */
import java.util.List;
import org.apache.fop.area.Area;
-import org.apache.fop.area.Block;
-import org.apache.fop.area.LineArea;
import org.apache.fop.fo.FObj;
public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {
- private Block curBlockArea;
-
public MultiSwitchLayoutManager(FObj node) {
super(node);
}
return BestFitLayoutUtils.getKnuthList(this, childrenLists);
}
- @Override
- public Keep getKeepTogether() {
- return Keep.KEEP_AUTO;
- }
-
- @Override
- public Keep getKeepWithNext() {
- return Keep.KEEP_AUTO;
- }
-
- @Override
- public Keep getKeepWithPrevious() {
- return Keep.KEEP_AUTO;
- }
-
- @Override
- public int getContentAreaIPD() {
- if (curBlockArea != null) {
- return curBlockArea.getIPD();
- }
- return super.getContentAreaIPD();
- }
-
@Override
public Area getParentArea(Area childArea) {
- if (curBlockArea == null) {
- curBlockArea = new Block();
- curBlockArea.setIPD(super.getContentAreaIPD());
- setCurrentArea(curBlockArea);
- // Set up dimensions
- // Must get dimensions from parent area
- /*Area parentArea = */parentLayoutManager.getParentArea(curBlockArea);
- }
- return curBlockArea;
+ return parentLayoutManager.getParentArea(childArea);
}
@Override
public void addChildArea(Area childArea) {
- if (curBlockArea != null) {
- if (childArea instanceof LineArea) {
- curBlockArea.addLineArea((LineArea) childArea);
- } else {
- curBlockArea.addBlock((Block) childArea);
- }
- }
- }
-
- /**
- * Force current area to be added to parent area.
- */
- @Override
- protected void flush() {
- if (curBlockArea != null) {
- parentLayoutManager.addChildArea(getCurrentArea());
- }
+ parentLayoutManager.addChildArea(childArea);
}
@Override
AreaAdditionUtil.addAreas(this, newPosIter, context);
flush();
- // TODO removing the following line forces the generated area
- // to be rendered twice in some cases...
- curBlockArea = null;
}
}
private int currentKeepContext = Constants.EN_AUTO;
private KnuthNode lastBeforeKeepContextSwitch;
- /** Holds the variant of a dynamic content that must be attached to the next page node */
- private Variant variant;
-
/**
* Construct a page breaking algorithm.
* @param topLevelLM the top level layout manager
/** Index of the last inserted element of the last inserted footnote. */
public int footnoteElementIndex;
+ /** Current active variant attached to this node */
public final Variant variant;
+ /** Pending variant to be assigned to all descending nodes */
+ public Variant pendingVariant;
public KnuthPageNode(int position,
int line, int fitness,
bestTotalFootnotesLength[fitness] = totalFootnotesLength;
bestFootnoteListIndex[fitness] = footnoteListIndex;
bestFootnoteElementIndex[fitness] = footnoteElementIndex;
- bestVariant[fitness] = variant;
+ bestVariant[fitness] = ((KnuthPageNode) node).pendingVariant;
}
public int getInsertedFootnotesLength(int fitness) {
public Variant getVariant(int fitness) {
return bestVariant[fitness];
}
+
}
/** {@inheritDoc} */
insertedFootnotesLength, totalFootnotesLength,
footnoteListIndex, footnoteElementIndex,
adjustRatio, availableShrink, availableStretch,
- difference, totalDemerits, previous, variant);
+ difference, totalDemerits, previous,
+ (previous != null) ? ((KnuthPageNode)previous).pendingVariant : null);
}
/** {@inheritDoc} */
int actualWidth = totalWidth - pageNode.totalWidth;
int footnoteSplit;
boolean canDeferOldFN;
- variant = null;
if (element.isPenalty()) {
if (element instanceof BestFitPenalty) {
- actualWidth += handleBestFitPenalty(activeNode, (BestFitPenalty) element, elementIndex);
+ actualWidth += handleBestFitPenalty(pageNode, (BestFitPenalty) element, elementIndex);
} else {
actualWidth += element.getWidth();
+ if (pageNode.pendingVariant != null) {
+ actualWidth += ((KnuthPageNode) activeNode).pendingVariant.width;
+ }
}
}
if (footnotesPending) {
}
}
- private int handleBestFitPenalty(KnuthNode activeNode, BestFitPenalty penalty, int elementIndex) {
+ private int handleBestFitPenalty(KnuthPageNode activeNode, BestFitPenalty penalty, int elementIndex) {
for (Variant var : penalty.getVariants()) {
int difference = computeDifference(activeNode, var.toPenalty(), elementIndex);
double r = computeAdjustmentRatio(activeNode, difference);
if (r >= -1.0) {
- variant = var;
- return variant.width;
+ var.penaltyIndex = elementIndex;
+ activeNode.pendingVariant = var;
+ return var.width;
}
}
return 0;
// Check if the given node has an attached variant of a dynamic content
KnuthPageNode pageNode = (KnuthPageNode) bestActiveNode;
if (pageNode.variant != null) {
- BestFitPenalty penalty = (BestFitPenalty) par.get(pageNode.position);
+ BestFitPenalty penalty = (BestFitPenalty) par.get(pageNode.variant.penaltyIndex);
penalty.setActiveVariant(pageNode.variant);
}
int difference = bestActiveNode.difference;
<!-- 1. First variant -->
<eval expected="3" xpath="count(//pageSequence[1]/pageViewport)"/>
<eval expected="Filler" xpath="//pageSequence[1]/pageViewport[2]//flow/block[1]"/>
- <eval expected="Variant 1 line 1" xpath="//pageSequence[1]/pageViewport[2]//flow/block[3]/block/block[1]"/>
+ <eval expected="Variant 1 line 1" xpath="//pageSequence[1]/pageViewport[2]//flow/block[3]"/>
<eval expected="This text should be on page 3." xpath="//pageSequence[1]/pageViewport[3]//flow/block[1]"/>
<!-- 2. Second variant -->
<eval expected="3" xpath="count(//pageSequence[2]/pageViewport)"/>
<eval expected="Page 2 line 1" xpath="//pageSequence[2]/pageViewport[2]//flow/block[1]"/>
- <eval expected="Variant 2 line 1" xpath="//pageSequence[2]/pageViewport[2]//flow/block[4]/block/block[1]"/>
+ <eval expected="Variant 2 line 1" xpath="//pageSequence[2]/pageViewport[2]//flow/block[4]"/>
<eval expected="This text should be on page 3." xpath="//pageSequence[2]/pageViewport[3]//flow/block[1]"/>
<!-- 3. No variant -->
<eval expected="Page 2 line 2" xpath="//pageSequence[3]/pageViewport[2]//flow/block[2]"/>
<eval expected="Filler" xpath="//pageSequence[3]/pageViewport[2]//flow/block[3]"/>
<eval expected="Before the multi-switch" xpath="//pageSequence[3]/pageViewport[2]//flow/block[4]"/>
- <eval expected="2" xpath="count(//pageSequence[3]/pageViewport[3]//flow/block)"/>
- <eval expected="Variant 1 line 1" xpath="//pageSequence[3]/pageViewport[3]//flow/block[1]/block/block[1]"/>
- <eval expected="This text should be on page 3." xpath="//pageSequence[3]/pageViewport[3]//flow/block[2]"/>
+ <eval expected="3" xpath="count(//pageSequence[3]/pageViewport[3]//flow/block)"/>
+ <eval expected="Variant 1 line 1" xpath="//pageSequence[3]/pageViewport[3]//flow/block[1]"/>
+ <eval expected="Variant 1 line 2" xpath="//pageSequence[3]/pageViewport[3]//flow/block[2]"/>
+ <eval expected="This text should be on page 3." xpath="//pageSequence[3]/pageViewport[3]//flow/block[3]"/>
</checks>
</testcase>