Skip to content

Commit 35a4327

Browse files
author
Joao Goncalves
committed
FOP-3181 Prevent page duplication when ipd changes
1 parent b077abb commit 35a4327

File tree

13 files changed

+299
-5
lines changed

13 files changed

+299
-5
lines changed

fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,16 @@ public boolean validateStrictly() {
539539
return factory.validateStrictly();
540540
}
541541

542+
/**
543+
* Are invalid positions to be allowed when breaking text?
544+
*
545+
* @return if invalid break positions are to be allowed
546+
* @see FopFactory#isLegacyInvalidBreakPosition()
547+
*/
548+
public boolean isLegacyInvalidBreakPosition() {
549+
return factory.isLegacyInvalidBreakPosition();
550+
}
551+
542552
/**
543553
* @return true if the indent inheritance should be broken when crossing reference area
544554
* boundaries (for more info, see the javadoc for the relative member variable)

fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class FopConfParser {
6363
private static final String LEGACY_SKIP_PAGE_POSITION_ONLY = "legacy-skip-page-position-only";
6464
private static final String LEGACY_LAST_PAGE_CHANGE_IPD = "legacy-last-page-change-ipd";
6565
private static final String LEGACY_FO_WRAPPER = "legacy-fo-wrapper";
66+
private static final String LEGACY_INVALID_BREAK_POSITION = "legacy-invalid-break-position";
6667

6768
private static final Log LOG = LogFactory.getLog(FopConfParser.class);
6869
private static final String ACCESSIBILITY = "accessibility";
@@ -330,6 +331,14 @@ private void configure(final URI baseURI, final ResourceResolver resourceResolve
330331
LogUtil.handleException(LOG, e, false);
331332
}
332333
}
334+
if (cfg.getChild(LEGACY_INVALID_BREAK_POSITION, false) != null) {
335+
try {
336+
fopFactoryBuilder.setLegacyInvalidBreakPosition(
337+
cfg.getChild(LEGACY_INVALID_BREAK_POSITION).getValueAsBoolean());
338+
} catch (ConfigurationException e) {
339+
LogUtil.handleException(LOG, e, strict);
340+
}
341+
}
333342

334343
// configure font manager
335344
new FontManagerConfigurator(cfg, baseURI, fopFactoryBuilder.getBaseURI(), resourceResolver)

fop-core/src/main/java/org/apache/fop/apps/FopFactory.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ boolean isLegacyFoWrapper() {
256256
return config.isLegacyFoWrapper();
257257
}
258258

259+
public boolean isLegacyInvalidBreakPosition() {
260+
return config.isLegacyInvalidBreakPosition();
261+
}
262+
259263
/**
260264
* Returns a new {@link Fop} instance. FOP will be configured with a default user agent
261265
* instance. Use this factory method if your output type requires an output stream.

fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,11 @@ public FopFactoryBuilder setLegacyFoWrapper(boolean b) {
375375
return this;
376376
}
377377

378+
public FopFactoryBuilder setLegacyInvalidBreakPosition(boolean value) {
379+
fopFactoryConfigBuilder.setLegacyInvalidBreakPosition(value);
380+
return this;
381+
}
382+
378383
public static class FopFactoryConfigImpl implements FopFactoryConfig {
379384

380385
private final EnvironmentProfile enviro;
@@ -429,6 +434,8 @@ public static class FopFactoryConfigImpl implements FopFactoryConfig {
429434

430435
private boolean legacyFoWrapper;
431436

437+
private boolean legacyInvalidBreakPosition = FopFactoryConfig.DEFAULT_LEGACY_INVALID_BREAK_POSITION;
438+
432439
private static final class ImageContextImpl implements ImageContext {
433440

434441
private final FopFactoryConfig config;
@@ -573,6 +580,10 @@ public boolean isLegacyFoWrapper() {
573580
return legacyFoWrapper;
574581
}
575582

583+
public boolean isLegacyInvalidBreakPosition() {
584+
return legacyInvalidBreakPosition;
585+
}
586+
576587
public Map<String, String> getHyphenationPatternNames() {
577588
return hyphPatNames;
578589
}
@@ -600,6 +611,8 @@ private interface FopFactoryConfigBuilder {
600611

601612
void setStrictUserConfigValidation(boolean validateStrictly);
602613

614+
void setLegacyInvalidBreakPosition(boolean invalidBreakPosition);
615+
603616
void setBreakIndentInheritanceOnReferenceAreaBoundary(boolean value);
604617

605618
void setSourceResolution(float dpi);
@@ -677,6 +690,10 @@ public void setStrictUserConfigValidation(boolean validateStrictly) {
677690
throwIllegalStateException();
678691
}
679692

693+
public void setLegacyInvalidBreakPosition(boolean ignoreInvalidBreakPosition) {
694+
throwIllegalStateException();
695+
}
696+
680697
public void setBreakIndentInheritanceOnReferenceAreaBoundary(
681698
boolean value) {
682699
throwIllegalStateException();
@@ -788,8 +805,7 @@ public void setStrictUserConfigValidation(
788805
config.hasStrictUserValidation = validateStrictly;
789806
}
790807

791-
public void setBreakIndentInheritanceOnReferenceAreaBoundary(
792-
boolean value) {
808+
public void setBreakIndentInheritanceOnReferenceAreaBoundary(boolean value) {
793809
config.breakIndentInheritanceOnReferenceBoundary = value;
794810
}
795811

@@ -857,6 +873,10 @@ public void setLegacyLastPageChangeIPD(boolean b) {
857873
public void setLegacyFoWrapper(boolean b) {
858874
config.legacyFoWrapper = b;
859875
}
876+
877+
public void setLegacyInvalidBreakPosition(boolean legacyInvalidBreakPosition) {
878+
config.legacyInvalidBreakPosition = legacyInvalidBreakPosition;
879+
}
860880
}
861881

862882
}

fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
// part of the API. Why would a user care how the internal objects are passed around? They shouldn't.
4141
public interface FopFactoryConfig {
4242

43+
/**
44+
* Defines if FOP should allow breaks at positions deemed invalid
45+
*/
46+
boolean DEFAULT_LEGACY_INVALID_BREAK_POSITION = false;
47+
4348
/** Defines if FOP should use an alternative rule to determine text indents */
4449
boolean DEFAULT_BREAK_INDENT_INHERITANCE = false;
4550

@@ -178,6 +183,8 @@ public interface FopFactoryConfig {
178183

179184
boolean isLegacyFoWrapper();
180185

186+
boolean isLegacyInvalidBreakPosition();
187+
181188
/** @return the hyphenation pattern names */
182189
Map<String, String> getHyphenationPatternNames();
183190

fop-core/src/main/java/org/apache/fop/layoutmgr/RestartAtLM.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,18 @@ protected LayoutManager getRestartAtLM(AbstractBreaker breaker, PageBreakingAlgo
100100
position = position.getPosition();
101101
}
102102
if (position.getPosition() == null) {
103+
if (!breaker.getPageProvider().foUserAgent.isLegacyInvalidBreakPosition()) {
104+
breaker.firstElementsForRestart = new LinkedList<>();
105+
breaker.positionAtBreak = new LeafPosition(surroundingLM, positionIndex + 1);
106+
107+
return surroundingLM;
108+
}
109+
103110
if (!position.getLM().getFObj().isForceKeepTogether()) {
104111
position.getLM().getFObj().setForceKeepTogether(true);
105112
invalidPosition = true;
106113
}
114+
107115
return null;
108116
}
109117
restartAtLM = position.getPosition().getLM();

fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ public boolean validateUserConfigStrictly() {
8181
return delegate.validateUserConfigStrictly();
8282
}
8383

84+
public boolean isLegacyInvalidBreakPosition() {
85+
return delegate.isLegacyInvalidBreakPosition();
86+
}
87+
8488
public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() {
8589
return setBreakInheritance;
8690
}

fop-core/src/test/java/org/apache/fop/intermediate/TestAssistant.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ public FopFactory getFopFactory(Document testDoc) {
129129
builder.setLegacySkipPagePositionOnly(isLegacySkipPagePositionOnly(testDoc));
130130
builder.setLegacyLastPageChangeIPD(isLegacyLastPageChangeIPD(testDoc));
131131
builder.setLegacyFoWrapper(isLegacyFoWrapper(testDoc));
132+
builder.setLegacyInvalidBreakPosition(isLegacyInvalidBreakPosition(testDoc));
132133
return builder.build();
133134
}
134135

@@ -209,6 +210,15 @@ private boolean isLegacyFoWrapper(Document testDoc) {
209210
}
210211
}
211212

213+
private boolean isLegacyInvalidBreakPosition(Document testDoc) {
214+
try {
215+
String s = eval(testDoc, "/testcase/cfg/legacy-invalid-break-position");
216+
return "true".equalsIgnoreCase(s);
217+
} catch (XPathExpressionException e) {
218+
throw new RuntimeException(e);
219+
}
220+
}
221+
212222
/**
213223
* Loads a test case into a DOM document.
214224
* @param testFile the test file

fop/test/layoutengine/standard-testcases/flow_changing-ipd_7.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
</fo:root>
5757
</fo>
5858
<checks>
59-
<eval expected="4" xpath="count(//pageViewport)" />
60-
<eval expected="Call" xpath="//pageViewport[3]//word[1]" />
59+
<eval expected="3" xpath="count(//pageViewport)"/>
60+
<eval expected="Call" xpath="//pageViewport[2]//word[1]"/>
6161
</checks>
6262
</testcase>
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one or more
4+
contributor license agreements. See the NOTICE file distributed with
5+
this work for additional information regarding copyright ownership.
6+
The ASF licenses this file to You under the Apache License, Version 2.0
7+
(the "License"); you may not use this file except in compliance with
8+
the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
-->
18+
<!-- $Id$ -->
19+
<testcase>
20+
<info>
21+
<p>
22+
This test checks that a list can be relaid out when a change in ipd happens across pages, while using the
23+
legacy invalid break position handling.
24+
</p>
25+
</info>
26+
<cfg>
27+
<legacy-invalid-break-position>true</legacy-invalid-break-position>
28+
</cfg>
29+
<fo>
30+
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
31+
<fo:layout-master-set>
32+
<fo:simple-page-master master-name="PageFront" page-width="8.5in" page-height="11in" margin-bottom="0in"
33+
margin-right="0in" margin-top="0in" margin-left="0in">
34+
<fo:region-body margin-bottom="1in" margin-right="3.1in" margin-top="4.5in" margin-left="1in"
35+
region-name="letterPageBody"/>
36+
</fo:simple-page-master>
37+
<fo:simple-page-master master-name="PageRest" page-width="8.5in" page-height="11in" margin-bottom="0in"
38+
margin-right="0in" margin-top="0in" margin-left="0in">
39+
<fo:region-body margin-bottom="1in" margin-right="1in" margin-top="1in" margin-left="1in"
40+
region-name="letterPageBody"/>
41+
</fo:simple-page-master>
42+
<fo:page-sequence-master master-name="LetterPages">
43+
<fo:repeatable-page-master-alternatives>
44+
<fo:conditional-page-master-reference page-position="first" master-reference="PageFront"/>
45+
<fo:conditional-page-master-reference page-position="rest" master-reference="PageRest"/>
46+
<fo:conditional-page-master-reference page-position="last" master-reference="PageRest"/>
47+
</fo:repeatable-page-master-alternatives>
48+
</fo:page-sequence-master>
49+
</fo:layout-master-set>
50+
<fo:page-sequence format="1" id="th_default_sequence6" initial-page-number="auto"
51+
master-reference="LetterPages">
52+
<fo:flow flow-name="letterPageBody">
53+
<fo:block>
54+
<fo:block>
55+
<fo:inline>
56+
<fo:leader/>
57+
<fo:block break-before="page"/>Call if you need us
58+
</fo:inline>
59+
</fo:block>
60+
<fo:block>
61+
<fo:block break-before="page"/>
62+
</fo:block>
63+
</fo:block>
64+
</fo:flow>
65+
</fo:page-sequence>
66+
</fo:root>
67+
</fo>
68+
<checks>
69+
<eval expected="4" xpath="count(//pageViewport)"/>
70+
<eval expected="Call" xpath="//pageViewport[3]//word[1]"/>
71+
</checks>
72+
</testcase>

0 commit comments

Comments
 (0)