]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
FOP-2335: Content is missing after IPD change
authorSimon Steiner <ssteiner@apache.org>
Wed, 6 Jan 2016 12:13:52 +0000 (12:13 +0000)
committerSimon Steiner <ssteiner@apache.org>
Wed, 6 Jan 2016 12:13:52 +0000 (12:13 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1723297 13f79535-47bb-0310-9956-ffa450edef68

30 files changed:
src/java/org/apache/fop/area/BodyRegion.java
src/java/org/apache/fop/area/MainReference.java
src/java/org/apache/fop/fo/pagination/PageSequence.java
src/java/org/apache/fop/fo/pagination/PageSequenceMaster.java
src/java/org/apache/fop/fo/pagination/RepeatablePageMasterAlternatives.java
src/java/org/apache/fop/fo/pagination/RepeatablePageMasterReference.java
src/java/org/apache/fop/fo/pagination/Root.java
src/java/org/apache/fop/fo/pagination/SinglePageMasterReference.java
src/java/org/apache/fop/fo/pagination/SubSequenceSpecifier.java
src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java
src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.java
src/java/org/apache/fop/layoutmgr/BlockLevelEventProducer.xml
src/java/org/apache/fop/layoutmgr/PageBreaker.java
src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
src/java/org/apache/fop/layoutmgr/PageProvider.java
src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
test/layoutengine/standard-testcases/basic_link_to_last_page.xml
test/layoutengine/standard-testcases/flow_changing-ipd_columns.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_1.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_2.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_3.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_4.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_5.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_6.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_7.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_8.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_last-page_9.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/flow_changing-ipd_no-last-page.xml [new file with mode: 0644]

index 89bb206f2d73028a29af41ce873095dfd2be18c0..df7e914b71b03a7501adb311b8970d95853c6b7e 100644 (file)
@@ -81,6 +81,15 @@ public class BodyRegion extends RegionReference {
         return this.columnGap;
     }
 
+    int getContentIPD() {
+        RegionViewport rv = getRegionViewport();
+        return getIPD() - rv.getBorderAndPaddingWidthStart() - rv.getBorderAndPaddingWidthEnd();
+    }
+
+    public int getColumnIPD() {
+        return (getContentIPD() - (columnCount - 1) * columnGap) / columnCount;
+    }
+
     /**
      * Get the main reference area.
      *
index efc16515d6b1345c5eaa6f142ec71e47f59f7daf..9778db87ff01000e9b503766db5056d067a635fe 100644 (file)
@@ -59,12 +59,8 @@ public class MainReference extends Area {
             //Remove the current one if it is empty
             spanAreas.remove(spanAreas.size() - 1);
         }
-        RegionViewport rv = parent.getRegionViewport();
-        int ipdWidth = parent.getIPD()
-            - rv.getBorderAndPaddingWidthStart() - rv.getBorderAndPaddingWidthEnd();
-
         Span newSpan = new Span(((spanAll) ? 1 : getColumnCount()),
-                getColumnGap(), ipdWidth);
+                getColumnGap(), parent.getContentIPD());
         spanAreas.add(newSpan);
         return getCurrentSpan();
     }
index 6afd15e819477d3e5d6536beaffb7091ccef970c..a1a966e9098aa62621581783d964d55bb0f92c26 100644 (file)
@@ -454,4 +454,14 @@ public class PageSequence extends AbstractPageSequence implements WritingModeTra
         this.flowMap.clear();
     }
 
+    public SimplePageMaster getLastSimplePageMaster(int page, boolean isFirstPage, boolean isBlank) {
+        boolean isOddPage = ((page % 2) != 0); // please findbugs...
+        log.debug("getNextSimplePageMaster(page=" + page + " isOdd=" + isOddPage + " isFirst="
+                + isFirstPage + " isLast=true" + " isBlank=" + isBlank + ")");
+        if (pageSequenceMaster == null) {
+            return simplePageMaster;
+        }
+        return pageSequenceMaster.getLastSimplePageMaster(isOddPage, isFirstPage, isBlank, getMainFlow()
+                .getFlowName());
+    }
 }
index 86d5ff6638e14e01054cc7002cc0020736fc633d..f218e43b4e6a66c3dfa1b2feedb74759f77ab860 100644 (file)
@@ -254,6 +254,24 @@ public class PageSequenceMaster extends FObj {
         return FO_PAGE_SEQUENCE_MASTER;
     }
 
+    public SimplePageMaster getLastSimplePageMaster(boolean isOddPage, boolean isFirstPage, boolean isBlank,
+            String flowName) {
+        if (currentSubSequence == null) {
+            currentSubSequence = getNextSubSequence();
+            if (currentSubSequence == null) {
+                blockLevelEventProducer.missingSubsequencesInPageSequenceMaster(this, masterName,
+                        getLocator());
+            }
+            if (currentSubSequence.isInfinite() && !currentSubSequence.canProcess(flowName)) {
+                throw new PageProductionException(
+                        "The current sub-sequence will not terminate whilst processing the main flow");
+            }
+        }
+
+        SimplePageMaster pageMaster = currentSubSequence.getLastPageMaster(isOddPage, isFirstPage, isBlank,
+                blockLevelEventProducer);
+        return pageMaster;
+    }
 
 }
 
index dc69c600dc017a000b9545627f97807e9899f2bc..2914fb9a8f9412ffccc6aec7348432989e6fc827 100644 (file)
@@ -31,6 +31,7 @@ import org.apache.fop.fo.FObj;
 import org.apache.fop.fo.PropertyList;
 import org.apache.fop.fo.ValidationException;
 import org.apache.fop.fo.properties.Property;
+import org.apache.fop.layoutmgr.BlockLevelEventProducer;
 
 /**
  * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_repeatable-page-master-alternatives">
@@ -136,6 +137,22 @@ public class RepeatablePageMasterAlternatives extends FObj
         return null;
     }
 
+    public SimplePageMaster getLastPageMaster(boolean isOddPage, boolean isFirstPage, boolean isBlankPage,
+                                              BlockLevelEventProducer blockLevelEventProducer) {
+        for (ConditionalPageMasterReference cpmr : conditionalPageMasterRefs) {
+            if (cpmr.isValid(isOddPage, isFirstPage, true, isBlankPage)) {
+                return cpmr.getMaster();
+            }
+        }
+        blockLevelEventProducer.lastPageMasterReferenceMissing(this, getLocator());
+        for (ConditionalPageMasterReference cpmr : conditionalPageMasterRefs) {
+            if (cpmr.isValid(isOddPage, isFirstPage, false, isBlankPage)) {
+                return cpmr.getMaster();
+            }
+        }
+        throw new PageProductionException("Last page master not found: oddpage=" + isOddPage
+                + " firstpage=" + isFirstPage + " blankpage=" + isBlankPage);
+    }
 
     /**
      * Adds a new conditional page master reference.
index f6d41ce8b97f7971c3ec67d3eace14708bf07907..5e43c02b1bb21d7dc822bd035877baba34fa02ee 100644 (file)
@@ -101,6 +101,11 @@ public class RepeatablePageMasterReference extends FObj
         return master;
     }
 
+    public SimplePageMaster getLastPageMaster(boolean isOddPage, boolean isFirstPage, boolean isEmptyPage,
+                                              BlockLevelEventProducer blockLevelEventProducer) {
+        return getNextPageMaster(isOddPage, isFirstPage, true, isEmptyPage);
+    }
+
     /**
      * Get the value of the <code>maximum-repeats</code> property.
      * @return the "maximum-repeats" property
index cb433a06470f1747bfe3b4192be69ef13cae4cd2..51309a65d1dfcc3a5ab17c4b7a197ef72ac15c0d 100644 (file)
@@ -75,6 +75,16 @@ public class Root extends FObj implements CommonAccessibilityHolder {
      */
     private FOEventHandler foEventHandler;
 
+    private PageSequence lastSeq;
+
+    public void setLastSeq(PageSequence seq) {
+        lastSeq = seq;
+    }
+
+    public PageSequence getLastSeq() {
+          return lastSeq;
+    }
+
     /**
      * Base constructor
      *
index ed0c041ddb165478abb07cbff924f6ebad634f2a..2600909cb4b09a0f53c7db1e03d0fca2a0e814be 100644 (file)
@@ -100,6 +100,11 @@ public class SinglePageMasterReference extends FObj
         }
     }
 
+    public SimplePageMaster getLastPageMaster(boolean isOddPage, boolean isFirstPage, boolean isBlankPage,
+                                              BlockLevelEventProducer blockLevelEventProducer) {
+        return getNextPageMaster(isOddPage, isFirstPage, true, isBlankPage);
+    }
+
     /** {@inheritDoc} */
     public void reset() {
         this.state = FIRST;
index 271d80a9585f5ee41c813004218da6fd3b45b46f..0905ee8a81b085e76b3a70de589d1b08ffd0419f 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.fop.fo.pagination;
 
 import org.apache.fop.fo.ValidationException;
+import org.apache.fop.layoutmgr.BlockLevelEventProducer;
 
 /**
  * Classes that implement this interface can be added to a {@link PageSequenceMaster},
@@ -43,6 +44,10 @@ public interface SubSequenceSpecifier {
                                  boolean isBlankPage)
                                     throws PageProductionException;
 
+    SimplePageMaster getLastPageMaster(boolean isOddPage, boolean isFirstPage, boolean isBlankPage,
+                                       BlockLevelEventProducer blockLevelEventProducer)
+            throws PageProductionException;
+
     /**
      * Called before a new page sequence is rendered so subsequences can reset
      * any state they keep during the formatting process.
index e1c6b3a74ea363b0f5df6df8fbfef31ee4a3d9d9..d0594ce8a2289a01314ba8cbcd45240e658e3250 100644 (file)
@@ -42,6 +42,10 @@ public abstract class AbstractBreaker {
     /** logging instance */
     protected static final Log log = LogFactory.getLog(AbstractBreaker.class);
 
+    private LayoutManager originalRestartAtLM;
+    private Position positionAtBreak;
+    private List firstElementsForRestart;
+
     /**
      * A page break position.
      */
@@ -408,17 +412,36 @@ public abstract class AbstractBreaker {
                 alg.setConstantLineWidth(flowBPD);
                 int optimalPageCount = alg.findBreakingPoints(blockList, 1, true,
                         BreakingAlgorithm.ALL_BREAKS);
-
+                boolean ipdChangesOnNextPage = (alg.getIPDdifference() != 0);
+                boolean onLastPageAndIPDChanges = false;
+                if (!ipdChangesOnNextPage) {
+                    onLastPageAndIPDChanges = (lastPageHasIPDChange() && !thereIsANonRestartableLM(alg)
+                            && (shouldRedoLayout() || (wasLayoutRedone() && optimalPageCount > 1)));
+                }
                 if (alg.handlingFloat()) {
                     nextSequenceStartsOn = handleFloatLayout(alg, optimalPageCount, blockList, childLC);
-                } else if (Math.abs(alg.getIPDdifference()) > 1) {
-                    addAreas(alg, optimalPageCount, blockList, blockList);
-                    // *** redo Phase 1 ***
-                    log.trace("IPD changes after page " + optimalPageCount);
+                } else if (ipdChangesOnNextPage || onLastPageAndIPDChanges) {
+                    boolean visitedBefore = false;
+                    if (onLastPageAndIPDChanges) {
+                        visitedBefore = wasLayoutRedone();
+                        prepareToRedoLayout(alg, optimalPageCount, blockList, blockList);
+                    }
+
+                    firstElementsForRestart = null;
+                    LayoutManager restartAtLM = getRestartAtLM(alg, ipdChangesOnNextPage, onLastPageAndIPDChanges,
+                            visitedBefore, blockList, 1);
+                    if (restartAtLM == null) {
+                        firstElementsForRestart = null;
+                        restartAtLM = getRestartAtLM(alg, ipdChangesOnNextPage, onLastPageAndIPDChanges,
+                                visitedBefore, blockList, 0);
+                    }
+                    if (ipdChangesOnNextPage) {
+                        addAreas(alg, optimalPageCount, blockList, blockList);
+                    }
                     blockLists.clear();
-                    nextSequenceStartsOn = getNextBlockListChangedIPD(childLC, alg,
-                                                                      blockList);
                     blockListIndex = -1;
+                    nextSequenceStartsOn = getNextBlockList(childLC, Constants.EN_COLUMN, positionAtBreak,
+                            restartAtLM, firstElementsForRestart);
                 } else {
                     log.debug("PLM> optimalPageCount= " + optimalPageCount
                             + " pageBreaks.size()= " + alg.getPageBreaks().size());
@@ -433,6 +456,92 @@ public abstract class AbstractBreaker {
         blockLists = null;
     }
 
+    private LayoutManager getRestartAtLM(PageBreakingAlgorithm alg, boolean ipdChangesOnNextPage,
+                                         boolean onLastPageAndIPDChanges, boolean visitedBefore,
+                                         BlockSequence blockList, int start) {
+        KnuthNode optimalBreak = ipdChangesOnNextPage ? alg.getBestNodeBeforeIPDChange() : alg
+                .getBestNodeForLastPage();
+        if (onLastPageAndIPDChanges && visitedBefore && this.originalRestartAtLM == null) {
+            optimalBreak = null;
+        }
+
+        int positionIndex = (optimalBreak != null) ? optimalBreak.position : start;
+        KnuthElement elementAtBreak = alg.getElement(positionIndex);
+        if (elementAtBreak.getPosition() == null) {
+            elementAtBreak = alg.getElement(0);
+        }
+        positionAtBreak = elementAtBreak.getPosition();
+        /* Retrieve the original position wrapped into this space position */
+        positionAtBreak = positionAtBreak.getPosition();
+        if (ipdChangesOnNextPage || (positionAtBreak != null && positionAtBreak.getIndex() > -1)) {
+            firstElementsForRestart = Collections.EMPTY_LIST;
+            if (ipdChangesOnNextPage) {
+                if (containsNonRestartableLM(positionAtBreak)) {
+                    if (alg.getIPDdifference() > 0) {
+                        EventBroadcaster eventBroadcaster = getCurrentChildLM().getFObj()
+                                .getUserAgent().getEventBroadcaster();
+                        BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider
+                                .get(eventBroadcaster);
+                        eventProducer.nonRestartableContentFlowingToNarrowerPage(this);
+                    }
+                    firstElementsForRestart = new LinkedList();
+                    boolean boxFound = false;
+                    Iterator iter = blockList.listIterator(positionIndex + 1);
+                    Position position = null;
+                    while (iter.hasNext()
+                            && (position == null || containsNonRestartableLM(position))) {
+                        positionIndex++;
+                        KnuthElement element = (KnuthElement) iter.next();
+                        position = element.getPosition();
+                        if (element.isBox()) {
+                            boxFound = true;
+                            firstElementsForRestart.add(element);
+                        } else if (boxFound) {
+                            firstElementsForRestart.add(element);
+                        }
+                    }
+                    if (position instanceof SpaceResolver.SpaceHandlingBreakPosition) {
+                                    /* Retrieve the original position wrapped into this space position */
+                        positionAtBreak = position.getPosition();
+                    } else {
+                        positionAtBreak = null;
+                    }
+                }
+            }
+        }
+        LayoutManager restartAtLM = null;
+        if (ipdChangesOnNextPage || !(positionAtBreak != null && positionAtBreak.getIndex() > -1)) {
+            if (positionAtBreak != null && positionAtBreak.getIndex() == -1) {
+                Position position;
+                Iterator iter = blockList.listIterator(positionIndex + 1);
+                do {
+                    KnuthElement nextElement = (KnuthElement) iter.next();
+                    position = nextElement.getPosition();
+                } while (position == null
+                        || position instanceof SpaceResolver.SpaceHandlingPosition
+                        || position instanceof SpaceResolver.SpaceHandlingBreakPosition
+                        && position.getPosition().getIndex() == -1);
+                LayoutManager surroundingLM = positionAtBreak.getLM();
+                while (position.getLM() != surroundingLM) {
+                    position = position.getPosition();
+                }
+                restartAtLM = position.getPosition().getLM();
+            }
+            if (onLastPageAndIPDChanges && restartAtLM != null) {
+                if (originalRestartAtLM == null) {
+                    originalRestartAtLM = restartAtLM;
+                } else {
+                    restartAtLM = originalRestartAtLM;
+                }
+                firstElementsForRestart = Collections.EMPTY_LIST;
+            }
+        }
+        if (onLastPageAndIPDChanges && !visitedBefore && positionAtBreak.getPosition() != null) {
+            restartAtLM = positionAtBreak.getPosition().getLM();
+        }
+        return restartAtLM;
+    }
+
     /**
      * Returns {@code true} if the given position or one of its descendants
      * corresponds to a non-restartable LM.
@@ -709,84 +818,39 @@ public abstract class AbstractBreaker {
         return nextSequenceStartsOn;
     }
 
-    /**
-     * @param childLC LayoutContext to use
-     * @param alg the pagebreaking algorithm
-     * @param effectiveList the list of Knuth elements to be reused
-     * @return the page on which the next content should appear after a hard break
-     */
-    private int getNextBlockListChangedIPD(LayoutContext childLC, PageBreakingAlgorithm alg,
-                    BlockSequence effectiveList) {
-        int nextSequenceStartsOn;
-        KnuthNode optimalBreak = alg.getBestNodeBeforeIPDChange();
-        int positionIndex = optimalBreak.position;
-        log.trace("IPD changes at index " + positionIndex);
-        KnuthElement elementAtBreak = alg.getElement(positionIndex);
-        Position positionAtBreak = elementAtBreak.getPosition();
-        if (!(positionAtBreak instanceof SpaceResolver.SpaceHandlingBreakPosition)) {
-            throw new UnsupportedOperationException(
-                    "Don't know how to restart at position " + positionAtBreak);
-        }
-        /* Retrieve the original position wrapped into this space position */
-        positionAtBreak = positionAtBreak.getPosition();
-        LayoutManager restartAtLM = null;
-        List<KnuthElement> firstElements = Collections.emptyList();
-        if (containsNonRestartableLM(positionAtBreak)) {
-            if (alg.getIPDdifference() > 0) {
-                EventBroadcaster eventBroadcaster = getCurrentChildLM().getFObj()
-                        .getUserAgent().getEventBroadcaster();
-                BlockLevelEventProducer eventProducer
-                        = BlockLevelEventProducer.Provider.get(eventBroadcaster);
-                eventProducer.nonRestartableContentFlowingToNarrowerPage(this);
-            }
-            firstElements = new LinkedList<KnuthElement>();
-            boolean boxFound = false;
-            Iterator<KnuthElement> iter = effectiveList.listIterator(positionIndex + 1);
-            Position position = null;
-            while (iter.hasNext()
-                    && (position == null || containsNonRestartableLM(position))) {
-                positionIndex++;
-                KnuthElement element = iter.next();
-                position = element.getPosition();
-                if (element.isBox()) {
-                    boxFound = true;
-                    firstElements.add(element);
-                } else if (boxFound) {
-                    firstElements.add(element);
-                }
-            }
-            if (position instanceof SpaceResolver.SpaceHandlingBreakPosition) {
-                /* Retrieve the original position wrapped into this space position */
-                positionAtBreak = position.getPosition();
-            } else {
-                positionAtBreak = null;
+    protected boolean shouldRedoLayout() {
+        return false;
+    }
+
+    protected void prepareToRedoLayout(PageBreakingAlgorithm alg, int partCount,
+            BlockSequence originalList, BlockSequence effectiveList) {
+        return;
+    }
+
+    protected boolean wasLayoutRedone() {
+        return false;
+    }
+
+    private boolean thereIsANonRestartableLM(PageBreakingAlgorithm alg) {
+        KnuthNode optimalBreak = alg.getBestNodeForLastPage();
+        if (optimalBreak != null) {
+            int positionIndex = optimalBreak.position;
+            KnuthElement elementAtBreak = alg.getElement(positionIndex);
+            Position positionAtBreak = elementAtBreak.getPosition();
+            if (!(positionAtBreak instanceof SpaceResolver.SpaceHandlingBreakPosition)) {
+                return false;
             }
-        }
-        if (positionAtBreak != null && positionAtBreak.getIndex() == -1) {
-            /*
-             * This is an indication that we are between two blocks
-             * (possibly surrounded by another block), not inside a
-             * paragraph.
-             */
-            Position position;
-            Iterator<KnuthElement> iter = effectiveList.listIterator(positionIndex + 1);
-            do {
-                KnuthElement nextElement = iter.next();
-                position = nextElement.getPosition();
-            } while (position == null
-                    || position instanceof SpaceResolver.SpaceHandlingPosition
-                    || position instanceof SpaceResolver.SpaceHandlingBreakPosition
-                        && position.getPosition().getIndex() == -1);
-            LayoutManager surroundingLM = positionAtBreak.getLM();
-            while (position.getLM() != surroundingLM) {
-                position = position.getPosition();
+            /* Retrieve the original position wrapped into this space position */
+            positionAtBreak = positionAtBreak.getPosition();
+            if (positionAtBreak != null && containsNonRestartableLM(positionAtBreak)) {
+                return true;
             }
-            restartAtLM = position.getPosition().getLM();
         }
+        return false;
+    }
 
-        nextSequenceStartsOn = getNextBlockList(childLC, Constants.EN_COLUMN,
-                positionAtBreak, restartAtLM, firstElements);
-        return nextSequenceStartsOn;
+    protected boolean lastPageHasIPDChange() {
+        return false;
     }
 
     protected int handleFloatLayout(PageBreakingAlgorithm alg, int optimalPageCount, BlockSequence blockList,
index 7faa0565ecb7828413f663840c9530de801c3ec0..8435ad0938fc801152a7ec9c5a0b0a9d1685e5fe 100644 (file)
@@ -383,6 +383,11 @@ public abstract class AbstractPageSequenceLayoutManager extends AbstractLayoutMa
         if (curPage != null) {
             finishPage();
         }
+
+        while (forcePageCount != Constants.EN_NO_FORCE && getCurrentPageNum() < getLastPageNumber()) {
+            curPage = makeNewPage(true);
+            finishPage();
+        }
     }
 
     /** {@inheritDoc} */
@@ -390,4 +395,7 @@ public abstract class AbstractPageSequenceLayoutManager extends AbstractLayoutMa
         throw new IllegalStateException();
     }
 
+    protected int getLastPageNumber() {
+        return currentPageNum;
+    }
 }
index 6a407f266604b3c5d288c9c48d13f2111a5e489f..d043456be075bb87e195cf77aa7a8c7cf9a35993 100644 (file)
@@ -202,4 +202,21 @@ public interface BlockLevelEventProducer extends EventProducer {
      * @event.severity WARN
      */
     void nonRestartableContentFlowingToNarrowerPage(Object source);
+
+    /**
+     * A feasible layout has reached the given number of parts (columns or pages).
+     *
+     * @param source the event source
+     * @param partCount the number of parts that the layout has reached
+     * @event.severity INFO
+     */
+    void layoutHasReachedParts(Object source, int partCount);
+
+    /**
+     * Last page master reference missing.
+     *
+     * @param source the event source
+     * @event.severity WARN
+     */
+    void lastPageMasterReferenceMissing(Object source, Locator loc);
 }
index 6eb772db13a5319153378ccabd031cd84a4812c9..de040bdfe8dd5f41f1a7f288c88a510cce16aec0 100644 (file)
@@ -31,4 +31,6 @@
   <message key="missingSubsequencesInPageSequenceMaster">No subsequences in page-sequence-master "{pageSequenceMasterName}".{{locator}}</message>
   <message key="noMatchingPageMaster">No simple-page-master matching "{pageMasterName}" in page-sequence-master "{pageSequenceMasterName}".{{locator}}</message>
   <message key="nonRestartableContentFlowingToNarrowerPage">Content that cannot handle IPD changes is flowing to a narrower page. Part of it may be clipped by the page border.</message>
+  <message key="layoutHasReachedParts">A layout has reached {partCount} part(s).</message>
+  <message key="lastPageMasterReferenceMissing">page-position="last" master reference missing.{{locator}}</message>
 </catalogue>
index ba676ab897c7f5b90cc61f3029dd9d3f3d0fd7f7..8cc9db7907e8924df457cd7bbf8b6055d1e01ece 100644 (file)
@@ -51,6 +51,8 @@ public class PageBreaker extends AbstractBreaker {
     private PageProvider pageProvider;
     private Block separatorArea;
     private boolean spanAllActive;
+    private boolean layoutRedone;
+    private int previousIndex;
     private boolean handlingStartOfFloat;
     private boolean handlingEndOfFloat;
     private int floatHeight;
@@ -161,7 +163,7 @@ public class PageBreaker extends AbstractBreaker {
     /** {@inheritDoc} */
     protected int getNextBlockList(LayoutContext childLC, int nextSequenceStartsOn,
             Position positionAtIPDChange, LayoutManager restartLM, List firstElements) {
-        if (!handlingFloat()) {
+        if (!layoutRedone && !handlingFloat()) {
             if (!firstPart) {
                 // if this is the first page that will be created by
                 // the current BlockSequence, it could have a break
@@ -330,21 +332,55 @@ public class PageBreaker extends AbstractBreaker {
             return;
         }
 
-        boolean lastPageMasterDefined = pslm.getPageSequence().hasPagePositionLast()
-                || pslm.getPageSequence().hasPagePositionOnly() && pslm.isOnFirstPage(partCount - 1);
-        if (!hasMoreContent()) {
-            //last part is reached
-            if (lastPageMasterDefined) {
-                //last-page condition
-                redoLayout(alg, partCount, originalList, effectiveList);
-                return;
-            }
+        if (shouldRedoLayout(partCount)) {
+            redoLayout(alg, partCount, originalList, effectiveList);
+            return;
         }
 
         //nothing special: just add the areas now
         addAreas(alg, partCount, originalList, effectiveList);
     }
 
+    protected void prepareToRedoLayout(PageBreakingAlgorithm alg, int partCount,
+            BlockSequence originalList,
+            BlockSequence effectiveList) {
+        int newStartPos = 0;
+        int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
+        if (restartPoint > 0 && !layoutRedone) {
+            // Add definitive areas for the parts before the
+            // restarting point
+            addAreas(alg, restartPoint, originalList, effectiveList);
+            // Get page break from which we restart
+            PageBreakPosition pbp = alg.getPageBreaks().get(restartPoint - 1);
+            newStartPos = alg.par.getFirstBoxIndex(pbp.getLeafPos() + 1);
+            // Handle page break right here to avoid any side-effects
+            if (newStartPos > 0) {
+                handleBreakTrait(Constants.EN_PAGE);
+            }
+        }
+        pageBreakHandled = true;
+        // Update so the available BPD is reported correctly
+        int currentPageNum = pslm.getCurrentPageNum();
+        int currentColumn = pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex();
+        pageProvider.setStartOfNextElementList(currentPageNum, currentColumn, spanAllActive);
+
+        // Make sure we only add the areas we haven't added already
+        effectiveList.ignoreAtStart = newStartPos;
+        if (!layoutRedone) {
+            // Handle special page-master for last page
+            setLastPageIndex(currentPageNum);
+//          BodyRegion lastBody = pageProvider.getPage(false, currentPageNum).getPageViewport().getBodyRegion();
+            pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
+            previousIndex = pageProvider.getIndexOfCachedLastPage();
+        } else {
+            setLastPageIndex(currentPageNum + 1);
+//            pslm.setCurrentPage(previousPage);
+            pageProvider.discardCacheStartingWith(previousIndex);
+            pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
+        }
+        layoutRedone = true;
+    }
+
     /**
      * Restart the algorithm at the break corresponding to the given partCount. Used to
      * re-do the part after the last break in case of either column-balancing or a last
@@ -565,6 +601,7 @@ public class PageBreaker extends AbstractBreaker {
             return;
         case Constants.EN_COLUMN:
         case Constants.EN_AUTO:
+        case Constants.EN_PAGE:
         case -1:
             PageViewport pv = curPage.getPageViewport();
 
@@ -580,26 +617,35 @@ public class PageBreaker extends AbstractBreaker {
                 log.trace("Forcing new page with span");
                 curPage = pslm.makeNewPage(false);
                 curPage.getPageViewport().createSpan(true);
-            } else if (pv.getCurrentSpan().hasMoreFlows()) {
-                log.trace("Moving to next flow");
-                pv.getCurrentSpan().moveToNextFlow();
             } else {
-                log.trace("Making new page");
-                /*curPage = */pslm.makeNewPage(false);
+                if (breakVal == Constants.EN_PAGE) {
+                    handleBreakBeforeFollowingPage(breakVal);
+                } else {
+                    if (pv.getCurrentSpan().hasMoreFlows()) {
+                        log.trace("Moving to next flow");
+                        pv.getCurrentSpan().moveToNextFlow();
+                    } else {
+                        log.trace("Making new page");
+                        pslm.makeNewPage(false);
+                    }
+                }
             }
             return;
-        case Constants.EN_PAGE:
         default:
-            log.debug("handling break-before after page " + pslm.getCurrentPageNum()
-                + " breakVal=" + getBreakClassName(breakVal));
-            if (needBlankPageBeforeNew(breakVal)) {
-                log.trace("Inserting blank page");
-                /*curPage = */pslm.makeNewPage(true);
-            }
-            if (needNewPage(breakVal)) {
-                log.trace("Making new page");
-                /*curPage = */pslm.makeNewPage(false);
-            }
+            handleBreakBeforeFollowingPage(breakVal);
+        }
+    }
+
+    private void handleBreakBeforeFollowingPage(int breakVal) {
+        log.debug("handling break-before after page " + pslm.getCurrentPageNum() + " breakVal="
+                + getBreakClassName(breakVal));
+        if (needBlankPageBeforeNew(breakVal)) {
+            log.trace("Inserting blank page");
+            /* curPage = */pslm.makeNewPage(true);
+        }
+        if (needNewPage(breakVal)) {
+            log.trace("Making new page");
+            /* curPage = */pslm.makeNewPage(false);
         }
     }
 
@@ -641,6 +687,36 @@ public class PageBreaker extends AbstractBreaker {
         }
     }
 
+    protected boolean shouldRedoLayout() {
+        return shouldRedoLayout(-1);
+    }
+
+    protected boolean shouldRedoLayout(int partCount) {
+        boolean lastPageMasterDefined = pslm.getPageSequence().hasPagePositionLast();
+        if (!lastPageMasterDefined && partCount != -1) {
+            lastPageMasterDefined = pslm.getPageSequence().hasPagePositionOnly() && pslm.isOnFirstPage(partCount - 1);
+        }
+        return (!hasMoreContent() && lastPageMasterDefined && !layoutRedone);
+    }
+
+    protected boolean wasLayoutRedone() {
+        return layoutRedone;
+    }
+
+    protected boolean lastPageHasIPDChange() {
+        boolean lastPageMasterDefined = pslm.getPageSequence().hasPagePositionLast();
+        boolean onlyPageMasterDefined = pslm.getPageSequence().hasPagePositionOnly();
+        if (lastPageMasterDefined && !onlyPageMasterDefined) {
+            // code not very robust and unable to handle situations were only and last are defined
+            int currentIPD = this.pageProvider.getCurrentIPD();
+            int lastPageIPD = this.pageProvider.getLastPageIPD();
+            if (lastPageIPD != -1 && currentIPD != lastPageIPD) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     protected boolean handlingStartOfFloat() {
         return handlingStartOfFloat;
     }
index 9327f8f8cd5e699a9a9a52ba7f9282bf05e899e0..b72124c772484fab90732440e029ceaa122202e5 100644 (file)
@@ -95,6 +95,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
 
     private int ipdDifference;
     private KnuthNode bestNodeForIPDChange;
+    public KnuthNode bestNodeForLastPage;
 
     //Used to keep track of switches in keep-context
     private int currentKeepContext = Constants.EN_AUTO;
@@ -1258,6 +1259,9 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
                  * the IPD change. No need to do any special handling.
                  */
                 ipdDifference = 0;
+            } else if (line > 0 /*&& (bestNodeForLastPage == null
+                     || node.totalDemerits < bestNodeForLastPage.totalDemerits)*/) {
+                bestNodeForLastPage = node;
             }
             super.addNode(line, node);
         }
@@ -1274,6 +1278,10 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
         return pageProvider.compareIPDs(line);
     }
 
+    KnuthNode getBestNodeForLastPage() {
+        return bestNodeForLastPage;
+    }
+
     protected boolean handlingFloat() {
         return (handlingStartOfFloat || handlingEndOfFloat);
     }
index 142f7ad7287c295508e307a7b7344b1a48b71221..ca41c8c1e34d3fd4565d35bef077615191724a51 100644 (file)
@@ -201,8 +201,8 @@ public class PageProvider implements Constants {
             return 0;
         } else {
             Page nextPage = getPage(false, column.pageIndex + 1, RELTO_CURRENT_ELEMENT_LIST);
-            return column.page.getPageViewport().getBodyRegion().getIPD()
-                    - nextPage.getPageViewport().getBodyRegion().getIPD();
+            return column.page.getPageViewport().getBodyRegion().getColumnIPD()
+                    - nextPage.getPageViewport().getBodyRegion().getColumnIPD();
         }
     }
 
@@ -332,7 +332,7 @@ public class PageProvider implements Constants {
         return page;
     }
 
-    private void discardCacheStartingWith(int index) {
+    protected void discardCacheStartingWith(int index) {
         while (index < cachedPages.size()) {
             this.cachedPages.remove(cachedPages.size() - 1);
             if (!pageSeq.goToPreviousSimplePageMaster()) {
@@ -352,9 +352,38 @@ public class PageProvider implements Constants {
         page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
         page.getPageViewport().setWritingModeTraits(pageSeq);
         cachedPages.add(page);
+        if (isLastPage) {
+            pageSeq.getRoot().setLastSeq(pageSeq);
+        } else if (!isFirstPage) {
+            pageSeq.getRoot().setLastSeq(null);
+        }
         return page;
     }
 
+    public int getIndexOfCachedLastPage() {
+        return indexOfCachedLastPage;
+    }
+
+    public int getLastPageIndex() {
+        return lastPageIndex;
+    }
+
+    public int getLastPageIPD() {
+        int index = this.cachedPages.size();
+        boolean isFirstPage = (startPageOfPageSequence == index);
+        SimplePageMaster spm = pageSeq.getLastSimplePageMaster(index, isFirstPage, false);
+        Page page = new Page(spm, index, "", false, false);
+        if (pageSeq.getRoot().getLastSeq() != null && pageSeq.getRoot().getLastSeq() != pageSeq) {
+            return -1;
+        }
+        return page.getPageViewport().getBodyRegion().getColumnIPD();
+    }
+
+    public int getCurrentIPD() {
+        return getPageFromColumnIndex(startColumnOfCurrentElementList).getPageViewport().getBodyRegion()
+                .getColumnIPD();
+    }
+
     /**
      * Indicates whether the column/page at the given index is on the first page of the page sequence.
      *
index 2e2bd0a229a9b117a6a87b3c1b98a207ed3f7b4b..0ee7121aff0b34944b75fb72c8ef100d37e48b6f 100644 (file)
@@ -254,6 +254,16 @@ public class PageSequenceLayoutManager extends AbstractPageSequenceLayoutManager
         return pageProvider.isOnFirstPage(partIndex);
     }
 
+    protected int getLastPageNumber() {
+        return pageProvider.getLastPageIndex();
+    }
+
+    protected int getWidthOfCurrentPage() {
+        if (curPage != null) {
+            return (int) curPage.getPageViewport().getViewArea().getWidth();
+        }
+        return 0;
+    }
     /**
      * Registers the given footnotes so that they can be added to the current page, before any other footnote.
      *
index 457cfaef3afbad274e586105f65858d1bb55196f..e6dc5b22d6696a1c2d4dcd6fc39077c1de055004 100644 (file)
@@ -124,4 +124,8 @@ class TableContentPosition extends Position {
         sb.append(")");
         return sb.toString();
     }
+
+    public Position getPosition() {
+        return this;
+    }
 }
index df99c7cdeb26c9a617d6c46e15d050b5c1f13164..892e85fcf5387439b2184f74b425c889e241aa0c 100644 (file)
@@ -74,7 +74,7 @@
     <checks>
         <eval expected="(P2,par2)" xpath="((/areaTree/pageSequence/pageViewport)[4]//inlineparent[@internal-link])[1]/@internal-link"/>
         <eval expected="(P3,par3)" xpath="((/areaTree/pageSequence/pageViewport)[4]//inlineparent[@internal-link])[2]/@internal-link"/>
-        <eval expected="(P5,title)" xpath="/areaTree/bookmarkTree/bookmark/@internal-link"/>
+        <eval expected="(P6,title)" xpath="/areaTree/bookmarkTree/bookmark/@internal-link"/>
         <eval expected="4" xpath="count(/areaTree/pageSequence/pageViewport)"/>
     </checks>
 </testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_columns.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_columns.xml
new file mode 100644 (file)
index 0000000..ab6321a
--- /dev/null
@@ -0,0 +1,69 @@
+<?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>
+      Check that an IPD change is detected when switching from single column to multi-column layout.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="page1"
+          page-height="120pt" page-width="320pt" margin="10pt">
+          <fo:region-body/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="page2"
+          page-height="120pt" page-width="320pt" margin="10pt">
+          <fo:region-body column-count="2" column-gap="20pt"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="page"
+          page-height="120pt" page-width="320pt" margin="10pt">
+          <fo:region-body/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:single-page-master-reference master-reference="page1"/>
+          <fo:single-page-master-reference master-reference="page2"/>
+          <fo:repeatable-page-master-reference master-reference="page"/>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages">
+        <fo:flow flow-name="xsl-region-body" text-align="justify">
+          <fo:block>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 
+            tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et 
+            accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus 
+            est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed 
+            diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam 
+            voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd 
+            gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit 
+            amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et 
+            dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores 
+            et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit 
+            amet.</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="300000" xpath="//pageViewport[1]//flow/block/@ipd"/>
+    <eval expected="140000" xpath="//pageViewport[2]//flow[1]/block/@ipd"/>
+    <eval expected="140000" xpath="//pageViewport[2]//flow[2]/block/@ipd"/>
+    <eval expected="300000" xpath="//pageViewport[3]//flow/block/@ipd"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_1.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_1.xml
new file mode 100644 (file)
index 0000000..5024cd2
--- /dev/null
@@ -0,0 +1,58 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="Page-Portrait" page-width="8.5in" page-height="11in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master master-name="Page_Landscape" page-width="11in" page-height="8.5in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" 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="Page-Portrait"/>
+        <fo:conditional-page-master-reference master-reference="Page_Landscape" page-position="rest"/>
+        <fo:conditional-page-master-reference master-reference="Page-Portrait" page-position="last"/>
+      </fo:repeatable-page-master-alternatives>
+    </fo:page-sequence-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="LetterPages">
+    <fo:flow flow-name="letterPageBody">
+        <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. </fo:block>
+        <fo:block break-before="page"/>
+        <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. </fo:block>
+        <fo:block break-before="page"/>
+        <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. </fo:block>
+        <fo:block>Check this works!</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <eval expected="is just some generic text to use for testing. This is just some generic text to use for testing. This is just"  xpath="//pageViewport[3]//flow/block[1]/lineArea[2]//text"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_2.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_2.xml
new file mode 100644 (file)
index 0000000..c636d39
--- /dev/null
@@ -0,0 +1,54 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="Page-Portrait" page-width="3in" page-height="4.5in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master master-name="Page_Landscape" page-width="4.5in" page-height="3in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" 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="Page-Portrait"/>
+        <fo:conditional-page-master-reference master-reference="Page_Landscape" page-position="rest"/>
+        <fo:conditional-page-master-reference master-reference="Page-Portrait" page-position="last"/>
+      </fo:repeatable-page-master-alternatives>
+    </fo:page-sequence-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="LetterPages">
+    <fo:flow flow-name="letterPageBody">
+        <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. </fo:block>
+        <fo:block>Check this works!</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <eval expected="is just some generic text"  xpath="//pageViewport[3]//flow/block[1]/lineArea[2]//text"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_3.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_3.xml
new file mode 100644 (file)
index 0000000..b683d32
--- /dev/null
@@ -0,0 +1,55 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="Page-Portrait" page-width="3in" page-height="4.5in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master master-name="Page_Landscape" page-width="4.5in" page-height="3in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" 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="Page-Portrait"/>
+        <fo:conditional-page-master-reference master-reference="Page_Landscape" page-position="rest"/>
+        <fo:conditional-page-master-reference master-reference="Page-Portrait" page-position="last"/>
+      </fo:repeatable-page-master-alternatives>
+    </fo:page-sequence-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="LetterPages">
+    <fo:flow flow-name="letterPageBody">
+        <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing.</fo:block>
+        <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing.</fo:block>
+        <fo:block>Check this works!</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <eval expected="text to use for testing. This"  xpath="//pageViewport[3]//flow/block[1]/lineArea[2]//text"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_4.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_4.xml
new file mode 100644 (file)
index 0000000..ab209a1
--- /dev/null
@@ -0,0 +1,56 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="Page-First" page-width="3.5in" page-height="3.5in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body background-color="yellow" margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master master-name="Page-Rest" page-width="3.5in" page-height="3.5in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body background-color="orange" margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master master-name="Page-Last" page-width="4.0in" page-height="3.5in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body background-color="pink" margin-bottom="1.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" 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="Page-First"/>
+        <fo:conditional-page-master-reference master-reference="Page-Rest" page-position="rest"/>
+        <fo:conditional-page-master-reference master-reference="Page-Last" page-position="last"/>
+      </fo:repeatable-page-master-alternatives>
+    </fo:page-sequence-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="LetterPages">
+    <fo:flow flow-name="letterPageBody">
+        <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <eval expected="testing. This is just some generic text to"  xpath="//pageViewport[3]//flow/block[1]/lineArea[2]//text"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_5.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_5.xml
new file mode 100644 (file)
index 0000000..1deb24a
--- /dev/null
@@ -0,0 +1,99 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" xmlns:svg="http://www.w3.org/2000/svg" xmlns:th="http://www.thunderhead.com/XSL/Extensions" xmlns:rx="http://www.renderx.com/XSL/Extensions" xmlns:ps="http://xmlgraphics.apache.org/fop/postscript">
+      <fo:layout-master-set>
+        <fo:simple-page-master margin-left="0mm" master-name="PageOneFront" page-width="210mm" page-height="297mm" margin-bottom="6mm" margin-right="10mm" margin-top="0mm">
+
+          <fo:region-body margin-right="60mm" margin-left="25mm" margin-bottom="15mm" margin-top="44mm" region-name="letterPageBody"/>
+
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="PageRest" page-width="210mm" page-height="297mm" margin-bottom="6mm" margin-right="25mm" margin-top="0mm" margin-left="25mm">
+          <fo:region-body margin-top="44mm" margin-bottom="15mm" margin-right="0mm" margin-left="0mm" 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="PageOneFront"/>
+            <fo:conditional-page-master-reference page-position="rest" master-reference="PageRest"/>
+            <fo:conditional-page-master-reference blank-or-not-blank="not-blank" page-position="last" master-reference="PageRest"/>
+            <fo:conditional-page-master-reference blank-or-not-blank="blank" 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_sequence1" initial-page-number="auto" force-page-count="auto" master-reference="LetterPages">
+
+        <fo:flow flow-name="letterPageBody">
+          <fo:block-container min-height="50mm">
+            <fo:block>
+
+            </fo:block>
+          </fo:block-container>
+        </fo:flow>
+      </fo:page-sequence>
+      <fo:page-sequence format="1" id="th_default_sequence2" initial-page-number="auto" force-page-count="auto" master-reference="LetterPages">
+
+        <fo:flow flow-name="letterPageBody">
+          <fo:block-container min-height="50mm">
+            <fo:block>
+              <fo:table table-layout="fixed" width="100%">
+                <fo:table-column column-width="98%" column-number="1"/>
+                <fo:table-column column-width="1%" column-number="2"/>
+                <fo:table-column column-width="1%" column-number="3"/>
+                <fo:table-body>
+                  <fo:table-row height="10mm">
+                    <fo:table-cell number-columns-spanned="3">
+                      <fo:block>test</fo:block>
+                    </fo:table-cell>
+                  </fo:table-row>
+                  <fo:table-row height="29.5mm">
+                    <fo:table-cell column-number="1">
+                      <fo:block/>
+                    </fo:table-cell>
+                    <fo:table-cell column-number="2">
+                      <fo:block/>
+                    </fo:table-cell>
+                    <fo:table-cell column-number="3">
+                      <fo:block/>
+                    </fo:table-cell>
+                  </fo:table-row>
+                </fo:table-body>
+              </fo:table>
+            </fo:block>
+          </fo:block-container>
+
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="test" xpath="//word"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_6.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_6.xml
new file mode 100644 (file)
index 0000000..bcd6c30
--- /dev/null
@@ -0,0 +1,64 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" xmlns:svg="http://www.w3.org/2000/svg" xmlns:th="http://www.thunderhead.com/XSL/Extensions" xmlns:rx="http://www.renderx.com/XSL/Extensions">
+  <fo:layout-master-set>
+    <fo:simple-page-master margin-right="10mm" margin-left="0mm" margin-bottom="6mm" master-name="PageFront" page-width="210mm" page-height="297mm" margin-top="0mm">
+      <fo:region-body background-color="blue" margin-right="60mm" margin-left="25mm" margin-top="44mm" margin-bottom="15mm" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master margin-right="25mm" margin-left="25mm" margin-bottom="6mm" master-name="PageRest" page-width="210mm" page-height="297mm" margin-top="0mm">
+      <fo:region-body background-color="red" margin-top="44mm" margin-bottom="15mm" margin-right="0mm" margin-left="0mm" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master margin-right="25mm" margin-left="25mm" margin-bottom="6mm" master-name="PageLast" page-width="210mm" page-height="297mm" margin-top="0mm">
+      <fo:region-body background-color="green" margin-top="44mm" margin-bottom="15mm" margin-right="0mm" margin-left="0mm" 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 blank-or-not-blank="not-blank" page-position="rest" master-reference="PageRest"/>
+        <fo:conditional-page-master-reference blank-or-not-blank="not-blank" 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" initial-page-number="auto" force-page-count="auto" master-reference="LetterPages">   
+    <fo:flow flow-name="letterPageBody">      
+        <fo:block>page 1</fo:block>        
+    </fo:flow>
+  </fo:page-sequence>
+  <fo:page-sequence format="1" id="th_default_sequence2" initial-page-number="auto" force-page-count="auto" master-reference="LetterPages">
+    <fo:flow flow-name="letterPageBody">
+        <fo:block>page 2</fo:block>
+        <fo:block break-before="page">page 3</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  
+  </fo>
+  <checks>
+    <eval expected="color=#008000" xpath="/areaTree/pageSequence[2]/pageViewport[2]/page/regionViewport[1]/@background"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_7.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_7.xml
new file mode 100644 (file)
index 0000000..4e5f048
--- /dev/null
@@ -0,0 +1,154 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+      <fo:layout-master-set>
+        <fo:simple-page-master margin-left="0mm" margin-right="10mm" margin-bottom="6mm" master-name="PageFront" page-width="210mm" page-height="297mm" margin-top="0mm">
+          <fo:region-body margin-right="60mm" margin-left="25mm" margin-top="44mm" margin-bottom="15mm" region-name="letterPageBody"/>
+
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="PageRest" page-width="210mm" page-height="297mm" margin-bottom="6mm" margin-right="25mm" margin-top="0mm" margin-left="25mm">
+          <fo:region-body margin-top="44mm" margin-bottom="15mm" margin-right="0mm" margin-left="0mm" region-name="letterPageBody"/>
+
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="PageFrontLogoRight" margin-right="10mm" margin-left="25mm" margin-bottom="6mm" page-width="210mm" page-height="297mm" margin-top="0mm">
+          <fo:region-body margin-right="60mm" margin-top="44mm" margin-left="0" margin-bottom="15mm" region-name="letterPageBody"/>
+
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="PageFrontRestMediaType" margin-left="0mm" margin-right="10mm" margin-bottom="6mm" page-width="210mm" page-height="297mm" margin-top="0mm">
+          <fo:region-body margin-right="60mm" margin-top="44mm" margin-left="25mm" margin-bottom="15mm" 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:page-sequence-master master-name="LetterPagesMYLocal">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference master-reference="PageFrontRestMediaType" page-position="first"/>
+            <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_sequence1" initial-page-number="auto" force-page-count="auto" master-reference="LetterPages">
+
+        <fo:flow flow-name="letterPageBody">
+          <fo:block>
+
+            <fo:block page-break-after="always">
+              <fo:leader/>
+            </fo:block>
+
+            <fo:block>
+          test
+        </fo:block>
+
+          </fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+      <fo:page-sequence format="1" id="th_default_sequence4" master-reference="LetterPagesMYLocal" initial-page-number="auto" force-page-count="auto">
+
+        <fo:flow flow-name="letterPageBody">
+
+          <fo:block>
+
+            <fo:block page-break-after="always">
+              <fo:leader/>
+            </fo:block>
+            <fo:block page-break-after="always">
+              <fo:leader/>
+            </fo:block>
+            <fo:table table-layout="fixed" width="100%">
+              <fo:table-column column-width="proportional-column-width(100)" column-number="1"/>
+              <fo:table-body>
+                <fo:table-row>
+                  <fo:table-cell>
+                    <fo:block>
+                      <fo:table table-layout="fixed" width="100%">
+                        <fo:table-column column-width="proportional-column-width(1)" column-number="1"/>
+                        <fo:table-column column-width="proportional-column-width(28.49)" column-number="2"/>
+                        <fo:table-column column-width="proportional-column-width(21.55)" column-number="3"/>
+                        <fo:table-column column-width="proportional-column-width(47.96)" column-number="4"/>
+                        <fo:table-column column-width="proportional-column-width(1)" column-number="5"/>
+                        <fo:table-body>
+                          <fo:table-row height="16px">
+                            <fo:table-cell>
+                              <fo:block>
+                                <fo:block>
+                                  <fo:leader/>
+                                </fo:block>
+                              </fo:block>
+                            </fo:table-cell>
+                            <fo:table-cell number-columns-spanned="3">
+                              <fo:block>
+                            test
+                          </fo:block>
+                            </fo:table-cell>
+                            <fo:table-cell>
+                              <fo:block>
+                                <fo:block>
+                                  <fo:leader/>
+                                </fo:block>
+                              </fo:block>
+                            </fo:table-cell>
+                          </fo:table-row>
+                          <fo:table-row>
+                            <fo:table-cell>
+                              <fo:block>
+                                <fo:block>
+                                  <fo:leader/>
+                                </fo:block>
+                              </fo:block>
+                            </fo:table-cell>
+
+                          </fo:table-row>
+
+
+                        </fo:table-body>
+                      </fo:table>
+
+                    </fo:block>
+                  </fo:table-cell>
+                </fo:table-row>
+              </fo:table-body>
+            </fo:table>
+          </fo:block>
+
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+
+  </fo>
+  <checks>
+    <eval expected="test" xpath="//word"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_8.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_8.xml
new file mode 100644 (file)
index 0000000..53c83e8
--- /dev/null
@@ -0,0 +1,70 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="Page-Portrait" page-width="8.5in" page-height="11in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master master-name="Page_Landscape" page-width="11in" page-height="8.5in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" 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="Page-Portrait"/>
+        <fo:conditional-page-master-reference master-reference="Page_Landscape" page-position="rest"/>
+        <fo:conditional-page-master-reference master-reference="Page-Portrait" page-position="last"/>
+      </fo:repeatable-page-master-alternatives>
+    </fo:page-sequence-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="LetterPages">
+    <fo:flow flow-name="letterPageBody">
+      <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. </fo:block>
+      <fo:block break-before="page"/>
+      <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. </fo:block>
+      <fo:block break-before="page"/>
+      <fo:table>
+        <fo:table-body>
+          <fo:table-row>
+            <fo:table-cell>
+              <fo:block></fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell>
+              <fo:block>A table with first row empty after change in IPD and forced break before page...</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <eval expected="A table with first row empty after change in IPD and forced break before page..." xpath="//pageViewport[3]//lineArea"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_9.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_last-page_9.xml
new file mode 100644 (file)
index 0000000..2517aaa
--- /dev/null
@@ -0,0 +1,70 @@
+<?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 the definition of a special page-master for the last page with a
+      different width that the previous "rest" page causes FOP to redo the line breaking layout.
+    </p>
+  </info>
+  <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="Page-Portrait" page-width="8.5in" page-height="11in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" region-name="letterPageBody"/>
+    </fo:simple-page-master>
+    <fo:simple-page-master master-name="Page_Landscape" page-width="11in" page-height="8.5in" margin-bottom="0in" margin-right="0in" margin-top="0in" margin-left="0in">
+      <fo:region-body margin-bottom="0.5in" margin-right="0.5in" margin-top="0.5in" margin-left="0.5in" 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="Page-Portrait"/>
+        <fo:conditional-page-master-reference master-reference="Page_Landscape" page-position="rest"/>
+        <fo:conditional-page-master-reference master-reference="Page-Portrait" page-position="last"/>
+      </fo:repeatable-page-master-alternatives>
+    </fo:page-sequence-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="LetterPages">
+    <fo:flow flow-name="letterPageBody">
+      <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. </fo:block>
+      <fo:block break-before="page"/>
+      <fo:block>This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. This is just some generic text to use for testing. </fo:block>
+      <fo:block break-after="page"/>
+      <fo:table>
+        <fo:table-body>
+          <fo:table-row>
+            <fo:table-cell>
+              <fo:block></fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell>
+              <fo:block>A table with first row empty after change in IPD and forced break after page...</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
+  </fo>
+  <checks>
+    <eval expected="A table with first row empty after change in IPD and forced break after page..." xpath="//pageViewport[3]//lineArea"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/flow_changing-ipd_no-last-page.xml b/test/layoutengine/standard-testcases/flow_changing-ipd_no-last-page.xml
new file mode 100644 (file)
index 0000000..bf94413
--- /dev/null
@@ -0,0 +1,81 @@
+<?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 the definition of a special page-master for the last page does not 
+      interfere with the changing IPD code.
+    </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-right="0mm" margin-top="4mm" margin-left="7mm" margin-bottom="8mm" master-name="PageFront" page-width="210mm" page-height="297mm">
+          <fo:region-body margin-right="20mm" region-name="letterPageBody" margin-top="46mm" margin-left="26mm" margin-bottom="10mm"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master margin-right="0mm" margin-top="4mm" margin-left="7mm" master-name="PageRest" page-width="210mm" page-height="297mm" margin-bottom="8mm">
+          <fo:region-body margin-right="20mm" margin-top="35mm" margin-left="13mm" region-name="letterPageBody" margin-bottom="10mm"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master margin-right="0mm" master-name="PageBlank" margin-top="4mm" margin-left="7mm" page-width="210mm" page-height="297mm" margin-bottom="8mm">
+          <fo:region-body margin-right="20mm" margin-top="38mm" margin-bottom="12mm" margin-left="26mm" 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 blank-or-not-blank="not-blank" odd-or-even="even" page-position="last" master-reference="PageRest"/>
+            <fo:conditional-page-master-reference blank-or-not-blank="blank" odd-or-even="even" page-position="last" master-reference="PageBlank"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence format="1" id="th_default_sequence1" initial-page-number="auto" force-page-count="end-on-even" master-reference="LetterPages">
+
+        <fo:flow flow-name="letterPageBody">
+          <fo:block>
+            <fo:table table-layout="fixed">
+              <fo:table-body>
+                <fo:table-row height="30mm">
+                  <fo:table-cell width="157mm">
+                    <fo:block/>
+                  </fo:table-cell>
+                </fo:table-row>
+                <fo:table-row height="199mm" display-align="after">
+                  <fo:table-cell width="157mm">
+                    <fo:block margin-bottom="0mm"/>
+                  </fo:table-cell>
+                </fo:table-row>
+              </fo:table-body>
+            </fo:table>
+          </fo:block>
+          <fo:block>
+            <fo:block font-size="9pt">
+              <fo:leader/>
+              <fo:block break-before="page"/>
+            </fo:block>
+          </fo:block>
+
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="" xpath="//pageViewport[1]//flow/block[2]//text"/>
+    <eval expected="" xpath="//pageViewport[2]//flow/block[1]//text"/>
+  </checks>
+</testcase>