aboutsummaryrefslogtreecommitdiffstats
path: root/src/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java')
-rw-r--r--src/java/org/apache/fop/fo/Constants.java9
-rw-r--r--src/java/org/apache/fop/fo/FOPropertyMapping.java11
-rw-r--r--src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java6
-rw-r--r--src/java/org/apache/fop/fo/flow/MultiCase.java60
-rw-r--r--src/java/org/apache/fop/fo/flow/MultiSwitch.java22
-rw-r--r--src/java/org/apache/fop/fo/flow/MultiToggle.java13
-rw-r--r--src/java/org/apache/fop/layoutmgr/AbstractBreaker.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java14
-rw-r--r--src/java/org/apache/fop/layoutmgr/ElementListUtils.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/LayoutContext.java35
-rw-r--r--src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java22
-rw-r--r--src/java/org/apache/fop/layoutmgr/MultiCaseLayoutManager.java61
-rw-r--r--src/java/org/apache/fop/layoutmgr/MultiSwitchLayoutManager.java163
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java71
-rw-r--r--src/java/org/apache/fop/layoutmgr/WhitespaceManagementPenalty.java90
16 files changed, 516 insertions, 71 deletions
diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java
index 086cbca40..2d53d1d46 100644
--- a/src/java/org/apache/fop/fo/Constants.java
+++ b/src/java/org/apache/fop/fo/Constants.java
@@ -819,8 +819,11 @@ public interface Constants {
/** For specifying PDF optional content group (layer) binding. */
int PR_X_LAYER = 291;
+ /** Property constant */
+ int PR_X_AUTO_TOGGLE = 292;
+
/** Number of property constants defined */
- int PROPERTY_COUNT = 291;
+ int PROPERTY_COUNT = 292;
// compound property constants
@@ -1260,6 +1263,8 @@ public interface Constants {
int EN_TB_LR = 205; // for top-to-bottom, left-to-right writing mode
/** Enumeration constant -- for fo:retrieve-table-marker */
int EN_FIRST_INCLUDING_CARRYOVER = 206;
+ /** Enumeration constant -- for auto-toggle */
+ int EN_SELECT_FIRST_FITTING = 207;
/** Number of enumeration constants defined */
- int ENUM_COUNT = 206;
+ int ENUM_COUNT = 207;
}
diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java
index cc4fe9e2c..16f7ab457 100644
--- a/src/java/org/apache/fop/fo/FOPropertyMapping.java
+++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java
@@ -581,6 +581,7 @@ public final class FOPropertyMapping implements Constants {
// background-color
m = new ColorProperty.Maker(PR_BACKGROUND_COLOR) {
+ @Override
protected Property convertPropertyDatatype(
Property p, PropertyList propertyList, FObj fo) throws PropertyException {
String nameval = p.getNCname();
@@ -1620,6 +1621,7 @@ public final class FOPropertyMapping implements Constants {
// text-align TODO: make it a StringProperty with enums.
m = new EnumProperty.Maker(PR_TEXT_ALIGN) {
+ @Override
public Property get(int subpropId, PropertyList propertyList,
boolean bTryInherit, boolean bTryDefault) throws PropertyException {
Property p = super.get(subpropId, propertyList, bTryInherit, bTryDefault);
@@ -1649,6 +1651,7 @@ public final class FOPropertyMapping implements Constants {
// text-align-last
m = new EnumProperty.Maker(PR_TEXT_ALIGN_LAST) {
+ @Override
public Property get(int subpropId, PropertyList propertyList,
boolean bTryInherit, boolean bTryDefault) throws PropertyException {
Property p = super.get(subpropId, propertyList, bTryInherit, bTryDefault);
@@ -2125,7 +2128,7 @@ public final class FOPropertyMapping implements Constants {
addPropertyMaker("starting-state", m);
// switch-to
- m = new ToBeImplementedProperty.Maker(PR_SWITCH_TO);
+ m = new StringProperty.Maker(PR_SWITCH_TO);
m.setInherited(false);
m.setDefault("xsl-any");
addPropertyMaker("switch-to", m);
@@ -2614,6 +2617,12 @@ public final class FOPropertyMapping implements Constants {
m.setDefault("");
addPropertyMaker("fox:alt-text", m);
+ // fox:auto-toggle, used only in fo:multi-switch
+ m = new EnumProperty.Maker(PR_X_AUTO_TOGGLE);
+ m.setInherited(false);
+ m.addEnum("select-first-fitting", getEnumProperty(EN_SELECT_FIRST_FITTING, "SELECT_FIRST_FITTING"));
+ m.setDefault("select-first-fitting");
+ addPropertyMaker("fox:auto-toggle", m);
// fox:border-*-radius-*
m = new CondLengthProperty.Maker(PR_X_BORDER_BEFORE_RADIUS_START);
diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
index 82db43e59..eb02540bc 100644
--- a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
@@ -49,6 +49,7 @@ public class ExtensionElementMapping extends ElementMapping {
PROPERTY_ATTRIBUTES.add("orphan-content-limit");
PROPERTY_ATTRIBUTES.add("internal-destination");
PROPERTY_ATTRIBUTES.add("disable-column-balancing");
+ PROPERTY_ATTRIBUTES.add("auto-toggle");
//These are FOP's extension properties for accessibility
PROPERTY_ATTRIBUTES.add("alt-text");
PROPERTY_ATTRIBUTES.add("header");
@@ -80,6 +81,7 @@ public class ExtensionElementMapping extends ElementMapping {
/**
* Initialize the data structures.
*/
+ @Override
protected void initialize() {
if (foObjs == null) {
foObjs = new HashMap<String, Maker>();
@@ -91,23 +93,27 @@ public class ExtensionElementMapping extends ElementMapping {
}
static class DestinationMaker extends ElementMapping.Maker {
+ @Override
public FONode make(FONode parent) {
return new Destination(parent);
}
}
static class ExternalDocumentMaker extends ElementMapping.Maker {
+ @Override
public FONode make(FONode parent) {
return new ExternalDocument(parent);
}
}
/** {@inheritDoc} */
+ @Override
public String getStandardPrefix() {
return STANDARD_PREFIX;
}
/** {@inheritDoc} */
+ @Override
public boolean isAttributeProperty(QName attributeName) {
if (!URI.equals(attributeName.getNamespaceURI())) {
throw new IllegalArgumentException("The namespace URIs don't match");
diff --git a/src/java/org/apache/fop/fo/flow/MultiCase.java b/src/java/org/apache/fop/fo/flow/MultiCase.java
index ac965dffb..ef6e444e1 100644
--- a/src/java/org/apache/fop/fo/flow/MultiCase.java
+++ b/src/java/org/apache/fop/fo/flow/MultiCase.java
@@ -19,10 +19,13 @@
package org.apache.fop.fo.flow;
+import org.xml.sax.Locator;
+
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.ValidationException;
/**
* Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_multi-case">
@@ -30,16 +33,15 @@ import org.apache.fop.fo.PropertyList;
* 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 ToBeImplementedProperty caseName;
- // private ToBeImplementedProperty caseTitle;
+ private String caseName;
+ private String caseTitle;
// Unused but valid items, commented out for performance:
// private CommonAccessibility commonAccessibility;
// End of property values
- private static boolean notImplementedWarningGiven = false;
-
/**
* Base constructor
*
@@ -47,20 +49,38 @@ public class MultiCase extends FObj {
*/
public MultiCase(FONode parent) {
super(parent);
-
- if (!notImplementedWarningGiven) {
- getFOValidationEventProducer().unimplementedFeature(this, getName(),
- getName(), getLocator());
- notImplementedWarningGiven = true;
- }
}
- /** {@inheritDoc} */
+ @Override
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
startingState = pList.get(PR_STARTING_STATE).getEnum();
- // caseName = pList.get(PR_CASE_NAME);
- // caseTitle = pList.get(PR_CASE_TITLE);
+ caseName = pList.get(PR_CASE_NAME).getString();
+ caseTitle = pList.get(PR_CASE_TITLE).getString();
+ }
+
+ /**
+ * Content Model: (#PCDATA|%inline;|%block)*
+ */
+ @Override
+ protected void validateChildNode(Locator loc, String nsURI, String localName)
+ throws ValidationException {
+ if (FO_URI.equals(nsURI)) {
+ if (!isBlockOrInlineItem(nsURI, localName) || "marker".equals(localName)) {
+ invalidChildError(loc, nsURI, localName);
+ }
+ if (!"multi-toggle".equals(localName)) {
+ // Validate against parent of fo:multi-switch
+ FONode.validateChildNode(getParent().getParent(), loc, nsURI, localName);
+ }
+ }
+ }
+
+ @Override
+ public void endOfNode() throws FOPException {
+ if (firstChild == null) {
+ missingChildElementError("(#PCDATA|%inline;|%block)*");
+ }
}
/** @return the "starting-state" property */
@@ -68,7 +88,7 @@ public class MultiCase extends FObj {
return startingState;
}
- /** {@inheritDoc} */
+ @Override
public String getLocalName() {
return "multi-case";
}
@@ -77,7 +97,17 @@ public class MultiCase extends FObj {
* {@inheritDoc}
* @return {@link org.apache.fop.fo.Constants#FO_MULTI_CASE}
*/
+ @Override
public int getNameId() {
return FO_MULTI_CASE;
}
+
+ public String getCaseName() {
+ return caseName;
+ }
+
+ public String getCaseTitle() {
+ return caseTitle;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/MultiSwitch.java b/src/java/org/apache/fop/fo/flow/MultiSwitch.java
index d8ebee4cb..1248d1ca4 100644
--- a/src/java/org/apache/fop/fo/flow/MultiSwitch.java
+++ b/src/java/org/apache/fop/fo/flow/MultiSwitch.java
@@ -19,7 +19,6 @@
package org.apache.fop.fo.flow;
-// XML
import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
@@ -39,7 +38,7 @@ public class MultiSwitch extends FObj {
// private CommonAccessibility commonAccessibility;
// End of property values
- private static boolean notImplementedWarningGiven = false;
+ private int autoToggle;
/**
* Base constructor
@@ -48,32 +47,30 @@ public class MultiSwitch extends FObj {
*/
public MultiSwitch(FONode parent) {
super(parent);
-
- if (!notImplementedWarningGiven) {
- getFOValidationEventProducer().unimplementedFeature(this, getName(),
- getName(), getLocator());
- notImplementedWarningGiven = true;
- }
}
/** {@inheritDoc} */
+ @Override
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
+ autoToggle = pList.get(PR_X_AUTO_TOGGLE).getEnum();
// autoRestore = pList.get(PR_AUTO_RESTORE);
}
-
/** {@inheritDoc} */
+ @Override
public void endOfNode() throws FOPException {
if (firstChild == null) {
missingChildElementError("(multi-case+)");
}
+ super.endOfNode();
}
/**
* {@inheritDoc}
* <br>XSL Content Model: (multi-case+)
*/
+ @Override
protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException {
if (FO_URI.equals(nsURI)) {
@@ -84,6 +81,7 @@ public class MultiSwitch extends FObj {
}
/** {@inheritDoc} */
+ @Override
public String getLocalName() {
return "multi-switch";
}
@@ -92,7 +90,13 @@ public class MultiSwitch extends FObj {
* {@inheritDoc}
* @return {@link org.apache.fop.fo.Constants#FO_MULTI_SWITCH}
*/
+ @Override
public int getNameId() {
return FO_MULTI_SWITCH;
}
+
+ public int getAutoToggle() {
+ return autoToggle;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/MultiToggle.java b/src/java/org/apache/fop/fo/flow/MultiToggle.java
index 10766680e..05a634ada 100644
--- a/src/java/org/apache/fop/fo/flow/MultiToggle.java
+++ b/src/java/org/apache/fop/fo/flow/MultiToggle.java
@@ -19,7 +19,6 @@
package org.apache.fop.fo.flow;
-// FOP
import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
@@ -27,6 +26,7 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.StringProperty;
/**
@@ -36,7 +36,7 @@ import org.apache.fop.fo.ValidationException;
public class MultiToggle extends FObj {
// The value of properties relevant for fo:multi-toggle (commented out for performance).
// private CommonAccessibility commonAccessibility;
- // public ToBeImplementedProperty prSwitchTo;
+ public StringProperty prSwitchTo;
// End of property values
private static boolean notImplementedWarningGiven = false;
@@ -57,15 +57,17 @@ public class MultiToggle extends FObj {
}
/** {@inheritDoc} */
+ @Override
public void bind(PropertyList pList) throws FOPException {
- // prSwitchTo = pList.get(PR_SWITCH_TO);
-
+ super.bind(pList);
+ prSwitchTo = (StringProperty) pList.get(PR_SWITCH_TO);
}
/**
* {@inheritDoc}
* <br>XSL Content Model: (#PCDATA|%inline;|%block;)*
*/
+ @Override
protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException {
if (FO_URI.equals(nsURI)) {
@@ -76,6 +78,7 @@ public class MultiToggle extends FObj {
}
/** {@inheritDoc} */
+ @Override
public String getLocalName() {
return "multi-toggle";
}
@@ -84,7 +87,9 @@ public class MultiToggle extends FObj {
* {@inheritDoc}
* @return {@link org.apache.fop.fo.Constants#FO_MULTI_TOGGLE}
*/
+ @Override
public int getNameId() {
return FO_MULTI_TOGGLE;
}
+
}
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
index 51e80e8d4..408a02b04 100644
--- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
+++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
@@ -107,9 +107,9 @@ public abstract class AbstractBreaker {
* of previous BlockSequence?), EN_COLUMN, EN_ODD_PAGE,
* EN_EVEN_PAGE.
*/
- private int startOn;
+ private final int startOn;
- private int displayAlign;
+ private final int displayAlign;
/**
* Creates a new BlockSequence.
@@ -142,6 +142,7 @@ public abstract class AbstractBreaker {
* Finalizes a Knuth sequence.
* @return a finalized sequence.
*/
+ @Override
public KnuthSequence endSequence() {
return endSequence(null);
}
@@ -611,7 +612,6 @@ public abstract class AbstractBreaker {
// Handle SpaceHandling(Break)Positions, see SpaceResolver!
SpaceResolver.performConditionalsNotification(effectiveList,
startElementIndex, notificationEndElementIndex, lastBreak);
-
// Add areas now!
addAreas(new KnuthPossPosIter(effectiveList,
startElementIndex, endElementIndex + 1), childLC);
diff --git a/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java
index c7048295f..4cf15f3a0 100644
--- a/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java
+++ b/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java
@@ -319,12 +319,12 @@ public abstract class BreakingAlgorithm {
protected class BestRecords {
private static final double INFINITE_DEMERITS = Double.POSITIVE_INFINITY;
- private double[] bestDemerits = new double[4];
- private KnuthNode[] bestNode = new KnuthNode[4];
- private double[] bestAdjust = new double[4];
- private int[] bestDifference = new int[4];
- private int[] bestAvailableShrink = new int[4];
- private int[] bestAvailableStretch = new int[4];
+ private final double[] bestDemerits = new double[4];
+ private final KnuthNode[] bestNode = new KnuthNode[4];
+ private final double[] bestAdjust = new double[4];
+ private final int[] bestDifference = new int[4];
+ private final int[] bestAvailableShrink = new int[4];
+ private final int[] bestAvailableStretch = new int[4];
/** Points to the fitness class which currently leads to the best demerits. */
private int bestIndex = -1;
@@ -988,7 +988,7 @@ public abstract class BreakingAlgorithm {
* @param node the node
* @param line the line number
* @param elementIdx the position index of the element
- * @param difference the difference between content-length and avaialable width
+ * @param difference the difference between content-length and available width
* @param r the adjustment ratio
* @param demerits demerits produced by the node
* @param fitnessClass the fitness class
diff --git a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
index 2bd6f429a..e6be4ca63 100644
--- a/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
+++ b/src/java/org/apache/fop/layoutmgr/ElementListUtils.java
@@ -201,7 +201,7 @@ public final class ElementListUtils {
if (last.isPenalty() && ((KnuthPenalty)last).getPenalty() < KnuthElement.INFINITE) {
return true;
} else if (last instanceof BreakElement
- && ((BreakElement)last).getPenaltyValue() < KnuthElement.INFINITE) {
+ && ((BreakElement)last).getPenaltyValue() < KnuthElement.INFINITE) {
return true;
}
return false;
diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
index 4c7afa8d6..75c61b94f 100644
--- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
@@ -48,7 +48,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager
private static Log log = LogFactory.getLog(FlowLayoutManager.class);
/** Array of areas currently being filled stored by area class */
- private BlockParent[] currentAreas = new BlockParent[Area.CLASS_MAX];
+ private final BlockParent[] currentAreas = new BlockParent[Area.CLASS_MAX];
/**
* This is the top level layout manager.
diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java
index 21983c20f..763407132 100644
--- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java
+++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java
@@ -644,26 +644,27 @@ public final class LayoutContext {
}
/** {@inheritDoc} */
+ @Override
public String toString() {
return "Layout Context:"
- + "\nStack Limit BPD: \t"
- + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString())
- + "\nTrailing Space: \t"
- + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString())
- + "\nLeading Space: \t"
- + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString())
- + "\nReference IPD: \t" + getRefIPD()
- + "\nSpace Adjust: \t" + getSpaceAdjust()
- + "\nIPD Adjust: \t" + getIPDAdjust()
- + "\nResolve Leading Space: \t" + resolveLeadingSpace()
- + "\nSuppress Break Before: \t" + suppressBreakBefore()
- + "\nIs First Area: \t" + isFirstArea()
- + "\nStarts New Area: \t" + startsNewArea()
- + "\nIs Last Area: \t" + isLastArea()
- + "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending()
+ + "\nStack Limit BPD: \t"
+ + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString())
+ + "\nTrailing Space: \t"
+ + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString())
+ + "\nLeading Space: \t"
+ + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString())
+ + "\nReference IPD: \t" + getRefIPD()
+ + "\nSpace Adjust: \t" + getSpaceAdjust()
+ + "\nIPD Adjust: \t" + getIPDAdjust()
+ + "\nResolve Leading Space: \t" + resolveLeadingSpace()
+ + "\nSuppress Break Before: \t" + suppressBreakBefore()
+ + "\nIs First Area: \t" + isFirstArea()
+ + "\nStarts New Area: \t" + startsNewArea()
+ + "\nIs Last Area: \t" + isLastArea()
+ + "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending()
+ "][keep-with-previous=" + getKeepWithPreviousPending() + "] pending"
- + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
- + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
+ + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
+ + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
}
/**
diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
index 0e333d219..88c52b383 100644
--- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
+++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
@@ -49,6 +49,8 @@ import org.apache.fop.fo.flow.InstreamForeignObject;
import org.apache.fop.fo.flow.Leader;
import org.apache.fop.fo.flow.ListBlock;
import org.apache.fop.fo.flow.ListItem;
+import org.apache.fop.fo.flow.MultiCase;
+import org.apache.fop.fo.flow.MultiSwitch;
import org.apache.fop.fo.flow.PageNumber;
import org.apache.fop.fo.flow.PageNumberCitation;
import org.apache.fop.fo.flow.PageNumberCitationLast;
@@ -96,7 +98,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
private static final Log LOG = LogFactory.getLog(LayoutManagerMapping.class);
/** The map of LayoutManagerMakers */
- private Map makers = new HashMap();
+ private final Map makers = new HashMap();
/** default constructor */
public LayoutManagerMapping() {
@@ -142,6 +144,8 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
registerMaker(TableHeader.class, new Maker());
registerMaker(Wrapper.class, new WrapperLayoutManagerMaker());
registerMaker(Title.class, new InlineLayoutManagerMaker());
+ registerMaker(MultiCase.class, new MultiCaseLayoutManagerMaker());
+ registerMaker(MultiSwitch.class, new MultiSwitchLayoutManagerMaker());
}
/**
@@ -443,4 +447,20 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
}
}
+ public class MultiSwitchLayoutManagerMaker extends Maker {
+
+ @Override
+ public void make(FONode node, List lms) {
+ lms.add(new MultiSwitchLayoutManager((MultiSwitch) node));
+ }
+ }
+
+ public class MultiCaseLayoutManagerMaker extends Maker {
+
+ @Override
+ public void make(FONode node, List lms) {
+ lms.add(new MultiCaseLayoutManager((MultiCase) node));
+ }
+ }
+
}
diff --git a/src/java/org/apache/fop/layoutmgr/MultiCaseLayoutManager.java b/src/java/org/apache/fop/layoutmgr/MultiCaseLayoutManager.java
new file mode 100644
index 000000000..9469a2fb8
--- /dev/null
+++ b/src/java/org/apache/fop/layoutmgr/MultiCaseLayoutManager.java
@@ -0,0 +1,61 @@
+/*
+ * 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.layoutmgr;
+
+import org.apache.fop.area.Area;
+import org.apache.fop.fo.FObj;
+
+public class MultiCaseLayoutManager extends BlockStackingLayoutManager {
+
+ public MultiCaseLayoutManager(FObj node) {
+ super(node);
+ }
+
+ @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 Area getParentArea(Area childArea) {
+ return parentLayoutManager.getParentArea(childArea);
+ }
+
+ @Override
+ public void addChildArea(Area childArea) {
+ parentLayoutManager.addChildArea(childArea);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void addAreas(PositionIterator posIter, LayoutContext context) {
+ AreaAdditionUtil.addAreas(this, posIter, context);
+ flush();
+ }
+
+}
diff --git a/src/java/org/apache/fop/layoutmgr/MultiSwitchLayoutManager.java b/src/java/org/apache/fop/layoutmgr/MultiSwitchLayoutManager.java
new file mode 100644
index 000000000..2bef1a815
--- /dev/null
+++ b/src/java/org/apache/fop/layoutmgr/MultiSwitchLayoutManager.java
@@ -0,0 +1,163 @@
+/*
+ * 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.layoutmgr;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.fop.area.Area;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.flow.MultiSwitch;
+
+public class MultiSwitchLayoutManager extends BlockStackingLayoutManager {
+
+ static class WhitespaceManagementPosition extends Position {
+
+ private List<ListElement> knuthList;
+
+ public WhitespaceManagementPosition(LayoutManager lm) {
+ super(lm);
+ }
+
+ public List<Position> getPositionList() {
+ List<Position> positions = new LinkedList<Position>();
+ if (knuthList != null && !knuthList.isEmpty()) {
+ SpaceResolver.performConditionalsNotification(knuthList, 0, knuthList.size() - 1, -1);
+ for (ListElement el : knuthList) {
+ if (el.getPosition() != null) {
+ positions.add(el.getPosition());
+ }
+ }
+ }
+ return positions;
+ }
+
+ public void setKnuthList(List<ListElement> knuthList) {
+ this.knuthList = knuthList;
+ }
+
+ public List<ListElement> getKnuthList() {
+ return knuthList;
+ }
+
+ }
+
+ private interface KnuthElementsGenerator {
+ List<ListElement> getKnuthElements(LayoutContext context, int alignment);
+ }
+
+ private class DefaultKnuthListGenerator implements KnuthElementsGenerator {
+
+ public List<ListElement> getKnuthElements(LayoutContext context, int alignment) {
+ List<ListElement> knuthList = new LinkedList<ListElement>();
+ LayoutManager childLM = getChildLM();
+ while (!childLM.isFinished()) {
+ LayoutContext childLC = makeChildLayoutContext(context);
+ List childElements = childLM.getNextKnuthElements(childLC, alignment);
+ if (childElements != null) {
+ List<ListElement> newList = new LinkedList<ListElement>();
+ wrapPositionElements(childElements, newList);
+ knuthList.addAll(newList);
+ }
+ }
+ return knuthList;
+ }
+
+ }
+
+ private class WhitespaceManagement implements KnuthElementsGenerator {
+
+ @SuppressWarnings("unchecked")
+ public List<ListElement> getKnuthElements(LayoutContext context, int alignment) {
+
+ MultiSwitchLayoutManager mslm = MultiSwitchLayoutManager.this;
+ List<ListElement> knuthList = new LinkedList<ListElement>();
+ WhitespaceManagementPenalty penalty = new WhitespaceManagementPenalty(
+ new WhitespaceManagementPosition(mslm));
+ LayoutManager childLM;
+ while ((childLM = getChildLM()) != null) {
+ LayoutContext childLC = makeChildLayoutContext(context);
+ List<ListElement> childElements = new LinkedList<ListElement>();
+ while (!childLM.isFinished()) {
+ childElements.addAll(childLM.getNextKnuthElements(childLC, alignment));
+ }
+ List<ListElement> wrappedElements = new LinkedList<ListElement>();
+ wrapPositionElements(childElements, wrappedElements);
+ // TODO Doing space resolution here is wrong.
+ SpaceResolver.resolveElementList(wrappedElements);
+ int contentLength = ElementListUtils.calcContentLength(wrappedElements);
+ penalty.addVariant(penalty.new Variant(wrappedElements, contentLength));
+ }
+ // Prevent the penalty from being ignored if it is at the beginning of the content
+ knuthList.add(new KnuthBox(0, new Position(mslm), false));
+ knuthList.add(penalty);
+ // Prevent the penalty from being ignored if it is at the end of the content
+ knuthList.add(new KnuthBox(0, new Position(mslm), false));
+ return knuthList;
+ }
+
+ }
+
+ private KnuthElementsGenerator knuthGen;
+
+ public MultiSwitchLayoutManager(FObj node) {
+ super(node);
+ MultiSwitch multiSwitchNode = (MultiSwitch) node;
+ if (multiSwitchNode.getAutoToggle() == Constants.EN_SELECT_FIRST_FITTING) {
+ knuthGen = new WhitespaceManagement();
+ } else {
+ knuthGen = new DefaultKnuthListGenerator();
+ }
+ }
+
+ @Override
+ public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) {
+ referenceIPD = context.getRefIPD();
+ List<ListElement> knuthList = knuthGen.getKnuthElements(context, alignment);
+ setFinished(true);
+ return knuthList;
+ }
+
+ @Override
+ public Area getParentArea(Area childArea) {
+ return parentLayoutManager.getParentArea(childArea);
+ }
+
+ @Override
+ public void addChildArea(Area childArea) {
+ parentLayoutManager.addChildArea(childArea);
+ }
+
+ @Override
+ public void addAreas(PositionIterator posIter, LayoutContext context) {
+ LinkedList<Position> positionList = new LinkedList<Position>();
+ while (posIter.hasNext()) {
+ Position pos = posIter.next();
+ if (pos instanceof WhitespaceManagementPosition) {
+ positionList.addAll(((WhitespaceManagementPosition) pos).getPositionList());
+ } else {
+ positionList.add(pos);
+ }
+ }
+ PositionIterator newPosIter = new PositionIterator(positionList.listIterator());
+ AreaAdditionUtil.addAreas(this, newPosIter, context);
+ flush();
+ }
+
+}
diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
index a5084bac5..db849a40f 100644
--- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
+++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
@@ -30,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
import org.apache.fop.layoutmgr.AbstractBreaker.PageBreakPosition;
+import org.apache.fop.layoutmgr.WhitespaceManagementPenalty.Variant;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.util.ListUtil;
@@ -38,9 +39,9 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
/** the logger for the class */
private static Log log = LogFactory.getLog(PageBreakingAlgorithm.class);
- private LayoutManager topLevelLM;
- private PageProvider pageProvider;
- private PageBreakingLayoutListener layoutListener;
+ private final LayoutManager topLevelLM;
+ private final PageProvider pageProvider;
+ private final PageBreakingLayoutListener layoutListener;
/** List of PageBreakPosition elements. */
private LinkedList<PageBreakPosition> pageBreaks = null;
@@ -73,9 +74,9 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
private int footnoteElementIndex = -1;
// demerits for a page break that splits a footnote
- private int splitFootnoteDemerits = 5000;
+ private final int splitFootnoteDemerits = 5000;
// demerits for a page break that defers a whole footnote to the following page
- private int deferredFootnoteDemerits = 10000;
+ private final int deferredFootnoteDemerits = 10000;
private MinOptMax footnoteSeparatorLength = null;
// the method noBreakBetween(int, int) uses these variables
@@ -152,6 +153,14 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
/** Index of the last inserted element of the last inserted footnote. */
public int footnoteElementIndex;
+ /**
+ * Pending variants of dynamic contents that were evaluated WRT this node.
+ * When computing page difference for a break element, the total width of these variants
+ * will be added to 'actualWidth'.
+ */
+ private final List<Variant> pendingVariants = new ArrayList<Variant>();
+ private int totalVariantsWidth;
+
public KnuthPageNode(int position,
int line, int fitness,
int totalWidth, int totalStretch, int totalShrink,
@@ -169,6 +178,11 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
this.footnoteElementIndex = footnoteElementIndex;
}
+ public void addVariant(Variant variant) {
+ pendingVariants.add(variant);
+ totalVariantsWidth += variant.width;
+ }
+
}
/**
@@ -177,11 +191,12 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
*/
protected class BestPageRecords extends BestRecords {
- private int[] bestInsertedFootnotesLength = new int[4];
- private int[] bestTotalFootnotesLength = new int[4];
- private int[] bestFootnoteListIndex = new int[4];
- private int[] bestFootnoteElementIndex = new int[4];
+ private final int[] bestInsertedFootnotesLength = new int[4];
+ private final int[] bestTotalFootnotesLength = new int[4];
+ private final int[] bestFootnoteListIndex = new int[4];
+ private final int[] bestFootnoteElementIndex = new int[4];
+ @Override
public void addRecord(double demerits, KnuthNode node, double adjust,
int availableShrink, int availableStretch,
int difference, int fitness) {
@@ -209,6 +224,8 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
public int getFootnoteElementIndex(int fitness) {
return bestFootnoteElementIndex[fitness];
}
+
+
}
/** {@inheritDoc} */
@@ -406,6 +423,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
/** {@inheritDoc} */
@Override
protected int restartFrom(KnuthNode restartingNode, int currentIndex) {
+
int returnValue = super.restartFrom(restartingNode, currentIndex);
newFootnotes = false;
if (footnotesPending) {
@@ -509,7 +527,11 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
int actualWidth = totalWidth - pageNode.totalWidth;
int footnoteSplit;
boolean canDeferOldFN;
- if (element.isPenalty()) {
+ actualWidth += pageNode.totalVariantsWidth;
+ if (element instanceof WhitespaceManagementPenalty) {
+ actualWidth += handleWhitespaceManagementPenalty(pageNode,
+ (WhitespaceManagementPenalty) element, elementIndex);
+ } else if (element.isPenalty()) {
actualWidth += element.getWidth();
}
if (footnotesPending) {
@@ -571,6 +593,24 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
}
/**
+ * Evaluates the variants corresponding to the given penalty until one that
+ * leads to an acceptable adjustment ratio is found. That variant will
+ * be added to the list of pending variants in the given active node.
+ */
+ private int handleWhitespaceManagementPenalty(KnuthPageNode activeNode,
+ WhitespaceManagementPenalty penalty, int elementIndex) {
+ for (Variant var : penalty.getVariants()) {
+ int difference = computeDifference(activeNode, var.getPenalty(), elementIndex);
+ double r = computeAdjustmentRatio(activeNode, difference);
+ if (r >= -1.0) {
+ activeNode.addVariant(var);
+ return var.width;
+ }
+ }
+ return 0;
+ }
+
+ /**
* Checks whether footnotes from preceding pages may be deferred to the page after
* the given element.
* @param node active node for the preceding page break
@@ -982,6 +1022,17 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
int total) {
//int difference = (bestActiveNode.line < total)
// ? bestActiveNode.difference : bestActiveNode.difference + fillerMinWidth;
+ // Check if the given node has an attached variant of a dynamic content
+ KnuthPageNode pageNode = (KnuthPageNode) bestActiveNode;
+ KnuthPageNode previousPageNode = ((KnuthPageNode) pageNode.previous);
+ for (Variant var : previousPageNode.pendingVariants) {
+ WhitespaceManagementPenalty penalty = var.getWhitespaceManagementPenalty();
+ // A WMPenalty should not be activated more than once. The reason is simply
+ // because a dynamic content cannot occupy multiple pages at the same time.
+ if (!penalty.hasActiveVariant()) {
+ penalty.setActiveVariant(var);
+ }
+ }
int difference = bestActiveNode.difference;
if (difference + bestActiveNode.availableShrink < 0) {
if (!autoHeight) {
diff --git a/src/java/org/apache/fop/layoutmgr/WhitespaceManagementPenalty.java b/src/java/org/apache/fop/layoutmgr/WhitespaceManagementPenalty.java
new file mode 100644
index 000000000..e34d24b9a
--- /dev/null
+++ b/src/java/org/apache/fop/layoutmgr/WhitespaceManagementPenalty.java
@@ -0,0 +1,90 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.fop.layoutmgr.MultiSwitchLayoutManager.WhitespaceManagementPosition;
+
+/**
+ * A special penalty used to specify content having multiple variants. At most
+ * only one variant will be inserted into the final document. If none of the
+ * variants fit into the remaining space on the current page, the dynamic
+ * content will be completely ignored.
+ */
+public class WhitespaceManagementPenalty extends KnuthPenalty {
+
+ public class Variant {
+
+ public final List<ListElement> knuthList;
+ public final int width;
+ private final KnuthPenalty penalty;
+
+ public Variant(List<ListElement> knuthList, int width) {
+ this.knuthList = knuthList;
+ this.width = width;
+ this.penalty = new KnuthPenalty(width, 0, false, null, false);
+ }
+
+ public KnuthElement getPenalty() {
+ return penalty;
+ }
+
+ public WhitespaceManagementPenalty getWhitespaceManagementPenalty() {
+ return WhitespaceManagementPenalty.this;
+ }
+
+ }
+
+ private final WhitespaceManagementPosition whitespaceManagementPosition;
+ private final List<Variant> variantList;
+
+ public WhitespaceManagementPenalty(WhitespaceManagementPosition pos) {
+ super(0, 0, false, pos, false);
+ this.whitespaceManagementPosition = pos;
+ variantList = new ArrayList<Variant>();
+ }
+
+ public void addVariant(Variant variant) {
+ variantList.add(variant);
+ }
+
+ public void setActiveVariant(Variant bestVariant) {
+ whitespaceManagementPosition.setKnuthList(bestVariant.knuthList);
+ }
+
+ public boolean hasActiveVariant() {
+ return whitespaceManagementPosition.getKnuthList() != null;
+ }
+
+ public List<Variant> getVariants() {
+ return variantList;
+ }
+
+ @Override
+ public String toString() {
+ String str = super.toString();
+ StringBuffer buffer = new StringBuffer(64);
+ buffer.append(" number of variants = " + variantList.size());
+ return str + buffer.toString();
+ }
+
+}