diff options
13 files changed, 299 insertions, 5 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java b/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java index 4c6b2c100..32d11475f 100644 --- a/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java +++ b/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java @@ -540,6 +540,16 @@ public class FOUserAgent { } /** + * Are invalid positions to be allowed when breaking text? + * + * @return if invalid break positions are to be allowed + * @see FopFactory#isLegacyInvalidBreakPosition() + */ + public boolean isLegacyInvalidBreakPosition() { + return factory.isLegacyInvalidBreakPosition(); + } + + /** * @return true if the indent inheritance should be broken when crossing reference area * boundaries (for more info, see the javadoc for the relative member variable) * @see FopFactory#isBreakIndentInheritanceOnReferenceAreaBoundary() diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java b/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java index abc3a4edb..c610f766a 100644 --- a/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java +++ b/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java @@ -63,6 +63,7 @@ public class FopConfParser { private static final String LEGACY_SKIP_PAGE_POSITION_ONLY = "legacy-skip-page-position-only"; private static final String LEGACY_LAST_PAGE_CHANGE_IPD = "legacy-last-page-change-ipd"; private static final String LEGACY_FO_WRAPPER = "legacy-fo-wrapper"; + private static final String LEGACY_INVALID_BREAK_POSITION = "legacy-invalid-break-position"; private static final Log LOG = LogFactory.getLog(FopConfParser.class); private static final String ACCESSIBILITY = "accessibility"; @@ -330,6 +331,14 @@ public class FopConfParser { LogUtil.handleException(LOG, e, false); } } + if (cfg.getChild(LEGACY_INVALID_BREAK_POSITION, false) != null) { + try { + fopFactoryBuilder.setLegacyInvalidBreakPosition( + cfg.getChild(LEGACY_INVALID_BREAK_POSITION).getValueAsBoolean()); + } catch (ConfigurationException e) { + LogUtil.handleException(LOG, e, strict); + } + } // configure font manager new FontManagerConfigurator(cfg, baseURI, fopFactoryBuilder.getBaseURI(), resourceResolver) diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java index 46ec3ceb1..7befef58d 100644 --- a/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java +++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java @@ -256,6 +256,10 @@ public final class FopFactory implements ImageContext { return config.isLegacyFoWrapper(); } + public boolean isLegacyInvalidBreakPosition() { + return config.isLegacyInvalidBreakPosition(); + } + /** * Returns a new {@link Fop} instance. FOP will be configured with a default user agent * instance. Use this factory method if your output type requires an output stream. diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java index e89021412..243bc8570 100644 --- a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java +++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java @@ -375,6 +375,11 @@ public final class FopFactoryBuilder { return this; } + public FopFactoryBuilder setLegacyInvalidBreakPosition(boolean value) { + fopFactoryConfigBuilder.setLegacyInvalidBreakPosition(value); + return this; + } + public static class FopFactoryConfigImpl implements FopFactoryConfig { private final EnvironmentProfile enviro; @@ -429,6 +434,8 @@ public final class FopFactoryBuilder { private boolean legacyFoWrapper; + private boolean legacyInvalidBreakPosition = FopFactoryConfig.DEFAULT_LEGACY_INVALID_BREAK_POSITION; + private static final class ImageContextImpl implements ImageContext { private final FopFactoryConfig config; @@ -573,6 +580,10 @@ public final class FopFactoryBuilder { return legacyFoWrapper; } + public boolean isLegacyInvalidBreakPosition() { + return legacyInvalidBreakPosition; + } + public Map<String, String> getHyphenationPatternNames() { return hyphPatNames; } @@ -600,6 +611,8 @@ public final class FopFactoryBuilder { void setStrictUserConfigValidation(boolean validateStrictly); + void setLegacyInvalidBreakPosition(boolean invalidBreakPosition); + void setBreakIndentInheritanceOnReferenceAreaBoundary(boolean value); void setSourceResolution(float dpi); @@ -677,6 +690,10 @@ public final class FopFactoryBuilder { throwIllegalStateException(); } + public void setLegacyInvalidBreakPosition(boolean ignoreInvalidBreakPosition) { + throwIllegalStateException(); + } + public void setBreakIndentInheritanceOnReferenceAreaBoundary( boolean value) { throwIllegalStateException(); @@ -788,8 +805,7 @@ public final class FopFactoryBuilder { config.hasStrictUserValidation = validateStrictly; } - public void setBreakIndentInheritanceOnReferenceAreaBoundary( - boolean value) { + public void setBreakIndentInheritanceOnReferenceAreaBoundary(boolean value) { config.breakIndentInheritanceOnReferenceBoundary = value; } @@ -857,6 +873,10 @@ public final class FopFactoryBuilder { public void setLegacyFoWrapper(boolean b) { config.legacyFoWrapper = b; } + + public void setLegacyInvalidBreakPosition(boolean legacyInvalidBreakPosition) { + config.legacyInvalidBreakPosition = legacyInvalidBreakPosition; + } } } diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java index 190a6f556..6f62f17e3 100644 --- a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java +++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java @@ -40,6 +40,11 @@ import org.apache.fop.layoutmgr.LayoutManagerMaker; // part of the API. Why would a user care how the internal objects are passed around? They shouldn't. public interface FopFactoryConfig { + /** + * Defines if FOP should allow breaks at positions deemed invalid + */ + boolean DEFAULT_LEGACY_INVALID_BREAK_POSITION = false; + /** Defines if FOP should use an alternative rule to determine text indents */ boolean DEFAULT_BREAK_INDENT_INHERITANCE = false; @@ -178,6 +183,8 @@ public interface FopFactoryConfig { boolean isLegacyFoWrapper(); + boolean isLegacyInvalidBreakPosition(); + /** @return the hyphenation pattern names */ Map<String, String> getHyphenationPatternNames(); diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/RestartAtLM.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/RestartAtLM.java index 4a0fcd885..647c9968f 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/RestartAtLM.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/RestartAtLM.java @@ -100,10 +100,18 @@ class RestartAtLM { position = position.getPosition(); } if (position.getPosition() == null) { + if (!breaker.getPageProvider().foUserAgent.isLegacyInvalidBreakPosition()) { + breaker.firstElementsForRestart = new LinkedList<>(); + breaker.positionAtBreak = new LeafPosition(surroundingLM, positionIndex + 1); + + return surroundingLM; + } + if (!position.getLM().getFObj().isForceKeepTogether()) { position.getLM().getFObj().setForceKeepTogether(true); invalidPosition = true; } + return null; } restartAtLM = position.getPosition().getLM(); diff --git a/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java b/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java index dfd5b4bf1..319bdda12 100644 --- a/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java +++ b/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java @@ -81,6 +81,10 @@ public final class MutableConfig implements FopFactoryConfig { return delegate.validateUserConfigStrictly(); } + public boolean isLegacyInvalidBreakPosition() { + return delegate.isLegacyInvalidBreakPosition(); + } + public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() { return setBreakInheritance; } diff --git a/fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java b/fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java index 66939cfcc..33d11ddc5 100644 --- a/fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java +++ b/fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java @@ -129,6 +129,7 @@ public class TestAssistant { builder.setLegacySkipPagePositionOnly(isLegacySkipPagePositionOnly(testDoc)); builder.setLegacyLastPageChangeIPD(isLegacyLastPageChangeIPD(testDoc)); builder.setLegacyFoWrapper(isLegacyFoWrapper(testDoc)); + builder.setLegacyInvalidBreakPosition(isLegacyInvalidBreakPosition(testDoc)); return builder.build(); } @@ -209,6 +210,15 @@ public class TestAssistant { } } + private boolean isLegacyInvalidBreakPosition(Document testDoc) { + try { + String s = eval(testDoc, "/testcase/cfg/legacy-invalid-break-position"); + return "true".equalsIgnoreCase(s); + } catch (XPathExpressionException e) { + throw new RuntimeException(e); + } + } + /** * Loads a test case into a DOM document. * @param testFile the test file diff --git a/fop/test/layoutengine/standard-testcases/flow_changing-ipd_7.xml b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_7.xml index 9da3cd033..9ad4595c7 100644 --- a/fop/test/layoutengine/standard-testcases/flow_changing-ipd_7.xml +++ b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_7.xml @@ -56,7 +56,7 @@ </fo:root> </fo> <checks> - <eval expected="4" xpath="count(//pageViewport)" /> - <eval expected="Call" xpath="//pageViewport[3]//word[1]" /> + <eval expected="3" xpath="count(//pageViewport)"/> + <eval expected="Call" xpath="//pageViewport[2]//word[1]"/> </checks> </testcase> diff --git a/fop/test/layoutengine/standard-testcases/flow_changing-ipd_7_legacy.xml b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_7_legacy.xml new file mode 100644 index 000000000..6e3f62b2c --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_7_legacy.xml @@ -0,0 +1,72 @@ +<?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. +--> +<!-- $Id$ --> +<testcase> + <info> + <p> + This test checks that a list can be relaid out when a change in ipd happens across pages, while using the + legacy invalid break position handling. + </p> + </info> + <cfg> + <legacy-invalid-break-position>true</legacy-invalid-break-position> + </cfg> + <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="PageFront" page-width="8.5in" page-height="11in" margin-bottom="0in" + margin-right="0in" margin-top="0in" margin-left="0in"> + <fo:region-body margin-bottom="1in" margin-right="3.1in" margin-top="4.5in" margin-left="1in" + region-name="letterPageBody"/> + </fo:simple-page-master> + <fo:simple-page-master master-name="PageRest" page-width="8.5in" page-height="11in" margin-bottom="0in" + margin-right="0in" margin-top="0in" margin-left="0in"> + <fo:region-body margin-bottom="1in" margin-right="1in" margin-top="1in" margin-left="1in" + region-name="letterPageBody"/> + </fo:simple-page-master> + <fo:page-sequence-master master-name="LetterPages"> + <fo:repeatable-page-master-alternatives> + <fo:conditional-page-master-reference page-position="first" master-reference="PageFront"/> + <fo:conditional-page-master-reference page-position="rest" master-reference="PageRest"/> + <fo:conditional-page-master-reference page-position="last" master-reference="PageRest"/> + </fo:repeatable-page-master-alternatives> + </fo:page-sequence-master> + </fo:layout-master-set> + <fo:page-sequence format="1" id="th_default_sequence6" initial-page-number="auto" + master-reference="LetterPages"> + <fo:flow flow-name="letterPageBody"> + <fo:block> + <fo:block> + <fo:inline> + <fo:leader/> + <fo:block break-before="page"/>Call if you need us + </fo:inline> + </fo:block> + <fo:block> + <fo:block break-before="page"/> + </fo:block> + </fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="4" xpath="count(//pageViewport)"/> + <eval expected="Call" xpath="//pageViewport[3]//word[1]"/> + </checks> +</testcase> diff --git a/fop/test/layoutengine/standard-testcases/flow_changing-ipd_invalid-position.xml b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_invalid-position.xml new file mode 100644 index 000000000..af5adc44a --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_invalid-position.xml @@ -0,0 +1,74 @@ +<?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. +--> +<!-- $Id$ --> +<testcase> + <info> + <p> + This test checks that an invalid break position does not cause pages to be duplicated. + </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 margin-bottom="8mm" master-name="PageFront" page-width="210mm" + page-height="297mm" margin-right="20mm" margin-top="15mm" margin-left="20mm"> + <fo:region-body margin-right="58mm" margin-top="35mm" margin-bottom="20mm" margin-left="0mm" + region-name="PageBody"/> + </fo:simple-page-master> + <fo:simple-page-master margin-bottom="8mm" master-name="PageRest" page-width="210mm" page-height="297mm" + margin-right="20mm" margin-top="15mm" margin-left="20mm"> + <fo:region-body margin-bottom="0mm" margin-top="0mm" margin-right="0mm" margin-left="0mm" + region-name="PageBody"/> + </fo:simple-page-master> + <fo:simple-page-master margin-bottom="8mm" master-name="PageLast" page-width="210mm" page-height="297mm" + margin-right="20mm" margin-top="15mm" margin-left="20mm"> + <fo:region-body margin-bottom="0mm" margin-top="0mm" margin-right="0mm" margin-left="0mm" + region-name="PageBody"/> + </fo:simple-page-master> + <fo:page-sequence-master master-name="LetterPages"> + <fo:repeatable-page-master-alternatives> + <fo:conditional-page-master-reference page-position="rest" master-reference="PageFront"/> + <fo:conditional-page-master-reference page-position="first" master-reference="PageRest"/> + <fo:conditional-page-master-reference page-position="last" master-reference="PageLast"/> + </fo:repeatable-page-master-alternatives> + </fo:page-sequence-master> + </fo:layout-master-set> + <fo:page-sequence format="1" id="th_default_sequence1" master-reference="LetterPages"> + <fo:flow flow-name="PageBody"> + <fo:block page-break-after="always">test</fo:block> + <fo:block line-height="210mm">test2</fo:block> + <fo:block font-size="9pt" line-height="11pt"> + <fo:inline>Step 2 – Finance + <fo:block/> + </fo:inline> + If there is any Hire Purchase (HP) / Finance agreement associated with this vehicle, please + contact the finance company to provide your authorisation for Bank Box to liaise with them in + order to obtain the early settlement figure. + </fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="3" xpath="count(//pageViewport)"/> + <eval expected="test" xpath="//pageViewport[1]//lineArea[1]//text[1]/word[1]"/> + <eval expected="test2" xpath="//pageViewport[2]//lineArea[1]//text[1]/word[1]"/> + <eval expected="Step 2 – Finance" xpath="//pageViewport[2]//block[2]//lineArea[1]"/> + <eval expected="If" xpath="//pageViewport[3]//lineArea[1]//text[1]/word[1]"/> + </checks> +</testcase> diff --git a/fop/test/layoutengine/standard-testcases/flow_changing-ipd_invalid-position_1.xml b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_invalid-position_1.xml new file mode 100644 index 000000000..468808186 --- /dev/null +++ b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_invalid-position_1.xml @@ -0,0 +1,75 @@ +<?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. +--> +<!-- $Id$ --> +<testcase> + <info> + <p> + This test checks that a non empty block inside an inline does not cause a NPE. + </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 margin-bottom="8mm" master-name="PageFront" page-width="210mm" + page-height="297mm" margin-right="20mm" margin-top="15mm" margin-left="20mm"> + <fo:region-body margin-right="58mm" margin-top="35mm" margin-bottom="20mm" margin-left="0mm" + region-name="PageBody"/> + </fo:simple-page-master> + <fo:simple-page-master margin-bottom="8mm" master-name="PageRest" page-width="210mm" page-height="297mm" + margin-right="20mm" margin-top="15mm" margin-left="20mm"> + <fo:region-body margin-bottom="0mm" margin-top="0mm" margin-right="0mm" margin-left="0mm" + region-name="PageBody"/> + </fo:simple-page-master> + <fo:simple-page-master margin-bottom="8mm" master-name="PageLast" page-width="210mm" page-height="297mm" + margin-right="20mm" margin-top="15mm" margin-left="20mm"> + <fo:region-body margin-bottom="0mm" margin-top="0mm" margin-right="0mm" margin-left="0mm" + region-name="PageBody"/> + </fo:simple-page-master> + <fo:page-sequence-master master-name="LetterPages"> + <fo:repeatable-page-master-alternatives> + <fo:conditional-page-master-reference page-position="rest" master-reference="PageFront"/> + <fo:conditional-page-master-reference page-position="first" master-reference="PageRest"/> + <fo:conditional-page-master-reference page-position="last" master-reference="PageLast"/> + </fo:repeatable-page-master-alternatives> + </fo:page-sequence-master> + </fo:layout-master-set> + <fo:page-sequence format="1" id="th_default_sequence1" master-reference="LetterPages"> + <fo:flow flow-name="PageBody"> + <fo:block page-break-after="always">test</fo:block> + <fo:block line-height="210mm">test2</fo:block> + <fo:block font-size="9pt" line-height="11pt"> + <fo:inline>Step 2 – Finance + <fo:block>non empty block</fo:block> + </fo:inline> + If there is any Hire Purchase (HP) / Finance agreement associated with this vehicle, please + contact the finance company to provide your authorisation for Bank Box to liaise with them in + order to obtain the early settlement figure. + </fo:block> + </fo:flow> + </fo:page-sequence> + </fo:root> + </fo> + <checks> + <eval expected="3" xpath="count(//pageViewport)"/> + <eval expected="test" xpath="//pageViewport[1]//lineArea[1]//text[1]/word[1]"/> + <eval expected="test2" xpath="//pageViewport[2]//lineArea[1]//text[1]/word[1]"/> + <eval expected="Step 2 – Finance" xpath="//pageViewport[2]//block[2]//lineArea[1]"/> + <eval expected="non empty block" xpath="//pageViewport[2]//block[2]//lineArea[2]"/> + <eval expected="If" xpath="//pageViewport[3]//lineArea[1]//text[1]/word[1]"/> + </checks> +</testcase> diff --git a/fop/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_15.xml b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_15.xml index 6640fdb42..73f2658a7 100755 --- a/fop/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_15.xml +++ b/fop/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_15.xml @@ -55,7 +55,8 @@ </fo> <checks> <eval expected="test" xpath="//pageViewport[1]//lineArea[1]//text[1]/word[1]"/> - <eval expected="Step" xpath="//pageViewport[2]//lineArea[1]//text[1]/word[1]"/> + <eval expected="Step 2 – Finance" xpath="//pageViewport[1]//block[2]//lineArea[1]"/> + <eval expected="If" xpath="//pageViewport[2]//lineArea[1]//text[1]/word[1]"/> <eval expected="2" xpath="count(//pageViewport)"/> </checks> </testcase> |