]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla #46486: having a special page-master for the last page caused loss of conten...
authorVincent Hennebert <vhennebert@apache.org>
Mon, 18 Jan 2010 12:28:32 +0000 (12:28 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Mon, 18 Jan 2010 12:28:32 +0000 (12:28 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@900364 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/area/MainReference.java
src/java/org/apache/fop/layoutmgr/PageBreaker.java
status.xml
test/layoutengine/standard-testcases/page-sequence_two-column_last-page_1.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-sequence_two-column_last-page_2.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-sequence_two-column_last-page_2bis.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-sequence_two-column_last-page_3.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-sequence_two-column_last-page_4.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-sequence_two-column_last-page_5.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-sequence_two-column_last-page_6.xml [new file with mode: 0644]

index 0922ebd01fe4ef08898eb038e332ec98374e1146..dd53113afaed1cc461454039e819c4adb9254598 100644 (file)
@@ -19,8 +19,9 @@
 
 package org.apache.fop.area;
 
-import java.util.List;
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  * The main-reference-area generated by an fo:region-body
@@ -74,6 +75,17 @@ public class MainReference extends Area {
         return spanAreas;
     }
 
+    /**
+     * Do not use. Used to handle special page-master for last page: transfer the content
+     * that had already been added to a normal page to this main reference for the last
+     * page. TODO this is hacky.
+     *
+     * @param spans content already laid out
+     */
+    public void setSpans(List spans) {
+        spanAreas = new ArrayList(spans);
+    }
+
     /**
      * Get the span area currently being filled (i.e., the last span created).
      * @return the active span.
index 134e69f31298cde0a5305f235befc4339d338c3b..25ecd5a75199037cd680fc6905f205551a2038e1 100644 (file)
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.ListIterator;
 
 import org.apache.fop.area.Block;
+import org.apache.fop.area.BodyRegion;
 import org.apache.fop.area.Footnote;
 import org.apache.fop.area.PageViewport;
 import org.apache.fop.fo.Constants;
@@ -289,7 +290,7 @@ public class PageBreaker extends AbstractBreaker {
 
         if (needColumnBalancing) {
             //column balancing for the last part
-            doPhase3(alg, partCount, originalList, effectiveList, false);
+            redoLayout(alg, partCount, originalList, effectiveList);
             return;
         }
 
@@ -298,7 +299,7 @@ public class PageBreaker extends AbstractBreaker {
             //last part is reached
             if (lastPageMasterDefined) {
                 //last-page condition
-                doPhase3(alg, partCount, originalList, effectiveList, true);
+                redoLayout(alg, partCount, originalList, effectiveList);
                 return;
             }
         }
@@ -308,16 +309,12 @@ public class PageBreaker extends AbstractBreaker {
     }
 
     /**
-     * Restart the algorithm at the break corresponding
-     * to the given partCount
-     * (currently only used to redo the part after the
-     *  last break in case of column-balancing
-     *  and/or a last page-master)
+     * 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
+     * page-master.
      */
-    private void doPhase3(PageBreakingAlgorithm alg, int partCount,
-            BlockSequence originalList, BlockSequence effectiveList,
-            boolean isLastPart) {
-
+    private void redoLayout(PageBreakingAlgorithm alg, int partCount,
+            BlockSequence originalList, BlockSequence effectiveList) {
 
         int newStartPos = 0;
         int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
@@ -344,15 +341,10 @@ public class PageBreaker extends AbstractBreaker {
         pageProvider.setStartOfNextElementList(currentPageNum,
                 pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
 
-        PageBreakingAlgorithm algRestart = null;
-        int optimalPageCount;
         //Make sure we only add the areas we haven't added already
         effectiveList.ignoreAtStart = newStartPos;
 
-        if (isLastPart) {
-            pageProvider.setLastPageIndex(currentPageNum);
-        }
-
+        PageBreakingAlgorithm algRestart;
         if (needColumnBalancing) {
             AbstractBreaker.log.debug("Column balancing now!!!");
             AbstractBreaker.log.debug("===================================================");
@@ -365,7 +357,13 @@ public class PageBreaker extends AbstractBreaker {
                     pslm.getCurrentPV().getBodyRegion().getColumnCount());
             AbstractBreaker.log.debug("===================================================");
         } else  {
-            //plain last page, no column balancing
+            // Handle special page-master for last page
+            BodyRegion currentBody = pageProvider.getPage(false, currentPageNum)
+                    .getPageViewport().getBodyRegion();
+            pageProvider.setLastPageIndex(currentPageNum);
+            BodyRegion lastBody = pageProvider.getPage(false, currentPageNum)
+                    .getPageViewport().getBodyRegion();
+            lastBody.getMainReference().setSpans(currentBody.getMainReference().getSpans());
             AbstractBreaker.log.debug("Last page handling now!!!");
             AbstractBreaker.log.debug("===================================================");
             //Restart last page
@@ -377,16 +375,25 @@ public class PageBreaker extends AbstractBreaker {
             AbstractBreaker.log.debug("===================================================");
         }
 
-        optimalPageCount = algRestart.findBreakingPoints(effectiveList,
+        int optimalPageCount = algRestart.findBreakingPoints(effectiveList,
                     newStartPos,
                     1, true, BreakingAlgorithm.ALL_BREAKS);
         AbstractBreaker.log.debug("restart: optimalPageCount= " + optimalPageCount
                 + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
 
         boolean fitsOnePage
-                = optimalPageCount <= pslm.getCurrentPV().getBodyRegion().getColumnCount();
+                = optimalPageCount <= pslm.getCurrentPV().getBodyRegion().getMainReference().getCurrentSpan().getColumnCount();
 
-        if (isLastPart) {
+        if (needColumnBalancing) {
+            if (!fitsOnePage) {
+                AbstractBreaker.log.warn(
+                        "Breaking algorithm produced more columns than are available.");
+                /* reenable when everything works
+                throw new IllegalStateException(
+                        "Breaking algorithm must not produce more columns than available.");
+                */
+            }
+        } else {
             if (fitsOnePage) {
                 //Replace last page
                 pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
@@ -399,15 +406,6 @@ public class PageBreaker extends AbstractBreaker {
                 pslm.setCurrentPage(pslm.makeNewPage(true, true));
                 return;
             }
-        } else {
-            if (!fitsOnePage) {
-                AbstractBreaker.log.warn(
-                        "Breaking algorithm produced more columns than are available.");
-                /* reenable when everything works
-                throw new IllegalStateException(
-                        "Breaking algorithm must not produce more columns than available.");
-                */
-            }
         }
 
         addAreas(algRestart, optimalPageCount, originalList, effectiveList);
index 853fbdf1699425a25ce755303b927816194ebb3b..dcf1712ab67b4bf47a1225210f8375186951c9f1 100644 (file)
       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="46486">
+        Bugfix: having a special page-master for the last page caused loss of content when normal 
+        blocks were mixed with blocks spanning all columns.
+      </action>
       <action context="Renderers" dev="VH" type="add">
         Added possibility to customize PDF tagging via the ‘role’ property.
       </action>
diff --git a/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_1.xml b/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_1.xml
new file mode 100644 (file)
index 0000000..ecc348a
--- /dev/null
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks that a two-column document with a last page setting is properly rendered.
+    </p>
+    <p>
+      Test case: last content fits on last page without re-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"
+          page-height="250pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0F0"/>
+          <fo:region-before region-name="page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="last-page"
+          page-height="150pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0FF"/>
+          <fo:region-before region-name="last-page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="last-page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference page-position="last" master-reference="last-page"/>
+            <fo:conditional-page-master-reference page-position="any"  master-reference="page"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages" font-size="7pt" text-align="center">
+        <fo:static-content flow-name="page-header">
+          <fo:block border-bottom="1pt solid black" padding-bottom="0.5pt">Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="page-footer">
+          <fo:block border-top="1pt solid black" padding-top="0.5pt">Page Footer</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-header">
+          <fo:block border-bottom="1pt solid blue" padding-bottom="0.5pt">Last Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-footer">
+          <fo:block border-top="1pt solid blue" padding-top="0.5pt">Last Page Footer</fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt" text-align="justify"
+          space-before.minimum="0.8em"
+          space-before.optimum="1.0em"
+          space-before.maximum="2.5em">
+          <fo:block space-before="inherit">Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
+            In in egestas nisi. Etiam at ante eget velit placerat ullamcorper. Suspendisse potenti. 
+            Nulla posuere turpis ac orci placerat vitae lacinia lectus tincidunt. Duis ultricies 
+            diam et lectus tempor aliquam. Mauris ligula arcu, hendrerit imperdiet ultrices laoreet, 
+            gravida sit amet metus. Donec vehicula iaculis condimentum. Sed eget tortor nec libero 
+            venenatis tincidunt.</fo:block>
+          <fo:block space-before="inherit">Curabitur dui tortor, congue in condimentum dapibus, 
+            volutpat non ligula. Proin tincidunt, sem eget luctus iaculis, mi neque posuere dui, non 
+            elementum ante diam quis odio. Nam blandit elit massa, vel tempus tortor. Phasellus et 
+            sem nec ante dignissim pellentesque id sed est. Sed vel magna odio, quis condimentum 
+            nibh. Mauris condimentum turpis vitae mauris mattis pulvinar. Donec tortor dolor, 
+            molestie id pellentesque nec, adipiscing in massa.</fo:block>
+          <fo:block space-before="inherit">Morbi semper sodales nisl, vitae sagittis orci adipiscing 
+            feugiat. Quisque consectetur ullamcorper sapien, eget adipiscing orci imperdiet ac. 
+            Integer leo ipsum, aliquam sagittis consequat consectetur, scelerisque nec diam. 
+            Vestibulum urna mi, hendrerit ac lacinia et, eleifend vitae ligula. In a urna 
+            quam.</fo:block>
+          <fo:block space-before="inherit">Duis iaculis ultrices congue. Sed sodales iaculis 
+            dapibus. Aenean vel felis odio, sed facilisis erat. Nam molestie, quam ac aliquam 
+            cursus, lectus lectus ullamcorper massa, eget porttitor erat lectus a mi. Duis quis elit 
+            at nunc convallis tempor sed nec risus. Nullam sit amet ante lectus, rutrum congue mi. 
+            Curabitur dui risus, malesuada at varius vel, aliquam vel elit. Nunc posuere facilisis 
+            risus, vitae ultrices velit tincidunt sed.</fo:block>
+          <fo:block space-before="inherit" span="all" color="purple">Integer dictum erat in nulla 
+            accumsan in tincidunt mauris vehicula. Aenean sed enim ligula, sollicitudin porta magna. 
+            Suspendisse scelerisque tincidunt purus, sit amet viverra libero porta eget. Aliquam 
+            erat volutpat. Curabitur eu tempor leo.</fo:block>
+          <fo:block space-before="inherit">Etiam placerat, ante vel lacinia mattis, tellus lectus 
+            facilisis dui, id accumsan ante neque ut turpis.</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="2"   xpath="count(//pageViewport)"/>
+
+    <eval expected="page"      xpath="//pageViewport[1]/@simple-page-master-name"/>
+    <eval expected="Duis quis elit at nunc convallis tempor sed"
+                               xpath="//pageViewport[1]//flow[2]/block[position()=last()]/lineArea[position()=last()]"/>
+
+    <eval expected="last-page" xpath="//pageViewport[2]/@simple-page-master-name"/>
+    <eval expected="3"   xpath="count(//pageViewport[2]//mainReference/span)"/>
+    <eval expected="nec risus. Nullam sit amet ante lectus,"
+                               xpath="//pageViewport[2]//span[1]//lineArea[1]"/>
+    <eval expected="velit tincidunt sed."
+                               xpath="//pageViewport[2]//span[1]/flow[2]//lineArea[position()=last()]"/>
+    <eval expected="30000"     xpath="//pageViewport[2]//mainReference/span[2]/@bpd"/>
+    <eval expected="0"         xpath="//pageViewport[2]//mainReference/span[3]/flow[2]/@bpd"/>
+    <eval expected="Etiam placerat, ante vel lacinia mattis,"
+                               xpath="//pageViewport[2]//span[3]//lineArea[1]"/>
+    <eval expected="ante neque ut turpis."
+                               xpath="//pageViewport[2]//span[3]//lineArea[position()=last()]"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_2.xml b/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_2.xml
new file mode 100644 (file)
index 0000000..75a7360
--- /dev/null
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks that a two-column document with a last page setting is properly rendered.
+    </p>
+    <p>
+      Test case: last content fits on last page, but must be re-laid out (into two columns instead 
+      of one.)
+    </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"
+          page-height="250pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0F0"/>
+          <fo:region-before region-name="page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="last-page"
+          page-height="150pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0FF"/>
+          <fo:region-before region-name="last-page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="last-page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference page-position="last" master-reference="last-page"/>
+            <fo:conditional-page-master-reference page-position="any"  master-reference="page"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages" font-size="7pt" text-align="center">
+        <fo:static-content flow-name="page-header">
+          <fo:block border-bottom="1pt solid black" padding-bottom="0.5pt">Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="page-footer">
+          <fo:block border-top="1pt solid black" padding-top="0.5pt">Page Footer</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-header">
+          <fo:block border-bottom="1pt solid blue" padding-bottom="0.5pt">Last Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-footer">
+          <fo:block border-top="1pt solid blue" padding-top="0.5pt">Last Page Footer</fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt" text-align="justify"
+          space-before.minimum="0.8em"
+          space-before.optimum="1.0em"
+          space-before.maximum="2.5em">
+          <fo:block space-before="inherit">Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
+            In in egestas nisi. Etiam at ante eget velit placerat ullamcorper. Suspendisse potenti. 
+            Nulla posuere turpis ac orci placerat vitae lacinia lectus tincidunt. Duis ultricies 
+            diam et lectus tempor aliquam. Mauris ligula arcu, hendrerit imperdiet ultrices laoreet, 
+            gravida sit amet metus. Donec vehicula iaculis condimentum. Sed eget tortor nec libero 
+            venenatis tincidunt.</fo:block>
+          <fo:block space-before="inherit">Curabitur dui tortor, congue in condimentum dapibus, 
+            volutpat non ligula. Proin tincidunt, sem eget luctus iaculis, mi neque posuere dui, non 
+            elementum ante diam quis odio. Nam blandit elit massa, vel tempus tortor. Phasellus et 
+            sem nec ante dignissim pellentesque id sed est. Sed vel magna odio, quis condimentum 
+            nibh. Mauris condimentum turpis vitae mauris mattis pulvinar. Donec tortor dolor, 
+            molestie id pellentesque nec, adipiscing in massa.</fo:block>
+          <fo:block space-before="inherit">Morbi semper sodales nisl, vitae sagittis orci adipiscing 
+            feugiat. Quisque consectetur ullamcorper sapien, eget adipiscing orci imperdiet ac. 
+            Integer leo ipsum, aliquam sagittis consequat consectetur, scelerisque nec diam. 
+            Vestibulum urna mi, hendrerit ac lacinia et, eleifend vitae ligula. In a urna 
+            quam.</fo:block>
+          <fo:block space-before="inherit">Duis iaculis ultrices congue. Sed sodales iaculis 
+            dapibus. Aenean vel felis odio, sed facilisis erat. Nam molestie, quam ac aliquam 
+            cursus, lectus lectus ullamcorper massa, eget porttitor erat lectus a mi. Duis quis elit 
+            at nunc convallis tempor sed nec risus. Nullam sit amet ante lectus, rutrum congue mi. 
+            Curabitur dui risus, malesuada at varius vel, aliquam vel elit. Nunc posuere facilisis 
+            risus, vitae ultrices velit tincidunt sed.</fo:block>
+          <fo:block space-before="inherit" span="all" color="purple">Integer dictum erat in nulla 
+            accumsan in tincidunt mauris vehicula. Aenean sed enim ligula, sollicitudin porta magna. 
+            Suspendisse scelerisque tincidunt purus, sit amet viverra libero porta eget. Aliquam 
+            erat volutpat. Curabitur eu tempor leo.</fo:block>
+          <fo:block space-before="inherit">Etiam placerat, ante vel lacinia mattis, tellus lectus 
+            facilisis dui, id accumsan ante neque ut turpis. Aenean lorem arcu, aliquam vel 
+            tincidunt vel, malesuada quis nulla. Aliquam erat volutpat. Praesent sapien nisl, 
+            malesuada eget hendrerit vel, posuere in lectus.</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="2"   xpath="count(//pageViewport)"/>
+
+    <eval expected="page"      xpath="//pageViewport[1]/@simple-page-master-name"/>
+    <eval expected="Duis quis elit at nunc convallis tempor sed"
+                               xpath="//pageViewport[1]//flow[2]/block[position()=last()]/lineArea[position()=last()]"/>
+
+    <eval expected="last-page" xpath="//pageViewport[2]/@simple-page-master-name"/>
+    <eval expected="3"   xpath="count(//pageViewport[2]//mainReference/span)"/>
+    <eval expected="nec risus. Nullam sit amet ante lectus,"
+                               xpath="//pageViewport[2]//span[1]//lineArea[1]"/>
+    <eval expected="velit tincidunt sed."
+                               xpath="//pageViewport[2]//span[1]/flow[2]//lineArea[position()=last()]"/>
+    <eval expected="30000"     xpath="//pageViewport[2]//mainReference/span[2]/@bpd"/>
+    <eval expected="Etiam placerat, ante vel lacinia mattis,"
+                               xpath="//pageViewport[2]//span[3]/flow[1]//lineArea[1]"/>
+    <eval expected="aliquam vel tincidunt vel, malesuada quis"
+                               xpath="//pageViewport[2]//span[3]/flow[1]//lineArea[position()=last()]"/>
+    <eval expected="nulla. Aliquam erat volutpat. Praesent"
+                               xpath="//pageViewport[2]//span[3]/flow[2]//lineArea[1]"/>
+    <eval expected="posuere in lectus."
+                               xpath="//pageViewport[2]//span[3]/flow[2]//lineArea[position()=last()]"/>
+
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_2bis.xml b/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_2bis.xml
new file mode 100644 (file)
index 0000000..06ddb60
--- /dev/null
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks that a two-column document with a last page setting is properly rendered.
+    </p>
+    <p>
+      Test case: last content fits on last page, but must be re-laid out (into two columns instead 
+      of one.)
+    </p>
+    <p>
+      Copy of page-sequence_two-column_last-page_2.xml, height of last page increased by 5pt so that 
+      content does not exactly fit and node recovery mechanism is triggered.
+    </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"
+          page-height="250pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0F0"/>
+          <fo:region-before region-name="page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="last-page"
+          page-height="155pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0FF"/>
+          <fo:region-before region-name="last-page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="last-page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference page-position="last" master-reference="last-page"/>
+            <fo:conditional-page-master-reference page-position="any"  master-reference="page"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages" font-size="7pt" text-align="center">
+        <fo:static-content flow-name="page-header">
+          <fo:block border-bottom="1pt solid black" padding-bottom="0.5pt">Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="page-footer">
+          <fo:block border-top="1pt solid black" padding-top="0.5pt">Page Footer</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-header">
+          <fo:block border-bottom="1pt solid blue" padding-bottom="0.5pt">Last Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-footer">
+          <fo:block border-top="1pt solid blue" padding-top="0.5pt">Last Page Footer</fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt" text-align="justify"
+          space-before.minimum="0.8em"
+          space-before.optimum="1.0em"
+          space-before.maximum="2.5em">
+          <fo:block space-before="inherit">Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
+            In in egestas nisi. Etiam at ante eget velit placerat ullamcorper. Suspendisse potenti. 
+            Nulla posuere turpis ac orci placerat vitae lacinia lectus tincidunt. Duis ultricies 
+            diam et lectus tempor aliquam. Mauris ligula arcu, hendrerit imperdiet ultrices laoreet, 
+            gravida sit amet metus. Donec vehicula iaculis condimentum. Sed eget tortor nec libero 
+            venenatis tincidunt.</fo:block>
+          <fo:block space-before="inherit">Curabitur dui tortor, congue in condimentum dapibus, 
+            volutpat non ligula. Proin tincidunt, sem eget luctus iaculis, mi neque posuere dui, non 
+            elementum ante diam quis odio. Nam blandit elit massa, vel tempus tortor. Phasellus et 
+            sem nec ante dignissim pellentesque id sed est. Sed vel magna odio, quis condimentum 
+            nibh. Mauris condimentum turpis vitae mauris mattis pulvinar. Donec tortor dolor, 
+            molestie id pellentesque nec, adipiscing in massa.</fo:block>
+          <fo:block space-before="inherit">Morbi semper sodales nisl, vitae sagittis orci adipiscing 
+            feugiat. Quisque consectetur ullamcorper sapien, eget adipiscing orci imperdiet ac. 
+            Integer leo ipsum, aliquam sagittis consequat consectetur, scelerisque nec diam. 
+            Vestibulum urna mi, hendrerit ac lacinia et, eleifend vitae ligula. In a urna 
+            quam.</fo:block>
+          <fo:block space-before="inherit">Duis iaculis ultrices congue. Sed sodales iaculis 
+            dapibus. Aenean vel felis odio, sed facilisis erat. Nam molestie, quam ac aliquam 
+            cursus, lectus lectus ullamcorper massa, eget porttitor erat lectus a mi. Duis quis elit 
+            at nunc convallis tempor sed nec risus. Nullam sit amet ante lectus, rutrum congue mi. 
+            Curabitur dui risus, malesuada at varius vel, aliquam vel elit. Nunc posuere facilisis 
+            risus, vitae ultrices velit tincidunt sed.</fo:block>
+          <fo:block space-before="inherit" span="all" color="purple">Integer dictum erat in nulla 
+            accumsan in tincidunt mauris vehicula. Aenean sed enim ligula, sollicitudin porta magna. 
+            Suspendisse scelerisque tincidunt purus, sit amet viverra libero porta eget. Aliquam 
+            erat volutpat. Curabitur eu tempor leo.</fo:block>
+          <fo:block space-before="inherit">Etiam placerat, ante vel lacinia mattis, tellus lectus 
+            facilisis dui, id accumsan ante neque ut turpis. Aenean lorem arcu, aliquam vel 
+            tincidunt vel, malesuada quis nulla. Aliquam erat volutpat. Praesent sapien nisl, 
+            malesuada eget hendrerit vel, posuere in lectus.</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="2"   xpath="count(//pageViewport)"/>
+
+    <eval expected="page"      xpath="//pageViewport[1]/@simple-page-master-name"/>
+    <eval expected="Duis quis elit at nunc convallis tempor sed"
+                               xpath="//pageViewport[1]//flow[2]/block[position()=last()]/lineArea[position()=last()]"/>
+
+    <eval expected="last-page" xpath="//pageViewport[2]/@simple-page-master-name"/>
+    <eval expected="3"   xpath="count(//pageViewport[2]//mainReference/span)"/>
+    <eval expected="nec risus. Nullam sit amet ante lectus,"
+                               xpath="//pageViewport[2]//span[1]//lineArea[1]"/>
+    <eval expected="velit tincidunt sed."
+                               xpath="//pageViewport[2]//span[1]/flow[2]//lineArea[position()=last()]"/>
+    <eval expected="30000"     xpath="//pageViewport[2]//mainReference/span[2]/@bpd"/>
+    <eval expected="Etiam placerat, ante vel lacinia mattis,"
+                               xpath="//pageViewport[2]//span[3]/flow[1]//lineArea[1]"/>
+    <eval expected="aliquam vel tincidunt vel, malesuada quis"
+                               xpath="//pageViewport[2]//span[3]/flow[1]//lineArea[position()=last()]"/>
+    <eval expected="nulla. Aliquam erat volutpat. Praesent"
+                               xpath="//pageViewport[2]//span[3]/flow[2]//lineArea[1]"/>
+    <eval expected="posuere in lectus."
+                               xpath="//pageViewport[2]//span[3]/flow[2]//lineArea[position()=last()]"/>
+
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_3.xml b/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_3.xml
new file mode 100644 (file)
index 0000000..fa54373
--- /dev/null
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks that a two-column document with a last page setting is properly rendered.
+    </p>
+    <p>
+      Test case: last content does not fit on last page, normal page master must be used and empty 
+      last page produced.
+    </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"
+          page-height="250pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0F0"/>
+          <fo:region-before region-name="page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="last-page"
+          page-height="150pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0FF"/>
+          <fo:region-before region-name="last-page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="last-page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference page-position="last" master-reference="last-page"/>
+            <fo:conditional-page-master-reference page-position="any"  master-reference="page"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages" font-size="7pt" text-align="center">
+        <fo:static-content flow-name="page-header">
+          <fo:block border-bottom="1pt solid black" padding-bottom="0.5pt">Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="page-footer">
+          <fo:block border-top="1pt solid black" padding-top="0.5pt">Page Footer</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-header">
+          <fo:block border-bottom="1pt solid blue" padding-bottom="0.5pt">Last Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-footer">
+          <fo:block border-top="1pt solid blue" padding-top="0.5pt">Last Page Footer</fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt" text-align="justify"
+          space-before.minimum="0.8em"
+          space-before.optimum="1.0em"
+          space-before.maximum="2.5em">
+          <fo:block space-before="inherit">Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
+            In in egestas nisi. Etiam at ante eget velit placerat ullamcorper. Suspendisse potenti. 
+            Nulla posuere turpis ac orci placerat vitae lacinia lectus tincidunt. Duis ultricies 
+            diam et lectus tempor aliquam. Mauris ligula arcu, hendrerit imperdiet ultrices laoreet, 
+            gravida sit amet metus. Donec vehicula iaculis condimentum. Sed eget tortor nec libero 
+            venenatis tincidunt.</fo:block>
+          <fo:block space-before="inherit">Curabitur dui tortor, congue in condimentum dapibus, 
+            volutpat non ligula. Proin tincidunt, sem eget luctus iaculis, mi neque posuere dui, non 
+            elementum ante diam quis odio. Nam blandit elit massa, vel tempus tortor. Phasellus et 
+            sem nec ante dignissim pellentesque id sed est. Sed vel magna odio, quis condimentum 
+            nibh. Mauris condimentum turpis vitae mauris mattis pulvinar. Donec tortor dolor, 
+            molestie id pellentesque nec, adipiscing in massa.</fo:block>
+          <fo:block space-before="inherit">Morbi semper sodales nisl, vitae sagittis orci adipiscing 
+            feugiat. Quisque consectetur ullamcorper sapien, eget adipiscing orci imperdiet ac. 
+            Integer leo ipsum, aliquam sagittis consequat consectetur, scelerisque nec diam. 
+            Vestibulum urna mi, hendrerit ac lacinia et, eleifend vitae ligula. In a urna 
+            quam.</fo:block>
+          <fo:block space-before="inherit">Duis iaculis ultrices congue. Sed sodales iaculis 
+            dapibus. Aenean vel felis odio, sed facilisis erat. Nam molestie, quam ac aliquam 
+            cursus, lectus lectus ullamcorper massa, eget porttitor erat lectus a mi. Duis quis elit 
+            at nunc convallis tempor sed nec risus. Nullam sit amet ante lectus, rutrum congue mi. 
+            Curabitur dui risus, malesuada at varius vel, aliquam vel elit. Nunc posuere facilisis 
+            risus, vitae ultrices velit tincidunt sed.</fo:block>
+          <fo:block space-before="inherit" span="all" color="purple">Integer dictum erat in nulla 
+            accumsan in tincidunt mauris vehicula. Aenean sed enim ligula, sollicitudin porta magna. 
+            Suspendisse scelerisque tincidunt purus, sit amet viverra libero porta eget. Aliquam 
+            erat volutpat. Curabitur eu tempor leo.</fo:block>
+          <fo:block space-before="inherit">Etiam placerat, ante vel lacinia mattis, tellus lectus 
+            facilisis dui, id accumsan ante neque ut turpis. Aenean lorem arcu, aliquam vel 
+            tincidunt vel, malesuada quis nulla. Aliquam erat volutpat. Praesent sapien nisl, 
+            malesuada eget hendrerit vel, posuere in lectus.</fo:block>
+          <fo:block space-before="inherit">Quisque porttitor tellus a leo adipiscing malesuada. Nunc 
+            molestie, erat et ullamcorper vulputate, augue eros lobortis ligula, non fringilla diam 
+            tortor a nunc. Aenean ante sapien, bibendum in gravida rhoncus, mollis ut arcu. Sed 
+            magna massa, feugiat eu adipiscing ac, tincidunt quis mi. Mauris fermentum ullamcorper 
+            magna, eget molestie felis auctor quis.</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="3"   xpath="count(//pageViewport)"/>
+
+    <eval expected="Duis quis elit at nunc convallis tempor sed"
+                               xpath="//pageViewport[1]//flow[2]/block[position()=last()]/lineArea[position()=last()]"/>
+
+    <eval expected="page"      xpath="//pageViewport[2]/@simple-page-master-name"/>
+    <eval expected="3"   xpath="count(//pageViewport[2]//mainReference/span)"/>
+    <eval expected="nec risus. Nullam sit amet ante lectus,"
+                               xpath="//pageViewport[2]//span[1]//lineArea[1]"/>
+    <eval expected="velit tincidunt sed."
+                               xpath="//pageViewport[2]//span[1]/flow[2]//lineArea[position()=last()]"/>
+    <eval expected="30000"     xpath="//pageViewport[2]//mainReference/span[2]/@bpd"/>
+    <eval expected="Etiam placerat, ante vel lacinia mattis,"
+                               xpath="//pageViewport[2]//span[3]/flow[1]//lineArea[1]"/>
+    <eval expected="in gravida rhoncus, mollis ut arcu. Sed"
+                               xpath="//pageViewport[2]//span[3]/flow[1]/block[position()=last()]/lineArea[position()=last()]"/>
+    <eval expected="magna massa, feugiat eu adipiscing"
+                               xpath="//pageViewport[2]//span[3]/flow[2]//lineArea[1]"/>
+    <eval expected="auctor quis."
+                               xpath="//pageViewport[2]//span[3]/flow[2]//lineArea[position()=last()]"/>
+
+    <eval expected="last-page" xpath="//pageViewport[3]/@simple-page-master-name"/>
+    <eval expected="0"         xpath="//pageViewport[3]//regionBody//span/@bpd"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_4.xml b/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_4.xml
new file mode 100644 (file)
index 0000000..2d2c14d
--- /dev/null
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks that a two-column document with a last page setting is properly rendered.
+    </p>
+    <p>
+      Test case: last content spans all columns and does not fit on last page, normal page master 
+      must be used and empty last page produced.
+    </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"
+          page-height="250pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0F0"/>
+          <fo:region-before region-name="page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="last-page"
+          page-height="150pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0FF"/>
+          <fo:region-before region-name="last-page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="last-page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference page-position="last" master-reference="last-page"/>
+            <fo:conditional-page-master-reference page-position="any"  master-reference="page"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages" font-size="7pt" text-align="center">
+        <fo:static-content flow-name="page-header">
+          <fo:block border-bottom="1pt solid black" padding-bottom="0.5pt">Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="page-footer">
+          <fo:block border-top="1pt solid black" padding-top="0.5pt">Page Footer</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-header">
+          <fo:block border-bottom="1pt solid blue" padding-bottom="0.5pt">Last Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-footer">
+          <fo:block border-top="1pt solid blue" padding-top="0.5pt">Last Page Footer</fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt" text-align="justify"
+          space-before.minimum="0.8em"
+          space-before.optimum="1.0em"
+          space-before.maximum="2.5em">
+          <fo:block space-before="inherit">Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
+            In in egestas nisi. Etiam at ante eget velit placerat ullamcorper. Suspendisse potenti. 
+            Nulla posuere turpis ac orci placerat vitae lacinia lectus tincidunt. Duis ultricies 
+            diam et lectus tempor aliquam. Mauris ligula arcu, hendrerit imperdiet ultrices laoreet, 
+            gravida sit amet metus. Donec vehicula iaculis condimentum. Sed eget tortor nec libero 
+            venenatis tincidunt.</fo:block>
+          <fo:block space-before="inherit">Curabitur dui tortor, congue in condimentum dapibus, 
+            volutpat non ligula. Proin tincidunt, sem eget luctus iaculis, mi neque posuere dui, non 
+            elementum ante diam quis odio. Nam blandit elit massa, vel tempus tortor. Phasellus et 
+            sem nec ante dignissim pellentesque id sed est. Sed vel magna odio, quis condimentum 
+            nibh. Mauris condimentum turpis vitae mauris mattis pulvinar. Donec tortor dolor, 
+            molestie id pellentesque nec, adipiscing in massa.</fo:block>
+          <fo:block space-before="inherit">Morbi semper sodales nisl, vitae sagittis orci adipiscing 
+            feugiat. Quisque consectetur ullamcorper sapien, eget adipiscing orci imperdiet ac. 
+            Integer leo ipsum, aliquam sagittis consequat consectetur, scelerisque nec diam. 
+            Vestibulum urna mi, hendrerit ac lacinia et, eleifend vitae ligula. In a urna 
+            quam.</fo:block>
+          <fo:block space-before="inherit">Duis iaculis ultrices congue. Sed sodales iaculis 
+            dapibus. Aenean vel felis odio, sed facilisis erat. Nam molestie, quam ac aliquam 
+            cursus, lectus lectus ullamcorper massa, eget porttitor erat lectus a mi. Duis quis elit 
+            at nunc convallis tempor sed nec risus. Nullam sit amet ante lectus, rutrum congue mi. 
+            Curabitur dui risus, malesuada at varius vel, aliquam vel elit.</fo:block>
+          <fo:block space-before="inherit">Integer dictum erat in nulla accumsan in tincidunt mauris 
+            vehicula. Aenean sed enim ligula, sollicitudin porta magna. Suspendisse scelerisque 
+            tincidunt purus, sit amet viverra libero porta eget. Aliquam erat volutpat. Curabitur eu 
+            tempor leo.</fo:block>
+          <fo:block space-before="inherit" span="all" color="purple">Quisque porttitor tellus a leo 
+            adipiscing malesuada. Nunc molestie, erat et ullamcorper vulputate, augue eros lobortis 
+            ligula, non fringilla diam tortor a nunc. Aenean ante sapien, bibendum in gravida 
+            rhoncus, mollis ut arcu. Sed magna massa, feugiat eu adipiscing ac, tincidunt quis mi. 
+            Mauris fermentum ullamcorper magna, eget molestie felis auctor quis.</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="3"   xpath="count(//pageViewport)"/>
+
+    <eval expected="Duis quis elit at nunc convallis tempor sed"
+                               xpath="//pageViewport[1]//flow[2]/block[position()=last()]/lineArea[position()=last()]"/>
+
+    <eval expected="page"      xpath="//pageViewport[2]/@simple-page-master-name"/>
+    <eval expected="2"   xpath="count(//pageViewport[2]//mainReference/span)"/>
+    <eval expected="nec risus. Nullam sit amet ante lectus,"
+                               xpath="//pageViewport[2]//span[1]//lineArea[1]"/>
+    <eval expected="erat volutpat. Curabitur eu tempor leo."
+                               xpath="//pageViewport[2]//span[1]/flow[2]//lineArea[position()=last()]"/>
+    <eval expected="50000"     xpath="//pageViewport[2]//mainReference/span[2]/@bpd"/>
+
+    <eval expected="last-page" xpath="//pageViewport[3]/@simple-page-master-name"/>
+    <eval expected="0"         xpath="//pageViewport[3]//regionBody//span/@bpd"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_5.xml b/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_5.xml
new file mode 100644 (file)
index 0000000..cf92bdb
--- /dev/null
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks that a two-column document with a last page setting is properly rendered.
+    </p>
+    <p>
+      Test case: last content does not fit on last page, and there is not even space left to fit any 
+      part of it after switching to last-page master.
+    </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"
+          page-height="250pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0F0"/>
+          <fo:region-before region-name="page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="last-page"
+          page-height="150pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0FF"/>
+          <fo:region-before region-name="last-page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="last-page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference page-position="last" master-reference="last-page"/>
+            <fo:conditional-page-master-reference page-position="any"  master-reference="page"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages" font-size="7pt" text-align="center">
+        <fo:static-content flow-name="page-header">
+          <fo:block border-bottom="1pt solid black" padding-bottom="0.5pt">Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="page-footer">
+          <fo:block border-top="1pt solid black" padding-top="0.5pt">Page Footer</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-header">
+          <fo:block border-bottom="1pt solid blue" padding-bottom="0.5pt">Last Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-footer">
+          <fo:block border-top="1pt solid blue" padding-top="0.5pt">Last Page Footer</fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt" text-align="justify"
+          space-before.minimum="0.8em"
+          space-before.optimum="1.0em"
+          space-before.maximum="2.5em">
+          <fo:block space-before="inherit">Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
+            In in egestas nisi. Etiam at ante eget velit placerat ullamcorper. Suspendisse potenti. 
+            Nulla posuere turpis ac orci placerat vitae lacinia lectus tincidunt. Duis ultricies 
+            diam et lectus tempor aliquam. Mauris ligula arcu, hendrerit imperdiet ultrices laoreet, 
+            gravida sit amet metus. Donec vehicula iaculis condimentum. Sed eget tortor nec libero 
+            venenatis tincidunt.</fo:block>
+          <fo:block space-before="inherit">Curabitur dui tortor, congue in condimentum dapibus, 
+            volutpat non ligula. Proin tincidunt, sem eget luctus iaculis, mi neque posuere dui, non 
+            elementum ante diam quis odio. Nam blandit elit massa, vel tempus tortor. Phasellus et 
+            sem nec ante dignissim pellentesque id sed est. Sed vel magna odio, quis condimentum 
+            nibh. Mauris condimentum turpis vitae mauris mattis pulvinar. Donec tortor dolor, 
+            molestie id pellentesque nec, adipiscing in massa.</fo:block>
+          <fo:block space-before="inherit">Morbi semper sodales nisl, vitae sagittis orci adipiscing 
+            feugiat. Quisque consectetur ullamcorper sapien, eget adipiscing orci imperdiet ac. 
+            Integer leo ipsum, aliquam sagittis consequat consectetur, scelerisque nec diam. 
+            Vestibulum urna mi, hendrerit ac lacinia et, eleifend vitae ligula. In a urna 
+            quam.</fo:block>
+          <fo:block space-before="inherit">Duis iaculis ultrices congue. Sed sodales iaculis 
+            dapibus. Aenean vel felis odio, sed facilisis erat. Nam molestie, quam ac aliquam 
+            cursus, lectus lectus ullamcorper massa, eget porttitor erat lectus a mi. Duis quis elit 
+            at nunc convallis tempor sed nec risus. Nullam sit amet ante lectus, rutrum congue mi. 
+            Curabitur dui risus, malesuada at varius vel, aliquam vel elit.</fo:block>
+          <fo:block space-before="inherit">Integer dictum erat in nulla accumsan in tincidunt mauris 
+            vehicula. Aenean sed enim ligula, sollicitudin porta magna. Suspendisse scelerisque 
+            tincidunt purus, sit amet viverra libero porta eget. Aliquam erat volutpat. Curabitur eu 
+            tempor leo.</fo:block>
+          <fo:block space-before="inherit" span="all" color="purple">Etiam placerat, ante vel 
+            lacinia mattis, tellus lectus facilisis dui, id accumsan ante neque ut turpis. Aenean 
+            lorem arcu, aliquam vel tincidunt vel, malesuada quis nulla. Aliquam erat volutpat. 
+            Praesent sapien nisl, malesuada eget hendrerit vel, posuere in lectus.</fo:block>
+          <fo:block space-before="inherit">Quisque porttitor tellus a leo adipiscing malesuada. Nunc 
+            molestie, erat et ullamcorper vulputate, augue eros lobortis ligula, non fringilla diam 
+            tortor a nunc. Aenean ante sapien, bibendum in gravida rhoncus, mollis ut arcu. Sed 
+            magna massa, feugiat eu adipiscing ac, tincidunt quis mi. Mauris fermentum ullamcorper 
+            magna, eget molestie felis auctor quis.</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="3"   xpath="count(//pageViewport)"/>
+
+    <eval expected="Duis quis elit at nunc convallis tempor sed"
+                               xpath="//pageViewport[1]//flow[2]/block[position()=last()]/lineArea[position()=last()]"/>
+
+    <eval expected="page"      xpath="//pageViewport[2]/@simple-page-master-name"/>
+    <eval expected="3"   xpath="count(//pageViewport[2]//mainReference/span)"/>
+    <eval expected="nec risus. Nullam sit amet ante lectus,"
+                               xpath="//pageViewport[2]//span[1]//lineArea[1]"/>
+    <eval expected="erat volutpat. Curabitur eu tempor leo."
+                               xpath="//pageViewport[2]//span[1]/flow[2]//lineArea[position()=last()]"/>
+    <eval expected="40000"     xpath="//pageViewport[2]//mainReference/span[2]/@bpd"/>
+    <eval expected="Quisque porttitor tellus a leo adipiscing"
+                               xpath="//pageViewport[2]//span[3]/flow[1]//lineArea[1]"/>
+    <eval expected="ac, tincidunt quis mi. Mauris fermentum"
+                               xpath="//pageViewport[2]//span[3]/flow[1]//lineArea[position()=last()]"/>
+    <eval expected="ullamcorper magna, eget molestie felis"
+                               xpath="//pageViewport[2]//span[3]/flow[2]//lineArea[1]"/>
+    <eval expected="auctor quis."
+                               xpath="//pageViewport[2]//span[3]/flow[2]//lineArea[position()=last()]"/>
+
+    <eval expected="last-page" xpath="//pageViewport[3]/@simple-page-master-name"/>
+    <eval expected="0"         xpath="//pageViewport[3]//regionBody//span/@bpd"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_6.xml b/test/layoutengine/standard-testcases/page-sequence_two-column_last-page_6.xml
new file mode 100644 (file)
index 0000000..f5ff952
--- /dev/null
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- $Id$ -->
+<testcase>
+  <info>
+    <p>
+      This test checks that a two-column document with a last page setting is properly rendered.
+    </p>
+    <p>
+      Test case: last content spans all columns and does not fit on last page, and there is not even 
+      space left to fit any part of it after switching to last-page master.
+    </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"
+          page-height="250pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0F0"/>
+          <fo:region-before region-name="page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="last-page"
+          page-height="150pt" page-width="320pt" margin="10pt">
+          <fo:region-body margin-top="15pt" margin-bottom="15pt" column-count="2" column-gap="12pt"
+            background-color="#F0F0FF"/>
+          <fo:region-before region-name="last-page-header" extent="10pt" display-align="after"/>
+          <fo:region-after  region-name="last-page-footer" extent="10pt"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="pages">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference page-position="last" master-reference="last-page"/>
+            <fo:conditional-page-master-reference page-position="any"  master-reference="page"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="pages" font-size="7pt" text-align="center">
+        <fo:static-content flow-name="page-header">
+          <fo:block border-bottom="1pt solid black" padding-bottom="0.5pt">Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="page-footer">
+          <fo:block border-top="1pt solid black" padding-top="0.5pt">Page Footer</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-header">
+          <fo:block border-bottom="1pt solid blue" padding-bottom="0.5pt">Last Page Header</fo:block>
+        </fo:static-content>
+        <fo:static-content flow-name="last-page-footer">
+          <fo:block border-top="1pt solid blue" padding-top="0.5pt">Last Page Footer</fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body" font-size="8pt" line-height="10pt" text-align="justify"
+          space-before.minimum="0.8em"
+          space-before.optimum="1.0em"
+          space-before.maximum="2.5em">
+          <fo:block space-before="inherit">Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
+            In in egestas nisi. Etiam at ante eget velit placerat ullamcorper. Suspendisse potenti. 
+            Nulla posuere turpis ac orci placerat vitae lacinia lectus tincidunt. Duis ultricies 
+            diam et lectus tempor aliquam. Mauris ligula arcu, hendrerit imperdiet ultrices laoreet, 
+            gravida sit amet metus. Donec vehicula iaculis condimentum. Sed eget tortor nec libero 
+            venenatis tincidunt.</fo:block>
+          <fo:block space-before="inherit">Curabitur dui tortor, congue in condimentum dapibus, 
+            volutpat non ligula. Proin tincidunt, sem eget luctus iaculis, mi neque posuere dui, non 
+            elementum ante diam quis odio. Nam blandit elit massa, vel tempus tortor. Phasellus et 
+            sem nec ante dignissim pellentesque id sed est. Sed vel magna odio, quis condimentum 
+            nibh. Mauris condimentum turpis vitae mauris mattis pulvinar. Donec tortor dolor, 
+            molestie id pellentesque nec, adipiscing in massa.</fo:block>
+          <fo:block space-before="inherit">Morbi semper sodales nisl, vitae sagittis orci adipiscing 
+            feugiat. Quisque consectetur ullamcorper sapien, eget adipiscing orci imperdiet ac. 
+            Integer leo ipsum, aliquam sagittis consequat consectetur, scelerisque nec diam. 
+            Vestibulum urna mi, hendrerit ac lacinia et, eleifend vitae ligula. In a urna 
+            quam.</fo:block>
+          <fo:block space-before="inherit">Duis iaculis ultrices congue. Sed sodales iaculis 
+            dapibus. Aenean vel felis odio, sed facilisis erat. Nam molestie, quam ac aliquam 
+            cursus, lectus lectus ullamcorper massa, eget porttitor erat lectus a mi. Duis quis elit 
+            at nunc convallis tempor sed nec risus. Nullam sit amet ante lectus, rutrum congue mi. 
+            Curabitur dui risus, malesuada at varius vel, aliquam vel elit.</fo:block>
+          <fo:block space-before="inherit">Integer dictum erat in nulla accumsan in tincidunt mauris 
+            vehicula. Aenean sed enim ligula, sollicitudin porta magna. Suspendisse scelerisque 
+            tincidunt purus, sit amet viverra libero porta eget. Aliquam erat volutpat. Curabitur eu 
+            tempor leo.</fo:block>
+          <fo:block space-before="inherit">Etiam placerat, ante vel lacinia mattis, tellus lectus 
+            facilisis dui, id accumsan ante neque ut turpis. Aenean lorem arcu, aliquam vel 
+            tincidunt vel, malesuada quis nulla. Aliquam erat volutpat. Praesent sapien nisl, 
+            malesuada eget hendrerit vel, posuere in lectus.</fo:block>
+          <fo:block space-before="inherit" span="all" color="purple">Quisque porttitor tellus a leo 
+            adipiscing malesuada. Nunc molestie, erat et ullamcorper vulputate, augue eros lobortis 
+            ligula, non fringilla diam tortor a nunc. Aenean ante sapien, bibendum in gravida 
+            rhoncus, mollis ut arcu. Sed magna massa, feugiat eu adipiscing ac, tincidunt quis mi. 
+            Mauris fermentum ullamcorper magna, eget molestie felis auctor quis.</fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="3"   xpath="count(//pageViewport)"/>
+
+    <eval expected="aliquam cursus, lectus lectus ullamcorper"
+                               xpath="//pageViewport[1]//flow[2]/block[position()=last()]/lineArea[position()=last()]"/>
+
+    <eval expected="page"      xpath="//pageViewport[2]/@simple-page-master-name"/>
+    <eval expected="2"   xpath="count(//pageViewport[2]//mainReference/span)"/>
+    <eval expected="massa, eget porttitor erat lectus a mi."
+                               xpath="//pageViewport[2]//span[1]//lineArea[1]"/>
+    <eval expected="posuere in lectus."                                             
+                               xpath="//pageViewport[2]//span[1]/flow[2]/block[2]/lineArea[position()=last()]"/>
+    <eval expected="50000"     xpath="//pageViewport[2]//mainReference/span[2]/@bpd"/>
+    <eval expected="Quisque"   xpath="//pageViewport[2]//span[2]/flow[1]//lineArea[1]//word[1]"/>
+    <eval expected="felis auctor quis."
+                               xpath="//pageViewport[2]//span[2]/flow[1]//lineArea[position()=last()]"/>
+
+    <eval expected="last-page" xpath="//pageViewport[3]/@simple-page-master-name"/>
+    <eval expected="0"         xpath="//pageViewport[3]//regionBody//span/@bpd"/>
+  </checks>
+</testcase>