aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageBreaker.java3
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageProvider.java80
-rw-r--r--status.xml4
-rw-r--r--test/events/region-body_overflow.fo115
-rw-r--r--test/java/org/apache/fop/events/EventChecker.java11
-rw-r--r--test/java/org/apache/fop/events/EventProcessingTestCase.java31
6 files changed, 198 insertions, 46 deletions
diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
index 58cb0ae4e..309f4e32f 100644
--- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java
+++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
@@ -95,8 +95,7 @@ public class PageBreaker extends AbstractBreaker {
return new PageBreakingLayoutListener() {
public void notifyOverflow(int part, int amount, FObj obj) {
- Page p = pageProvider.getPage(
- false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST);
+ Page p = pageProvider.getPageFromColumnIndex(part);
RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion(
Region.FO_REGION_BODY);
BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get(
diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java
index 0ad990899..8117d547d 100644
--- a/src/java/org/apache/fop/layoutmgr/PageProvider.java
+++ b/src/java/org/apache/fop/layoutmgr/PageProvider.java
@@ -151,18 +151,37 @@ public class PageProvider implements Constants {
return this.lastReportedBPD;
}
- // Wish there were a more elegant way to do this in Java
- private int[] getColIndexAndColCount(int index) {
+ private static class Column {
+
+ final Page page;
+
+ final int pageIndex;
+
+ final int colIndex;
+
+ final int columnCount;
+
+ Column(Page page, int pageIndex, int colIndex, int columnCount) {
+ this.page = page;
+ this.pageIndex = pageIndex;
+ this.colIndex = colIndex;
+ this.columnCount = columnCount;
+ }
+
+ }
+
+ private Column getColumn(int index) {
int columnCount = 0;
int colIndex = startColumnOfCurrentElementList + index;
int pageIndex = -1;
+ Page page;
do {
colIndex -= columnCount;
pageIndex++;
- Page page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+ page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
columnCount = page.getPageViewport().getCurrentSpan().getColumnCount();
} while (colIndex >= columnCount);
- return new int[] {colIndex, columnCount};
+ return new Column(page, pageIndex, colIndex, columnCount);
}
/**
@@ -173,22 +192,13 @@ public class PageProvider implements Constants {
* than, equal to or greater than the IPD of the following part
*/
public int compareIPDs(int index) {
- int columnCount = 0;
- int colIndex = startColumnOfCurrentElementList + index;
- int pageIndex = -1;
- Page page;
- do {
- colIndex -= columnCount;
- pageIndex++;
- page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
- columnCount = page.getPageViewport().getCurrentSpan().getColumnCount();
- } while (colIndex >= columnCount);
- if (colIndex + 1 < columnCount) {
+ Column column = getColumn(index);
+ if (column.colIndex + 1 < column.columnCount) {
// Next part is a column on same page => same IPD
return 0;
} else {
- Page nextPage = getPage(false, pageIndex + 1, RELTO_CURRENT_ELEMENT_LIST);
- return page.getPageViewport().getBodyRegion().getIPD()
+ Page nextPage = getPage(false, column.pageIndex + 1, RELTO_CURRENT_ELEMENT_LIST);
+ return column.page.getPageViewport().getBodyRegion().getIPD()
- nextPage.getPageViewport().getBodyRegion().getIPD();
}
}
@@ -199,7 +209,7 @@ public class PageProvider implements Constants {
* @return {@code true} if the break starts a new page
*/
boolean startPage(int index) {
- return getColIndexAndColCount(index)[0] == 0;
+ return getColumn(index).colIndex == 0;
}
/**
@@ -208,8 +218,8 @@ public class PageProvider implements Constants {
* @return {@code true} if the break ends a page
*/
boolean endPage(int index) {
- int[] colIndexAndColCount = getColIndexAndColCount(index);
- return colIndexAndColCount[0] == colIndexAndColCount[1] - 1;
+ Column column = getColumn(index);
+ return column.colIndex == column.columnCount - 1;
}
/**
@@ -219,7 +229,7 @@ public class PageProvider implements Constants {
* @return the number of columns
*/
int getColumnCount(int index) {
- return getColIndexAndColCount(index)[1];
+ return getColumn(index).columnCount;
}
/**
@@ -229,24 +239,12 @@ public class PageProvider implements Constants {
* @return the requested part index
*/
public int getStartingPartIndexForLastPage(int partCount) {
- int result = 0;
- int idx = 0;
- int pageIndex = 0;
- int colIndex = startColumnOfCurrentElementList;
- Page page = getPage(
- false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
- while (idx < partCount) {
- if ((colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount())) {
- colIndex = 0;
- pageIndex++;
- page = getPage(
- false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
- result = idx;
- }
- colIndex++;
- idx++;
- }
- return result;
+ int lastPartIndex = partCount - 1;
+ return lastPartIndex - getColumn(lastPartIndex).colIndex;
+ }
+
+ Page getPageFromColumnIndex(int columnIndex) {
+ return getColumn(columnIndex).page;
}
/**
@@ -291,7 +289,9 @@ public class PageProvider implements Constants {
log.trace("last page requested: " + index);
}
}
- while (intIndex >= cachedPages.size()) {
+ if (intIndex > cachedPages.size()) {
+ throw new UnsupportedOperationException("Cannot handle holes in page cache");
+ } else if (intIndex == cachedPages.size()) {
if (log.isTraceEnabled()) {
log.trace("Caching " + index);
}
diff --git a/status.xml b/status.xml
index b1635fea9..8b82d990d 100644
--- a/status.xml
+++ b/status.xml
@@ -62,6 +62,10 @@
documents. Example: the fix of marks layering will be such a case when it's done.
-->
<release version="FOP Trunk" date="TBD">
+ <action context="Layout" dev="VH" type="fix" fixes-bug="53688">
+ Wrong page number reported when a column overflows the region-body in a multi-column
+ document.
+ </action>
<action context="Renderers" dev="VH" type="add" fixes-bug="53639">
When PDF accessibility is enabled, the Scope attribute must be present in the structure tree
for table header elements.
diff --git a/test/events/region-body_overflow.fo b/test/events/region-body_overflow.fo
new file mode 100644
index 000000000..99b6dde68
--- /dev/null
+++ b/test/events/region-body_overflow.fo
@@ -0,0 +1,115 @@
+<?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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="page"
+ page-height="80pt" page-width="530pt" margin="10pt" margin-bottom="0">
+ <fo:region-body margin-bottom="20pt" column-count="5" column-gap="10pt"/>
+ <fo:region-after extent="15pt"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt">
+ <fo:static-content flow-name="xsl-region-after">
+ <fo:block text-align="center"><fo:page-number/></fo:block>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body">
+
+ <fo:block>Page 1 Column 1 Line 1</fo:block>
+ <fo:block>Page 1 Column 1 Line 2</fo:block>
+ <fo:block>Page 1 Column 1 Line 3</fo:block>
+ <fo:block>Page 1 Column 1 Line 4</fo:block>
+ <fo:block>Page 1 Column 1 Line 5</fo:block>
+ <fo:block>Page 1 Column 2 Line 1</fo:block>
+ <fo:block>Page 1 Column 2 Line 2</fo:block>
+ <fo:block>Page 1 Column 2 Line 3</fo:block>
+ <fo:block>Page 1 Column 2 Line 4</fo:block>
+ <fo:block>Page 1 Column 2 Line 5</fo:block>
+ <fo:block>Page 1 Column 3 Line 1</fo:block>
+ <fo:block>Page 1 Column 3 Line 2</fo:block>
+ <fo:block>Page 1 Column 3 Line 3</fo:block>
+ <fo:block>Page 1 Column 3 Line 4</fo:block>
+ <fo:block>Page 1 Column 3 Line 5</fo:block>
+ <fo:block>Page 1 Column 4 Line 1</fo:block>
+ <fo:block>Page 1 Column 4 Line 2</fo:block>
+ <fo:block>Page 1 Column 4 Line 3</fo:block>
+ <fo:block>Page 1 Column 4 Line 4</fo:block>
+ <fo:block>Page 1 Column 4 Line 5</fo:block>
+ <fo:block-container height="55pt" background-color="#F0F0F0">
+ <fo:block>Page 1 Column 5 Line 1</fo:block>
+ <fo:block>Page 1 Column 5 Line 2</fo:block>
+ <fo:block>Page 1 Column 5 Line 3</fo:block>
+ <fo:block>Page 1 Column 5 Line 4</fo:block>
+ <fo:block>Page 1 Column 5 Line 5</fo:block>
+ </fo:block-container>
+
+ <fo:block break-before="page">Page 2 Column 1 Line 1</fo:block>
+ <fo:block>Page 2 Column 1 Line 2</fo:block>
+ <fo:block>Page 2 Column 1 Line 3</fo:block>
+ <fo:block>Page 2 Column 1 Line 4</fo:block>
+ <fo:block>Page 2 Column 1 Line 5</fo:block>
+ <fo:block>Page 2 Column 2 Line 1</fo:block>
+ <fo:block>Page 2 Column 2 Line 2</fo:block>
+ <fo:block>Page 2 Column 2 Line 3</fo:block>
+ <fo:block>Page 2 Column 2 Line 4</fo:block>
+ <fo:block>Page 2 Column 2 Line 5</fo:block>
+ <fo:block>Page 2 Column 3 Line 1</fo:block>
+ <fo:block>Page 2 Column 3 Line 2</fo:block>
+ <fo:block>Page 2 Column 3 Line 3</fo:block>
+ <fo:block>Page 2 Column 3 Line 4</fo:block>
+ <fo:block>Page 2 Column 3 Line 5</fo:block>
+ <fo:block>Page 2 Column 4 Line 1</fo:block>
+ <fo:block>Page 2 Column 4 Line 2</fo:block>
+ <fo:block>Page 2 Column 4 Line 3</fo:block>
+ <fo:block>Page 2 Column 4 Line 4</fo:block>
+ <fo:block>Page 2 Column 4 Line 5</fo:block>
+ <fo:block>Page 2 Column 5 Line 1</fo:block>
+ <fo:block>Page 2 Column 5 Line 2</fo:block>
+ <fo:block>Page 2 Column 5 Line 3</fo:block>
+ <fo:block>Page 2 Column 5 Line 4</fo:block>
+ <fo:block>Page 2 Column 5 Line 5</fo:block>
+
+ <fo:block>Page 3 Column 1 Line 1</fo:block>
+ <fo:block>Page 3 Column 1 Line 2</fo:block>
+ <fo:block>Page 3 Column 1 Line 3</fo:block>
+ <fo:block>Page 3 Column 1 Line 4</fo:block>
+ <fo:block>Page 3 Column 1 Line 5</fo:block>
+ <fo:block>Page 3 Column 2 Line 1</fo:block>
+ <fo:block>Page 3 Column 2 Line 2</fo:block>
+ <fo:block>Page 3 Column 2 Line 3</fo:block>
+ <fo:block>Page 3 Column 2 Line 4</fo:block>
+ <fo:block>Page 3 Column 2 Line 5</fo:block>
+ <fo:block>Page 3 Column 3 Line 1</fo:block>
+ <fo:block>Page 3 Column 3 Line 2</fo:block>
+ <fo:block>Page 3 Column 3 Line 3</fo:block>
+ <fo:block>Page 3 Column 3 Line 4</fo:block>
+ <fo:block>Page 3 Column 3 Line 5</fo:block>
+ <fo:block>Page 3 Column 4 Line 1</fo:block>
+ <fo:block>Page 3 Column 4 Line 2</fo:block>
+ <fo:block>Page 3 Column 4 Line 3</fo:block>
+ <fo:block>Page 3 Column 4 Line 4</fo:block>
+ <fo:block>Page 3 Column 4 Line 5</fo:block>
+ <fo:block>Page 3 Column 5 Line 1</fo:block>
+ <fo:block>Page 3 Column 5 Line 2</fo:block>
+ <fo:block>Page 3 Column 5 Line 3</fo:block>
+ <fo:block>Page 3 Column 5 Line 4</fo:block>
+ <fo:block>Page 3 Column 5 Line 5</fo:block>
+
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
diff --git a/test/java/org/apache/fop/events/EventChecker.java b/test/java/org/apache/fop/events/EventChecker.java
index dac67a8cc..3f0eef6bb 100644
--- a/test/java/org/apache/fop/events/EventChecker.java
+++ b/test/java/org/apache/fop/events/EventChecker.java
@@ -19,6 +19,9 @@
package org.apache.fop.events;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
@@ -28,10 +31,13 @@ class EventChecker implements EventListener {
private final String expectedEventID;
+ private final Map<String, Object> expectedParams;
+
private boolean eventReceived;
- EventChecker(String expectedEventID) {
+ EventChecker(String expectedEventID, Map<String, Object> expectedParams) {
this.expectedEventID = expectedEventID;
+ this.expectedParams = expectedParams;
}
public void processEvent(Event event) {
@@ -39,6 +45,9 @@ class EventChecker implements EventListener {
String id = event.getEventID();
if (id.equals(expectedEventID)) {
eventReceived = true;
+ for (Map.Entry<String, Object> param : expectedParams.entrySet()) {
+ assertEquals(event.getParam(param.getKey()), param.getValue());
+ }
}
}
diff --git a/test/java/org/apache/fop/events/EventProcessingTestCase.java b/test/java/org/apache/fop/events/EventProcessingTestCase.java
index 9338fc01a..fb17c9c0c 100644
--- a/test/java/org/apache/fop/events/EventProcessingTestCase.java
+++ b/test/java/org/apache/fop/events/EventProcessingTestCase.java
@@ -22,6 +22,9 @@ package org.apache.fop.events;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
@@ -62,9 +65,10 @@ public class EventProcessingTestCase {
CONFIG_BASE_DIR = base.resolve("test/config/");
}
- public void doTest(InputStream inStream, URI fopConf, String expectedEventID, String mimeType)
- throws Exception {
- EventChecker eventChecker = new EventChecker(expectedEventID);
+
+ public void doTest(InputStream inStream, URI fopConf, String expectedEventID, String mimeType,
+ Map<String, Object> expectedParams) throws Exception {
+ EventChecker eventChecker = new EventChecker(expectedEventID, expectedParams);
FopFactory fopFactory;
if (fopConf != null) {
fopFactory = FopFactory.newInstance(new File(fopConf));
@@ -81,6 +85,19 @@ public class EventProcessingTestCase {
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
eventChecker.end();
+
+ }
+
+ public void doTest(InputStream inStream, URI fopConf, String expectedEventID, String mimeType)
+ throws Exception {
+ Map<String, Object> noParams = Collections.emptyMap();
+ doTest(inStream, fopConf, expectedEventID, mimeType, noParams);
+ }
+
+ public void doTest(String filename, String expectedEventID, Map<String, Object> expectedParams)
+ throws Exception {
+ doTest(BASE_DIR.resolve(filename).toURL().openStream(), null, expectedEventID,
+ MimeConstants.MIME_PDF, expectedParams);
}
public void doTest(String filename, String expectedEventID) throws Exception {
@@ -133,4 +150,12 @@ public class EventProcessingTestCase {
public void testViewportBPDOverflow() throws Exception {
doTest("viewport-overflow.fo", BlockLevelEventProducer.class.getName() + ".viewportBPDOverflow");
}
+
+ @Test
+ public void testPageOverflow() throws Exception {
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put("page", "1");
+ doTest("region-body_overflow.fo", BlockLevelEventProducer.class.getName() + ".regionOverflow",
+ params);
+ }
}