Browse Source

Handle the case where dynamic content is in the middle of a page, selecting the first variant

Patch by Seifeddine Dridi, applied with some modifications


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_WhitespaceManagement@1578270 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-2_0
Vincent Hennebert 10 years ago
parent
commit
aa09fc131c

+ 2
- 26
src/java/org/apache/fop/fo/flow/MultiCase.java View File

@@ -33,13 +33,11 @@ import org.apache.fop.fo.ValidationException;
* TODO implement validateChildNode()
*/
public class MultiCase extends FObj {
// The value of properties relevant for fo:multi-case.

// FO multi-case properties
private int startingState;
private String caseName;
private String caseTitle;
private MultiCaseHandler multiCaseHandler;
// private ToBeImplementedProperty caseName;
// private ToBeImplementedProperty caseTitle;
// Unused but valid items, commented out for performance:
// private CommonAccessibility commonAccessibility;
// End of property values
@@ -59,12 +57,6 @@ public class MultiCase extends FObj {
startingState = pList.get(PR_STARTING_STATE).getEnum();
caseName = pList.get(PR_CASE_NAME).getString();
caseTitle = pList.get(PR_CASE_TITLE).getString();
if (startingState == EN_SHOW) {
MultiSwitch multiSwitch = (MultiSwitch) parent;
if (multiSwitch.getCurrentlyVisibleNode() == null) {
multiSwitch.setCurrentlyVisibleNode(this);
}
}
}

/**
@@ -91,14 +83,6 @@ public class MultiCase extends FObj {
}
}

@Override
protected void addChildNode(FONode child) throws FOPException {
if (child instanceof MultiCaseHandler) {
multiCaseHandler = (MultiCaseHandler) child;
}
super.addChildNode(child);
}

/** @return the "starting-state" property */
public int getStartingState() {
return startingState;
@@ -126,12 +110,4 @@ public class MultiCase extends FObj {
return caseTitle;
}

public boolean hasToggle() {
return multiCaseHandler != null;
}

MultiCaseHandler getHandler() {
return multiCaseHandler;
}

}

+ 0
- 38
src/java/org/apache/fop/fo/flow/MultiCaseHandler.java View File

@@ -1,38 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.fop.fo.flow;

import org.apache.fop.apps.FOPException;

/**
* This interface is used in conjunction with {@link MultiSwitch}
* to implement a callback system for handling fo:multi-case elements.
*/

public interface MultiCaseHandler {

/**
* A filtering function used to select one or more fo:multi-case
* elements, children of {@link MultiSwitch}.
*
* @param multiSwitch parent of the fo:multi-case elements to filter
* @throws FOPException
*/
void filter(MultiSwitch multiSwitch) throws FOPException;

}

+ 0
- 16
src/java/org/apache/fop/fo/flow/MultiSwitch.java View File

@@ -68,22 +68,6 @@ public class MultiSwitch extends FObj {
super.endOfNode();
}

@Override
public void finalizeNode() throws FOPException {
if (autoToggle.equals("best-fit")) {
// Nothing to do in this case
setCurrentlyVisibleNode(null);
} else {
FONodeIterator nodeIter = getChildNodes();
while (nodeIter.hasNext()) {
MultiCase multiCase = (MultiCase) nodeIter.next();
if (multiCase.hasToggle()) {
multiCase.getHandler().filter(this);
}
}
}
}

/**
* {@inheritDoc}
* <br>XSL Content Model: (multi-case+)

+ 1
- 36
src/java/org/apache/fop/fo/flow/MultiToggle.java View File

@@ -33,7 +33,7 @@ import org.apache.fop.fo.properties.StringProperty;
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_multi-toggle">
* <code>fo:multi-toggle<code></a> property.
*/
public class MultiToggle extends FObj implements MultiCaseHandler {
public class MultiToggle extends FObj {
// The value of properties relevant for fo:multi-toggle (commented out for performance).
// private CommonAccessibility commonAccessibility;
public StringProperty prSwitchTo;
@@ -92,39 +92,4 @@ public class MultiToggle extends FObj implements MultiCaseHandler {
return FO_MULTI_TOGGLE;
}

public void filter(MultiSwitch multiSwitch) throws FOPException {
if (multiSwitch.getCurrentlyVisibleNode() == null) {
multiSwitch.setCurrentlyVisibleNode(parent);
}

FONode currentlyVisibleMultiCase = multiSwitch.getCurrentlyVisibleNode();

if (prSwitchTo.getString().equals("xsl-any")) {
// NoOp
} else if (prSwitchTo.getString().equals("xsl-preceding")) {
FONodeIterator nodeIter = multiSwitch.getChildNodes(currentlyVisibleMultiCase);
if (nodeIter != null) {
if (!nodeIter.hasPrevious()) {
currentlyVisibleMultiCase = nodeIter.lastNode();
} else {
currentlyVisibleMultiCase = nodeIter.previousNode();
}
}
} else if (prSwitchTo.getString().equals("xsl-following")) {
FONodeIterator nodeIter = multiSwitch.getChildNodes(currentlyVisibleMultiCase);
if (nodeIter != null) {
//Ignore the first node
nodeIter.next();
if (!nodeIter.hasNext()) {
currentlyVisibleMultiCase = nodeIter.firstNode();
} else {
currentlyVisibleMultiCase = nodeIter.nextNode();
}
}
} else {
// Pick an fo:multi-case that matches a case-name...
}

multiSwitch.setCurrentlyVisibleNode(currentlyVisibleMultiCase);
}
}

+ 21
- 15
src/java/org/apache/fop/layoutmgr/BestFitLayoutUtils.java View File

@@ -20,7 +20,10 @@ package org.apache.fop.layoutmgr;
import java.util.LinkedList;
import java.util.List;

/*
import org.apache.fop.fo.flow.MultiSwitch;
import org.apache.fop.layoutmgr.BestFitPenalty.Variant;

/**
* Utility class used in {@link MultiSwitchLayoutManager}
* to handle the <i>best-fit</i> property value if specified in {@link MultiSwitch}
*/
@@ -30,32 +33,27 @@ public final class BestFitLayoutUtils {

static class BestFitPosition extends Position {

public List<ListElement> knuthList;
private List<ListElement> knuthList;

public BestFitPosition(LayoutManager lm) {
super(lm);
}

public BestFitPosition(LayoutManager lm, List<ListElement> knuthList) {
super(lm);
this.knuthList = knuthList;
}

public List<Position> getPositionList() {
List<Position> positions = new LinkedList<Position>();
if (knuthList != null) {
SpaceResolver.performConditionalsNotification(knuthList, 0, knuthList.size() - 1, -1);
for (ListElement elem : knuthList) {
if (elem.getPosition() != null && elem.getLayoutManager() != null) {
positions.add(elem.getPosition());
}
positions.add(elem.getPosition());
}
}
return positions;
}

public void setKnuthList(List<ListElement> knuthList) {
this.knuthList = knuthList;
}

}

public static List<ListElement> getKnuthList(LayoutManager lm,
@@ -65,14 +63,23 @@ public final class BestFitLayoutUtils {

BestFitPenalty bestFitPenalty = new BestFitPenalty(new BestFitPosition(lm));
for (List<ListElement> childList : childrenLists) {
// TODO Doing space resolution here is not correct.
// Space elements will simply be nulled.
SpaceResolver.resolveElementList(childList);
int contentLength = ElementListUtils.calcContentLength(childList);
bestFitPenalty.addVariant(childList, contentLength);
bestFitPenalty.addVariant(new Variant(childList, contentLength));
}
// TODO Adding the two enclosing boxes is definitely a dirty hack.
// Let's leave it like that for now, until I find a proper fix.
// TODO Adding two enclosing boxes is definitely a dirty hack.
// The first box forces the breaking algorithm to consider the penalty
// in case there are no elements preceding it
// and the last box prevents the glue and penalty from getting deleted
// 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;
}
@@ -82,9 +89,8 @@ public final class BestFitLayoutUtils {
// "unwrap" the NonLeafPositions stored in parentIter
// and put them in a new list;
LinkedList<Position> positionList = new LinkedList<Position>();
Position pos;
while (posIter.hasNext()) {
pos = posIter.next();
Position pos = posIter.next();
if (pos instanceof BestFitPosition) {
positionList.addAll(((BestFitPosition) pos).getPositionList());
} else {

+ 8
- 7
src/java/org/apache/fop/layoutmgr/BestFitPenalty.java View File

@@ -27,11 +27,11 @@ import org.apache.fop.layoutmgr.BestFitLayoutUtils.BestFitPosition;
/**
* A type of penalty used to specify a set of alternatives for the layout engine
* to choose from. The chosen alternative must have an occupied size
* that is less than the available BPD of the current page.
* less than the remaining BPD on the active page.
*/
public class BestFitPenalty extends KnuthPenalty {

public class Variant {
public static class Variant {

public final List<ListElement> knuthList;
public final int width;
@@ -40,13 +40,14 @@ public class BestFitPenalty extends KnuthPenalty {
this.knuthList = knuthList;
this.width = width;
}

public KnuthElement toPenalty() {
return new KnuthPenalty(width, 0, false, null, false);
}

}

private final BestFitPosition bestFitPosition;

private final List<Variant> variantList;

public BestFitPenalty(BestFitPosition pos) {
@@ -55,15 +56,15 @@ public class BestFitPenalty extends KnuthPenalty {
variantList = new ArrayList<Variant>();
}

public void addVariant(List<ListElement> knuthList, int width) {
variantList.add(new Variant(knuthList, width));
public void addVariant(Variant variant) {
variantList.add(variant);
}

public void activatePenalty(Variant bestVariant) {
public void setActiveVariant(Variant bestVariant) {
bestFitPosition.setKnuthList(bestVariant.knuthList);
}

public List<Variant> getVariantList() {
public List<Variant> getVariants() {
return variantList;
}


+ 3
- 31
src/java/org/apache/fop/layoutmgr/MultiSwitchLayoutManager.java View File

@@ -24,10 +24,7 @@ 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.FONode;
import org.apache.fop.fo.FONode.FONodeIterator;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.MultiSwitch;

public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {

@@ -41,7 +38,7 @@ public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {
public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) {

referenceIPD = context.getRefIPD();
List<List<ListElement>> childrenLists = new LinkedList<List<ListElement>>();
List<List<ListElement>> childrenLists = new ArrayList<List<ListElement>>();
LayoutManager childLM;
while ((childLM = getChildLM()) != null) {
if (!childLM.isFinished()) {
@@ -58,33 +55,6 @@ public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {
return BestFitLayoutUtils.getKnuthList(this, childrenLists);
}

@Override
protected List<LayoutManager> createChildLMs(int size) {
MultiSwitch multiSwitch = (MultiSwitch) getFObj();
if (multiSwitch.getCurrentlyVisibleNode() != null) {
List<LayoutManager> newLMs = new ArrayList<LayoutManager>(size);
if (childLMs.size() == 0) {
createMultiCaseLM(multiSwitch.getCurrentlyVisibleNode());
return new ArrayList<LayoutManager>(size);
}
return newLMs;
} else {
return super.createChildLMs(size);
}
}

private void createMultiCaseLM(FONode multiCase) {
FONodeIterator childIter = multiCase.getChildNodes();
while (childIter.hasNext()) {
List<LayoutManager> newLMs = new ArrayList<LayoutManager>(1);
getPSLM().getLayoutManagerMaker()
.makeLayoutManagers((childIter.nextNode()), newLMs);
if (!newLMs.isEmpty()) {
this.getParent().addChildLM(newLMs.get(0));
}
}
}

@Override
public Keep getKeepTogether() {
return Keep.KEEP_AUTO;
@@ -151,6 +121,8 @@ public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {

AreaAdditionUtil.addAreas(this, newPosIter, context);
flush();
// TODO removing the following line forces the generated area
// to be rendered twice in some cases...
curBlockArea = null;
}


+ 5
- 5
src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java View File

@@ -99,7 +99,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
private int currentKeepContext = Constants.EN_AUTO;
private KnuthNode lastBeforeKeepContextSwitch;

/** Holds the variant that should be assigned to the next node to be created */
/** Holds the variant of a dynamic content that must be attached to the next page node */
private Variant variant;

/**
@@ -458,7 +458,6 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
/** {@inheritDoc} */
@Override
protected void considerLegalBreak(KnuthElement element, int elementIdx) {
variant = null;
if (element.isPenalty()) {
int breakClass = ((KnuthPenalty) element).getBreakClass();
switch (breakClass) {
@@ -526,6 +525,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
int actualWidth = totalWidth - pageNode.totalWidth;
int footnoteSplit;
boolean canDeferOldFN;
variant = null;
if (element.isPenalty()) {
if (element instanceof BestFitPenalty) {
actualWidth += handleBestFitPenalty(activeNode, (BestFitPenalty) element, elementIndex);
@@ -592,7 +592,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
}

private int handleBestFitPenalty(KnuthNode activeNode, BestFitPenalty penalty, int elementIndex) {
for (Variant var : penalty.getVariantList()) {
for (Variant var : penalty.getVariants()) {
int difference = computeDifference(activeNode, var.toPenalty(), elementIndex);
double r = computeAdjustmentRatio(activeNode, difference);
if (r >= -1.0) {
@@ -1015,11 +1015,11 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
int total) {
//int difference = (bestActiveNode.line < total)
// ? bestActiveNode.difference : bestActiveNode.difference + fillerMinWidth;
// Check if the given node has an attached dynamic content
// 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);
penalty.activatePenalty(pageNode.variant);
penalty.setActiveVariant(pageNode.variant);
}
int difference = bestActiveNode.difference;
if (difference + bestActiveNode.availableShrink < 0) {

+ 51
- 0
test/layoutengine/standard-testcases/multi-switch_best-fit.xml View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<testcase>
<info>
<p>
Basic test for fo:multi-switch using the whitespace management extension.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="page" page-height="70pt" page-width="120pt"
margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body">
<fo:multi-switch fox:auto-toggle="best-fit">
<fo:multi-case>
<fo:block>First variant</fo:block>
</fo:multi-case>
<fo:multi-case>
<fo:block>Second variant</fo:block>
</fo:multi-case>
</fo:multi-switch>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<eval expected="1" xpath="count(//flow/block)"/>
<eval expected="First variant" xpath="//flow/block"/>
<eval expected="14400" xpath="//flow/block/@bpd"/>
</checks>
</testcase>

+ 63
- 0
test/layoutengine/standard-testcases/multi-switch_best-fit_middle-page.xml View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<testcase>
<info>
<p>
Dynamic content in the middle of a page: the first variant is selected.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="page" page-height="70pt" page-width="120pt"
margin="10pt">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt">
<fo:block>Before the multi-switch</fo:block>
<fo:multi-switch fox:auto-toggle="best-fit">
<fo:multi-case>
<fo:block>First variant</fo:block>
</fo:multi-case>
<fo:multi-case>
<fo:block>Second variant</fo:block>
<fo:block>Second variant</fo:block>
</fo:multi-case>
</fo:multi-switch>
<fo:block>After the multi-switch</fo:block>
<fo:block>Filler 1</fo:block>
<fo:block>Filler 2</fo:block>
<fo:block>This should be on page 2.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<eval expected="2" xpath="count(//pageViewport)"/>
<eval expected="5" xpath="count(//pageViewport[1]//flow/block)"/>
<eval expected="Before the multi-switch" xpath="//pageViewport[1]//flow/block[1]"/>
<eval expected="First variant" xpath="//pageViewport[1]//flow/block[2]"/>
<eval expected="After the multi-switch" xpath="//pageViewport[1]//flow/block[3]"/>
<eval expected="Filler 1" xpath="//pageViewport[1]//flow/block[4]"/>
<eval expected="Filler 2" xpath="//pageViewport[1]//flow/block[5]"/>
<eval expected="1" xpath="count(//pageViewport[2]//flow/block)"/>
<eval expected="This should be on page 2." xpath="//pageViewport[2]//flow/block[1]"/>
</checks>
</testcase>

+ 129
- 0
test/layoutengine/standard-testcases/multi-switch_best-fit_multiple-variants.xml View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<testcase>
<info>
<p>
Check that the right variant is being selected (if any), depending on the space left on the
page.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="page"
page-height="70pt" page-width="220pt" margin="10pt">
<fo:region-body background-color="#F0F0F0"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
<fo:flow flow-name="xsl-region-body">
<fo:block>Page 1 line 1</fo:block>
<fo:block
space-before.minimum="15pt"
space-before.optimum="25pt"
space-before.maximum="30pt">Page 1 line 2</fo:block>
<fo:block>Page 1 line 3</fo:block>
<fo:block font-size="16pt" line-height="20pt">Filler</fo:block>
<fo:block>Before the multi-switch</fo:block>
<fo:multi-switch fox:auto-toggle="best-fit">
<fo:multi-case>
<fo:block>Variant 1 line 1</fo:block>
<fo:block>Variant 1 line 2</fo:block>
</fo:multi-case>
<fo:multi-case>
<fo:block>Variant 2 line 1</fo:block>
</fo:multi-case>
</fo:multi-switch>
<fo:block>This text should be on page 3.</fo:block>
</fo:flow>
</fo:page-sequence>

<fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
<fo:flow flow-name="xsl-region-body">
<fo:block>Page 1 line 1</fo:block>
<fo:block
space-before.minimum="20pt"
space-before.optimum="25pt"
space-before.maximum="35pt">Page 1 line 2</fo:block>
<fo:block>Page 2 line 1</fo:block>
<fo:block font-size="16pt" line-height="20pt">Filler</fo:block>
<fo:block>Before the multi-switch</fo:block>
<fo:multi-switch fox:auto-toggle="best-fit">
<fo:multi-case>
<fo:block>Variant 1 line 1</fo:block>
<fo:block>Variant 1 line 2</fo:block>
</fo:multi-case>
<fo:multi-case>
<fo:block>Variant 2 line 1</fo:block>
</fo:multi-case>
</fo:multi-switch>
<fo:block>This text should be on page 3.</fo:block>
</fo:flow>
</fo:page-sequence>

<fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
<fo:flow flow-name="xsl-region-body">
<fo:block>Page 1 line 1</fo:block>
<fo:block
space-before.minimum="20pt"
space-before.optimum="25pt"
space-before.maximum="35pt">Page 1 line 2</fo:block>
<fo:block>Page 2 line 1</fo:block>
<fo:block>Page 2 line 2</fo:block>
<fo:block font-size="16pt" line-height="20pt">Filler</fo:block>
<fo:block>Before the multi-switch</fo:block>
<fo:multi-switch fox:auto-toggle="best-fit">
<fo:multi-case>
<fo:block>Variant 1 line 1</fo:block>
<fo:block>Variant 1 line 2</fo:block>
</fo:multi-case>
<fo:multi-case>
<fo:block>Variant 2 line 1</fo:block>
</fo:multi-case>
</fo:multi-switch>
<fo:block>This text should be on page 3.</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<!-- 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="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="This text should be on page 3." xpath="//pageSequence[2]/pageViewport[3]//flow/block[1]"/>

<!-- 3. No variant -->
<eval expected="3" xpath="count(//pageSequence[3]/pageViewport)"/>
<eval expected="4" xpath="count(//pageSequence[3]/pageViewport[2]//flow/block)"/>
<eval expected="Page 2 line 1" xpath="//pageSequence[3]/pageViewport[2]//flow/block[1]"/>
<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]"/>
</checks>
</testcase>

Loading…
Cancel
Save