]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla #39118:
authorJeremias Maerki <jeremias@apache.org>
Sun, 23 Apr 2006 09:31:08 +0000 (09:31 +0000)
committerJeremias Maerki <jeremias@apache.org>
Sun, 23 Apr 2006 09:31:08 +0000 (09:31 +0000)
Initial support for page-number-citation-last (XSL 1.1). Works without problems only for page-sequence so far.
Submitted by: Pierre-Henri Kraus <phkraus.at.skynet.be>

Modifications to the patch by jeremias during review:
- Tab character removed
- Some style fixes and javadoc enhancements
- Renamed some methods in AreaTreeHandler to some more speaking names
- Changed the ..._basic.xml testcase so it shows a remaining problem: Forward references are not properly resolved, yet.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@396243 13f79535-47bb-0310-9956-ffa450edef68

24 files changed:
src/java/org/apache/fop/area/AreaTreeHandler.java
src/java/org/apache/fop/area/inline/UnresolvedPageNumber.java
src/java/org/apache/fop/fo/Constants.java
src/java/org/apache/fop/fo/FOElementMapping.java
src/java/org/apache/fop/fo/FObj.java
src/java/org/apache/fop/fo/PropertySets.java
src/java/org/apache/fop/fo/flow/PageNumberCitationLast.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
src/java/org/apache/fop/layoutmgr/PageSequenceLayoutManager.java
src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java [new file with mode: 0644]
src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
status.xml
test/layoutengine/disabled-testcases.xml
test/layoutengine/standard-testcases/page-number-citation-last_basic.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-number-citation-last_complex.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-number-citation-last_page-sequence.xml [new file with mode: 0644]
test/layoutengine/standard-testcases/page-position_last_1.xml

index 82a4ba234210c3429efba0749bdb17b4ef1c3f2d..8e165a99eb4a76f989a2a34a7563b7ce8015a7c9 100644 (file)
@@ -95,6 +95,9 @@ public class AreaTreeHandler extends FOEventHandler {
     // idref's whose target PageViewports have yet to be identified
     // Each idref has a HashSet of Resolvable objects containing that idref
     private Map unresolvedIDRefs = new HashMap();
+    
+    private Set unfinishedIDs = new HashSet();
+    private Set alreadyResolvedIDs = new HashSet();
 
      // The formatting results to be handed back to the caller.
     private FormattingResults results = new FormattingResults();
@@ -180,11 +183,62 @@ public class AreaTreeHandler extends FOEventHandler {
              * See if this ID is in the unresolved idref list, if so
              * resolve Resolvable objects tied to it.
              */
-            tryIDResolution(id, pv, pvList);
+            if (!unfinishedIDs.contains(id)) {
+              tryIDResolution(id, pv, pvList);
+            }
         } else {
             pvList.add(pv);
         }
     }
+    
+    /**
+     * This method tie an ID to the areaTreeHandler until this one is
+     * ready to be processed. This is used in page-number-citation-last processing so we know
+     * when an id can be resolved.
+     * @param id the id of the object being processed
+     */
+    public void signalPendingID(String id) {
+        if (log.isDebugEnabled()) {
+            log.debug("signalPendingID(" + id + ")");
+        }
+        unfinishedIDs.add(id);
+    }
+    
+    /**
+     * Signals that all areas for the formatting object with the given ID have been generated.
+     * This is used to determine when page-number-citation-last ref-ids can be resolved.
+     * @param id the id of the formatting object which was just finished
+     */
+    public void signalIDProcessed(String id) {
+        if (log.isDebugEnabled()) {
+            log.debug("signalIDProcessed(" + id + ")");
+        }
+        
+        alreadyResolvedIDs.add(id);
+        if (!unfinishedIDs.contains(id)) {
+            return;
+        }
+        unfinishedIDs.remove(id);
+        
+        List pvList = (List) idLocations.get(id);
+        Set todo = (Set) unresolvedIDRefs.get(id);
+        if (todo != null) {
+            for (Iterator iter = todo.iterator(); iter.hasNext();) {
+                Resolvable res = (Resolvable) iter.next();
+                res.resolveIDRef(id, pvList);
+            }
+            unresolvedIDRefs.remove(id);
+        }
+    }
+    
+    /**
+     * Check if an ID has already been resolved
+     * @param id the id to check
+     * @return true if the ID has been resolved
+     */
+    public boolean alreadyResolvedID(String id) {
+        return (alreadyResolvedIDs.contains(id));
+    }
 
     /**
      * Tries to resolve all unresolved ID references on the given page.
@@ -197,8 +251,13 @@ public class AreaTreeHandler extends FOEventHandler {
         if (todo != null) {
             for (Iterator iter = todo.iterator(); iter.hasNext();) {
                 Resolvable res = (Resolvable) iter.next();
-                res.resolveIDRef(id, pvList);
+                if (!unfinishedIDs.contains(id)) {
+                    res.resolveIDRef(id, pvList);
+                } else {
+                    return;
+                }
             }
+            alreadyResolvedIDs.add(id);
             unresolvedIDRefs.remove(id);
         }
     }
index 99978e7c66e4053140b8148fab21f384a916e2f6..fc28bda49347c38f2815a5a0b167abffa3f8a358 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -34,20 +34,39 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable {
     private boolean resolved = false;
     private String pageIDRef;
     private String text;
+    private boolean pageType;
 
+    /** Indicates that the reference refers to the first area generated by a formatting object. */
+    public static final boolean FIRST = true;
+    /** Indicates that the reference refers to the last area generated by a formatting object. */
+    public static final boolean LAST = false;
+    
     //Transient fields
     private transient Font font;
     
     /**
-     * Create a new unresolvable page number.
+     * Create a new unresolved page number.
      *
      * @param id the id reference for resolving this
      * @param f  the font for formatting the page number
      */
     public UnresolvedPageNumber(String id, Font f) {
+        this(id, f, FIRST);
+    }
+    
+    /**
+     * Create a new unresolved page number.
+     *
+     * @param id   the id reference for resolving this
+     * @param f    the font for formatting the page number
+     * @param type indicates whether the reference refers to the first or last area generated by
+     *             a formatting object
+     */
+    public UnresolvedPageNumber(String id, Font f, boolean type) {
         pageIDRef = id;
         font = f;
         text = "?";
+        pageType = type;
     }
 
     /**
@@ -70,9 +89,17 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable {
      * @param pages the list of PageViewports associated with this ID
      */
     public void resolveIDRef(String id, List pages) {
+        if (log.isDebugEnabled()) {
+            log.debug("Resolving pageNumber: " + id);
+        }
         if (pageIDRef.equals(id) && pages != null) {
             resolved = true;
-            PageViewport page = (PageViewport)pages.get(0);
+            PageViewport page;
+            if (pageType == FIRST) {
+                page = (PageViewport)pages.get(0);
+            } else { 
+                page = (PageViewport)pages.get(pages.size() - 1);
+            }
             // replace the text
             removeText();
             addWord(page.getPageNumberString(), 0);
@@ -83,7 +110,7 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable {
                 font = null;
             } else {
                 log.warn("Cannot update the IPD of an unresolved page number."
-                        + " No font information avilable.");
+                        + " No font information available.");
             }
         }
     }
@@ -108,5 +135,4 @@ public class UnresolvedPageNumber extends TextArea implements Resolvable {
                                         int lineStretch, int lineShrink) {
         return true;
     }
-
 }
index 737d54854262909ca257d9aa7c21392d4963191e..b28a350fc9fcc4357d2065fda872bb094deae288 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 The Apache Software Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -156,8 +156,10 @@ public interface Constants {
     int FO_BOOKMARK_TITLE = 59;
     /** FO element constant - XSL 1.1 */
     int FO_PAGE_SEQUENCE_WRAPPER = 60;
+    /** FO element constant - XSL 1.1 */
+    int FO_PAGE_NUMBER_CITATION_LAST = 61;
     /** Number of FO element constants defined */
-    int FRM_OBJ_COUNT = 60;
+    int FRM_OBJ_COUNT = 61;
 
     // Masks
     /**
index bf376de2ac3d0f3c80748cd41018386b876b97ae..609cfcc34dab97ed65a502a7d7a868993acecf15 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -93,6 +93,8 @@ public class FOElementMapping extends ElementMapping {
             foObjs.put("page-number", new PageNumberMaker());
             foObjs.put("page-number-citation",
                            new PageNumberCitationMaker());
+            foObjs.put("page-number-citation-last",
+                    new PageNumberCitationLastMaker());
 
             // Formatting Objects for Tables
             foObjs.put("table-and-caption", new TableAndCaptionMaker());
@@ -343,6 +345,12 @@ public class FOElementMapping extends ElementMapping {
         }
     }
 
+    static class PageNumberCitationLastMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new org.apache.fop.fo.flow.PageNumberCitationLast(parent);
+        }
+    }
+    
     static class TableAndCaptionMaker extends ElementMapping.Maker {
         public FONode make(FONode parent) {
             return new org.apache.fop.fo.flow.TableAndCaption(parent);
index 549f03c5831b4dac6200fce65315b2bbaf4cbe27..af45735e68d8d7d5a407f7418e671295b50f447d 100644 (file)
@@ -378,6 +378,7 @@ public abstract class FObj extends FONode implements Constants {
                         || lName.equals("leader") 
                         || lName.equals("page-number") 
                         || lName.equals("page-number-citation")
+                        || lName.equals("page-number-citation-last")
                         || lName.equals("basic-link")
                         || (lName.equals("multi-toggle")
                                 && (getNameId() == FO_MULTI_CASE 
index 61bc15a08dfae2fe5040c1fc37dad957ce632c76..c0dbe4a19ef501679c64e6f8682549a353bbaf2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
 
 /* $Id$ */
 
-
 package org.apache.fop.fo;
 
 import org.apache.fop.fo.Constants;
@@ -28,7 +27,7 @@ public class PropertySets {
     private static BitSet can_have_markers = null;
     private static BitSet no_inline_areas = null;
 
-    private Element[] elements = new Element[Constants.FRM_OBJ_COUNT+1];
+    private Element[] elements = new Element[Constants.FRM_OBJ_COUNT + 1];
     private BitSet block_elems = new BitSet();
     private BitSet inline_elems = new BitSet();
 
@@ -58,6 +57,7 @@ public class PropertySets {
         inline_elems.set(Constants.FO_LEADER);
         inline_elems.set(Constants.FO_PAGE_NUMBER);
         inline_elems.set(Constants.FO_PAGE_NUMBER_CITATION);
+        inline_elems.set(Constants.FO_PAGE_NUMBER_CITATION_LAST);
         inline_elems.set(Constants.FO_BASIC_LINK);
         inline_elems.set(Constants.FO_MULTI_TOGGLE);
     }
@@ -679,6 +679,34 @@ public class PropertySets {
         elem.addProperty(Constants.PR_VISIBILITY);
         elem.addProperty(Constants.PR_WORD_SPACING);
         elem.addProperty(Constants.PR_WRAP_OPTION);
+        
+        elem = elements[Constants.FO_PAGE_NUMBER_CITATION_LAST];
+        elem.addProperties(CommonAccessibilityProperties);
+        elem.addProperties(CommonAuralProperties);
+        elem.addProperties(CommonBorderPaddingBackgroundProperties);
+        elem.addProperties(CommonFontProperties);
+        elem.addProperties(CommonMarginPropertiesInline);
+        elem.addProperties(CommonRelativePositionProperties);
+        elem.addProperty(Constants.PR_VERTICAL_ALIGN);
+        elem.addProperty(Constants.PR_ALIGNMENT_ADJUST);
+        elem.addProperty(Constants.PR_ALIGNMENT_BASELINE);
+        elem.addProperty(Constants.PR_BASELINE_SHIFT);
+        elem.addProperty(Constants.PR_DOMINANT_BASELINE);
+        elem.addProperty(Constants.PR_ID);
+        elem.addProperty(Constants.PR_KEEP_WITH_NEXT);
+        elem.addProperty(Constants.PR_KEEP_WITH_PREVIOUS);
+        elem.addProperty(Constants.PR_LETTER_SPACING);
+        elem.addProperty(Constants.PR_LINE_HEIGHT);
+        elem.addProperty(Constants.PR_REF_ID);
+        elem.addProperty(Constants.PR_SCORE_SPACES);
+        elem.addProperty(Constants.PR_TEXT_ALTITUDE);
+        elem.addProperty(Constants.PR_TEXT_DECORATION);
+        elem.addProperty(Constants.PR_TEXT_DEPTH);
+        elem.addProperty(Constants.PR_TEXT_SHADOW);
+        elem.addProperty(Constants.PR_TEXT_TRANSFORM);
+        elem.addProperty(Constants.PR_VISIBILITY);
+        elem.addProperty(Constants.PR_WORD_SPACING);
+        elem.addProperty(Constants.PR_WRAP_OPTION);
 
         elem = elements[Constants.FO_TABLE_AND_CAPTION];
         elem.addProperties(CommonAccessibilityProperties);
@@ -992,7 +1020,7 @@ public class PropertySets {
         elem.addProperty(Constants.PR_RETRIEVE_BOUNDARY);
 
         // Merge the attributes from the children into the parent.
-        for (boolean dirty = true; dirty; ) {
+        for (boolean dirty = true; dirty;) {
             dirty = false;
             for (int i = 1; i < elements.length; i++) {
                 dirty = dirty || elements[i].merge();
@@ -1009,9 +1037,9 @@ public class PropertySets {
      * on the array the number of set bits in the BitSet.
      */
     private static short[] makeSparseIndices(BitSet set) {
-        short[] indices = new short[Constants.PROPERTY_COUNT+1];
+        short[] indices = new short[Constants.PROPERTY_COUNT + 1];
         int j = 1;
-        for (int i = 0; i < Constants.PROPERTY_COUNT+1; i++) {
+        for (int i = 0; i < Constants.PROPERTY_COUNT + 1; i++) {
             if (set.get(i)) {
                 indices[i] = (short) j++;
             }
@@ -1022,7 +1050,7 @@ public class PropertySets {
 
     public static short[] getPropertySet(int elementId) {
         if (mapping == null) {
-            mapping = new short[Constants.FRM_OBJ_COUNT+1][];
+            mapping = new short[Constants.FRM_OBJ_COUNT + 1][];
             PropertySets ps = new PropertySets();
             ps.initializeElements();
             ps.initializeCommon();
diff --git a/src/java/org/apache/fop/fo/flow/PageNumberCitationLast.java b/src/java/org/apache/fop/fo/flow/PageNumberCitationLast.java
new file mode 100644 (file)
index 0000000..89817e4
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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$ */
+
+package org.apache.fop.fo.flow;
+
+import org.apache.fop.fo.FONode;
+
+/**
+ * Class modelling the fo:page-number-citation-last object from XSL 1.1.
+ * This inline fo is replaced with the text for a page number.
+ * The page number used is the page that contains the end of the
+ * block referenced with the ref-id attribute.
+ * @since XSL 1.1
+ */
+public class PageNumberCitationLast extends PageNumberCitation {
+
+    /**
+     * Main constructor
+     * @param parent the parent FO node
+     */
+    public PageNumberCitationLast(FONode parent) {
+        super(parent);
+    }
+    
+    /** @see org.apache.fop.fo.FONode#getLocalName() */
+    public String getLocalName() {
+        return "page-number-citation-last";
+    }
+    
+    /** @see org.apache.fop.fo.FObj#getNameId() */
+    public int getNameId() {
+        return FO_PAGE_NUMBER_CITATION_LAST;
+    }
+}
index 2c593fd029d8c82f6a5cc0735dff51c8b5629250..1af26cb4ddc21f2a28d12d9bec29e30e77af0f9b 100644 (file)
@@ -837,6 +837,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
         viewportBlockArea = null;
         referenceArea = null;
         resetSpaces();
+        
+        getPSLM().notifyEndOfLayout(((BlockContainer)getFObj()).getId());
     }
     
     /**
index a303f18fd62c84f3fa7c489b7b13c871ea453125..4e6d3750aaaef80796a9e951d7d1cf7ced21ac25 100644 (file)
@@ -395,6 +395,9 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
 
         curBlockArea = null;
         resetSpaces();
+        
+        // Notify end of block layout manager to the PSLM
+        getPSLM().notifyEndOfLayout(getBlockFO().getId());
     }
 
     /**
index 783c6a60428da339f9322e635870b5f67c418cfe..9a812e0162db632eb34d7dd6f81fb180c25844d5 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 /* $Id$ */
+
 package org.apache.fop.layoutmgr;
 
 import java.util.ArrayList;
@@ -45,6 +46,7 @@ import org.apache.fop.fo.flow.ListBlock;
 import org.apache.fop.fo.flow.ListItem;
 import org.apache.fop.fo.flow.PageNumber;
 import org.apache.fop.fo.flow.PageNumberCitation;
+import org.apache.fop.fo.flow.PageNumberCitationLast;
 import org.apache.fop.fo.flow.RetrieveMarker;
 import org.apache.fop.fo.flow.Table;
 import org.apache.fop.fo.flow.TableBody;
@@ -73,6 +75,7 @@ import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager;
 import org.apache.fop.layoutmgr.inline.InstreamForeignObjectLM;
 import org.apache.fop.layoutmgr.inline.LeaderLayoutManager;
 import org.apache.fop.layoutmgr.inline.PageNumberCitationLayoutManager;
+import org.apache.fop.layoutmgr.inline.PageNumberCitationLastLayoutManager;
 import org.apache.fop.layoutmgr.inline.PageNumberLayoutManager;
 import org.apache.fop.layoutmgr.inline.TextLayoutManager;
 import org.apache.fop.layoutmgr.inline.WrapperLayoutManager;
@@ -123,6 +126,8 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
         makers.put(PageNumber.class, new PageNumberLayoutManagerMaker());
         makers.put(PageNumberCitation.class,
                    new PageNumberCitationLayoutManagerMaker());
+        makers.put(PageNumberCitationLast.class,
+                new PageNumberCitationLastLayoutManagerMaker());
         makers.put(Table.class, new TableLayoutManagerMaker());
         makers.put(TableBody.class, new Maker());
         makers.put(TableColumn.class, new Maker());
@@ -349,6 +354,12 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
          }
     }
 
+    public static class PageNumberCitationLastLayoutManagerMaker extends Maker {
+        public void make(FONode node, List lms) {
+           lms.add(new PageNumberCitationLastLayoutManager((PageNumberCitationLast) node));
+        }
+    }
+    
     public static class TableLayoutManagerMaker extends Maker {
         public void make(FONode node, List lms) {
             Table table = (Table) node;
index a410e1838cf10bab252c762e409c51fc6cc9a092..9c1693a59446886aa6df4f5755a469091f8b8e11 100644 (file)
@@ -142,7 +142,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
 
         curPage = makeNewPage(false, false);
 
-        addIDToPage(pageSeq.getId());
+        
         Flow mainFlow = pageSeq.getMainFlow();
         childFLM = getLayoutManagerMaker().
             makeFlowLayoutManager(this, mainFlow);
@@ -158,6 +158,10 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
      * Finished the page-sequence and notifies everyone about it.
      */
     public void finishPageSequence() {
+        if (!pageSeq.getId().equals("")) {
+            areaTreeHandler.signalIDProcessed(pageSeq.getId());
+        }
+
         pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum,
                 (currentPageNum - startPageNum) + 1);
         areaTreeHandler.notifyPageSequenceFinished(pageSeq,
@@ -165,6 +169,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
         log.debug("Ending layout");
     }
 
+
     private class PageBreaker extends AbstractBreaker {
         
         private PageSequenceLayoutManager pslm;
@@ -562,6 +567,21 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
         return null;
     }
 
+    /**
+     * This returns the last PageViewport that contains an id trait
+     * matching the idref argument, or null if no such PV exists.
+     *
+     * @param idref the idref trait needing to be resolved 
+     * @return the last PageViewport that contains the ID trait
+     */
+    public PageViewport getLastPVWithID(String idref) {
+        List list = areaTreeHandler.getPageViewportsContainingID(idref);
+        if (list != null && list.size() > 0) {
+            return (PageViewport) list.get(list.size() - 1);
+        }
+        return null;
+    }
+    
     /**
      * Add an ID reference to the current page.
      * When adding areas the area adds its ID reference.
@@ -575,7 +595,35 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
             areaTreeHandler.associateIDWithPageViewport(id, curPage.getPageViewport());
         }
     }
-
+    
+    /**
+     * Add an id reference of the layout manager in the AreaTreeHandler,
+     * if the id hasn't been resolved yet
+     * @param id the id to track
+     * @return a boolean indicating if the id has already been resolved
+     * TODO Maybe give this a better name
+     */
+    public boolean associateLayoutManagerID(String id) {
+        if (log.isDebugEnabled()) {
+            log.debug("associateLayoutManagerID(" + id + ")");
+        }
+        if (!areaTreeHandler.alreadyResolvedID(id)) {
+            areaTreeHandler.signalPendingID(id);
+            return false;
+        } else {
+            return true;
+        }
+    }
+    
+    /**
+     * Notify the areaTreeHandler that the LayoutManagers containing
+     * idrefs have finished creating areas
+     * @param id the id for which layout has finished
+     */
+    public void notifyEndOfLayout(String id) {
+        areaTreeHandler.signalIDProcessed(id);
+    }
+    
     /**
      * Identify an unresolved area (one needing an idref to be 
      * resolved, e.g. the internal-destination of an fo:basic-link)
@@ -669,6 +717,8 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager {
             log.debug("[" + curPage.getPageViewport().getPageNumberString() 
                     + (bIsBlank ? "*" : "") + "]");
         }
+        
+        addIDToPage(pageSeq.getId());
         return curPage;
     }
 
diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java
new file mode 100644 (file)
index 0000000..f55c00f
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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$ */
+
+package org.apache.fop.layoutmgr.inline;
+
+import org.apache.fop.fo.flow.PageNumberCitationLast;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.area.Resolvable;
+import org.apache.fop.area.inline.InlineArea;
+import org.apache.fop.area.inline.UnresolvedPageNumber;
+import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.layoutmgr.LayoutContext;
+import org.apache.fop.layoutmgr.LayoutManager;
+
+/**
+ * LayoutManager for the fo:page-number-citation-last formatting object
+ */
+public class PageNumberCitationLastLayoutManager extends PageNumberCitationLayoutManager {
+
+    private PageNumberCitationLast fobj;
+    
+    /**
+     * Constructor
+     *
+     * @param node the formatting object that creates this area
+     * @todo better retrieval of font info
+     */
+    public PageNumberCitationLastLayoutManager(PageNumberCitationLast node) {
+        super(node);
+        fobj = node;
+    }
+    
+    /** @see org.apache.fop.layoutmgr.inline.LeafNodeLayoutManager#get(LayoutContext) */
+    public InlineArea get(LayoutContext context) {
+        curArea = getPageNumberCitationLastInlineArea(parentLM);
+        return curArea;
+    }
+    
+    /**
+     * if id can be resolved then simply return a word, otherwise
+     * return a resolvable area
+     */
+    private InlineArea getPageNumberCitationLastInlineArea(LayoutManager parentLM) {
+        TextArea text = null;
+        resolved = false;
+        if (!getPSLM().associateLayoutManagerID(fobj.getRefId())) {
+            text = new UnresolvedPageNumber(fobj.getRefId(), font, UnresolvedPageNumber.LAST);
+            getPSLM().addUnresolvedArea(fobj.getRefId(), (Resolvable)text);
+            String str = "MMM"; // reserve three spaces for page number
+            int width = getStringWidth(str);
+            text.setIPD(width);
+        } else {
+            PageViewport page = getPSLM().getLastPVWithID(fobj.getRefId());
+            String str = page.getPageNumberString();
+            // get page string from parent, build area
+            text = new TextArea();
+            int width = getStringWidth(str);
+            text.addWord(str, 0);
+            text.setIPD(width);
+            
+            resolved = true;
+        }
+        
+        updateTextAreaTraits(text);
+        
+        return text;
+    }
+}
index 79c2d487dadd4aad8c0c2debcd107ca999db4de5..729e9c939a8d4962e64224205ff5ce79fa3ce9d9 100644 (file)
@@ -37,10 +37,11 @@ import org.apache.fop.layoutmgr.TraitSetter;
 public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager {
 
     private PageNumberCitation fobj;
-    private Font font;
+    /** Font for the page-number-citation */
+    protected Font font;
     
-    // whether the page referred to by the citation has been resolved yet
-    private boolean resolved = false;
+    /** Indicates whether the page referred to by the citation has been resolved yet */
+    protected boolean resolved = false;
     
     /**
      * Constructor
@@ -97,40 +98,45 @@ public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager {
      */
     private InlineArea getPageNumberCitationInlineArea(LayoutManager parentLM) {
         PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId());
-        TextArea inline = null;
+        TextArea text = null;
         if (page != null) {
             String str = page.getPageNumberString();
             // get page string from parent, build area
-            TextArea text = new TextArea();
-            inline = text;
+            text = new TextArea();
             int width = getStringWidth(str);
             text.addWord(str, 0);
-            inline.setIPD(width);
-            
+            text.setIPD(width);
             resolved = true;
         } else {
             resolved = false;
-            inline = new UnresolvedPageNumber(fobj.getRefId(), font);
+            text = new UnresolvedPageNumber(fobj.getRefId(), font);
             String str = "MMM"; // reserve three spaces for page number
             int width = getStringWidth(str);
-            inline.setIPD(width);
-            
+            text.setIPD(width);
         }
-        TraitSetter.setProducerID(inline, fobj.getId());
-        inline.setBPD(font.getAscender() - font.getDescender());
-        inline.setBaselineOffset(font.getAscender());
-        TraitSetter.addFontTraits(inline, font);
-        inline.addTrait(Trait.COLOR, fobj.getColor());
-        TraitSetter.addTextDecoration(inline, fobj.getTextDecoration());
+        updateTextAreaTraits(text);
         
-        return inline;
+        return text;
+    }
+    
+    /**
+     * Updates the traits for the generated text area. 
+     * @param text the text area
+     */
+    protected void updateTextAreaTraits(TextArea text) {
+        TraitSetter.setProducerID(text, fobj.getId());
+        text.setBPD(font.getAscender() - font.getDescender());
+        text.setBaselineOffset(font.getAscender());
+        TraitSetter.addFontTraits(text, font);
+        text.addTrait(Trait.COLOR, fobj.getColor());
+        TraitSetter.addTextDecoration(text, fobj.getTextDecoration());
     }
     
     /**
      * @param str string to be measured
      * @return width (in millipoints ??) of the string
      */
-    private int getStringWidth(String str) {
+    protected int getStringWidth(String str) {
         int width = 0;
         for (int count = 0; count < str.length(); count++) {
             width += font.getCharWidth(str.charAt(count));
index e23639e0d97900ba357d97829092550612b8f95d..5704ae99d973a20e88cf814faaf89bce03232d72 100644 (file)
@@ -207,6 +207,8 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
 
         curBlockArea = null;
         resetSpaces();
+        
+        getPSLM().notifyEndOfLayout(((ListBlock)getFObj()).getId());
     }
 
     /**
index 23ba4dd52df836f6bb8fc1a6e43139a80ff41bec..d894a0aeb5aeb363a4b3139ec658112b96065850 100644 (file)
@@ -171,6 +171,8 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager {
         flush();
 
         curBlockArea = null;
+        
+        getPSLM().notifyEndOfLayout(((AbstractListItemPart)getFObj()).getId());
     }
 
     /**
index d9bbd18f61545454ae29c68d224696878c78f794..7f3794bb6dbad1d24b626d7cd931ba8bcc066fa1 100644 (file)
@@ -535,6 +535,8 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
 
         curBlockArea = null;
         resetSpaces();
+        
+        getPSLM().notifyEndOfLayout(((ListItem)getFObj()).getId());
     }
 
     /**
index 8ec1b8e16c2c22484358fc208a57398918f340bc..61d2d37013d0bdc48104518deb18d0bbafadbf25 100644 (file)
@@ -252,6 +252,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
         //Space resolution
         SpaceResolver.resolveElementList(returnList);
         
+        getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId());
+        
         setFinished(true);
         return returnList;
     }
index 83ac2a937f21a3713c4d86e7bbaa92da2e90fdf9..a50cf1317166d4809291989d32badcc657d4c5d8 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.fop.layoutmgr.table;
 
 import org.apache.fop.datatypes.Length;
 import org.apache.fop.fo.flow.Table;
+import org.apache.fop.fo.flow.TableFObj;
 import org.apache.fop.fo.flow.TableColumn;
 import org.apache.fop.fo.properties.TableColLength;
 import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
@@ -376,6 +377,8 @@ public class TableLayoutManager extends BlockStackingLayoutManager
 
         resetSpaces();
         curBlockArea = null;
+        
+        getPSLM().notifyEndOfLayout(((Table)getFObj()).getId());
     }
 
     /**
index 65e38f0513a9b39292b0013334bd295c9ab768db..329c808dad44591f7c6c32d1dd2e8f6770659f91 100644 (file)
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Code" dev="JM" type="add" fixes-bug="39118" due-to="Pierre-Henri Kraus">
+        Initial support for page-number-citation-last (XSL 1.1). Works without problems 
+        only for page-sequence so far.
+      </action>
     </release>
     <release version="0.92beta" date="18 Apr 2006">
       <action context="Code" dev="JM" type="fix">
index 84f8bc5cdcf7bfeb5fc96c7929c9c746a264daf2..03fd4e64c1c22522c033b73c0d41dab1901b9866 100644 (file)
     <file>page-number-citation_forward-ref.xml</file>
     <description>Forward references are not properly adjusted when they are resolved.</description>
   </testcase>
+  <testcase>
+    <name>page-number-citation-last: FOs spanning multiple pages are not properly handled.</name>
+    <file>page-number-citation-last_basic.xml</file>
+    <description>Resolution of forward references does not wait until an FO is fully finished when an FO spans multiple pages.</description>
+  </testcase>
   <testcase>
     <name>IDs are not working on all FO elements</name>
     <file>page-number-citation_complex_1.xml</file>
diff --git a/test/layoutengine/standard-testcases/page-number-citation-last_basic.xml b/test/layoutengine/standard-testcases/page-number-citation-last_basic.xml
new file mode 100644 (file)
index 0000000..b038aae
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright 2006 The Apache Software Foundation
+
+  Licensed 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 fo:page-number-citation-last.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="master1" page-width="5in" page-height="1in">
+          <fo:region-body/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="master1" id="ps1" white-space-collapse="true" force-page-count="no-force">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block>page: <fo:page-number/> of <fo:page-number-citation-last ref-id="eof1"/></fo:block>
+          <fo:block>bof3's last area is on page <fo:page-number-citation-last ref-id="long-block"/></fo:block>
+          <fo:block linefeed-treatment="preserve" id="long-block">test
+          test
+          test
+          test
+          test
+          test
+          test
+          </fo:block>
+          <fo:block break-before="page">page: <fo:page-number/></fo:block>
+          <fo:block>bof3's last area is on page <fo:page-number-citation-last ref-id="long-block"/></fo:block>
+          <fo:block>page eof1: <fo:page-number/> of <fo:page-number-citation-last ref-id="eof1"/></fo:block>
+          <fo:block>page eof2: <fo:page-number/> of <fo:page-number-citation-last ref-id="eof2"/></fo:block>
+          <fo:block id="eof1"/>
+        </fo:flow>
+      </fo:page-sequence>
+      <fo:page-sequence master-reference="master1" id="ps2" white-space-collapse="true" initial-page-number="11" force-page-count="no-force">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block>page: <fo:page-number/> of <fo:page-number-citation-last ref-id="eof2"/></fo:block>
+          <fo:block>bof3's last area is on page <fo:page-number-citation-last ref-id="long-block"/></fo:block>
+          <fo:block break-before="page">page: <fo:page-number/></fo:block>
+          <fo:block break-before="page">page: <fo:page-number/></fo:block>
+          <fo:block>page eof1: <fo:page-number/> of <fo:page-number-citation-last ref-id="eof1"/></fo:block>
+          <fo:block>page eof2: <fo:page-number/> of <fo:page-number-citation-last ref-id="eof2"/></fo:block>
+          <fo:block id="eof2"/>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="2" xpath="count(//pageSequence)"/>
+    <eval expected="3" xpath="count(//pageSequence[1]/pageViewport)"/>
+    <eval expected="3" xpath="count(//pageSequence[2]/pageViewport)"/>
+    <eval expected="page: 1 of 3" xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea"/>
+    <eval expected="bof3's last area is on page 2" xpath="//pageViewport[@nr=1]//flow/block[2]/lineArea"/>
+    <eval expected="test" xpath="//pageViewport[@nr=1]//flow/block[3]/lineArea[1]"/>
+    <eval expected="test" xpath="//pageViewport[@nr=1]//flow/block[3]/lineArea[2]"/>
+    <eval expected="test" xpath="//pageViewport[@nr=1]//flow/block[3]/lineArea[3]"/>
+
+    <eval expected="test" xpath="//pageViewport[@nr=2]//flow/block[1]/lineArea[1]"/>
+    <eval expected="test" xpath="//pageViewport[@nr=2]//flow/block[1]/lineArea[2]"/>
+    <eval expected="test" xpath="//pageViewport[@nr=2]//flow/block[1]/lineArea[3]"/>
+    <eval expected="test" xpath="//pageViewport[@nr=2]//flow/block[1]/lineArea[4]"/>
+    
+    <eval expected="page: 3" xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea"/>
+    <eval expected="bof3's last area is on page 2" xpath="//pageViewport[@nr=3]//flow/block[2]/lineArea"/>
+    <eval expected="page eof1: 3 of 3" xpath="//pageViewport[@nr=3]//flow/block[3]/lineArea"/>
+    <eval expected="page eof2: 3 of 13" xpath="//pageViewport[@nr=3]//flow/block[4]/lineArea"/>
+
+    <eval expected="page: 11 of 13" xpath="//pageViewport[@nr=11]//flow/block[1]/lineArea"/>
+    <eval expected="bof3's last area is on page 2" xpath="//pageViewport[@nr=11]//flow/block[2]/lineArea"/>
+
+    <eval expected="page: 12" xpath="//pageViewport[@nr=12]//flow/block[1]/lineArea"/>
+
+    <eval expected="page: 13" xpath="//pageViewport[@nr=13]//flow/block[1]/lineArea"/>
+    <eval expected="page eof1: 13 of 3" xpath="//pageViewport[@nr=13]//flow/block[2]/lineArea"/>
+    <eval expected="page eof2: 13 of 13" xpath="//pageViewport[@nr=13]//flow/block[3]/lineArea"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-number-citation-last_complex.xml b/test/layoutengine/standard-testcases/page-number-citation-last_complex.xml
new file mode 100644 (file)
index 0000000..39cf3b3
--- /dev/null
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright 2005 The Apache Software Foundation
+
+  Licensed 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 page-number-citations with all combinations of 
+      definition-level and block-level IDs.
+    </p>
+    <p>
+      TODO:
+      Test table-and-caption and table-caption once implemented.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in" 
+              margin="20pt">
+          <fo:region-body background-color="yellow"/>
+        </fo:simple-page-master>
+      </fo:layout-master-set>
+      <fo:page-sequence id="page-sequence1" master-reference="normal" white-space-collapse="true">
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block id="block1">block1</fo:block>
+          <fo:list-block id="list1" provisional-distance-between-starts="50pt" provisional-label-separation="5pt">
+            <fo:list-item id="item1">
+              <fo:list-item-label id="item1-label" end-indent="label-end()">
+                <fo:block>•</fo:block>
+              </fo:list-item-label>
+              <fo:list-item-body id="item1-body" start-indent="body-start()">
+                <fo:block>here is text in the list item body</fo:block>
+              </fo:list-item-body>
+            </fo:list-item>
+          </fo:list-block>
+          <fo:table id="table1" table-layout="fixed" border-collapse="separate">
+            <fo:table-column column-width="100%"/>
+            <fo:table-header id="table-header1">
+              <fo:table-row>
+                <fo:table-cell>
+                  <fo:block>header</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-header>
+            <fo:table-footer id="table-footer1">
+              <fo:table-row>
+                <fo:table-cell>
+                  <fo:block>footer</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-footer>
+            <fo:table-body id="table-body1">
+              <fo:table-row id="table-row1">
+                <fo:table-cell id="table-cell1">
+                  <fo:block>body-content</fo:block>
+                </fo:table-cell>
+              </fo:table-row>
+            </fo:table-body>
+          </fo:table>
+          <fo:block-container id="block-container1">
+            <fo:block>block-container-content</fo:block>
+          </fo:block-container>
+        </fo:flow>
+      </fo:page-sequence>
+      <fo:page-sequence master-reference="normal">
+        <fo:flow flow-name="xsl-region-body" font-size="8pt">
+          <fo:block>page-sequence= <fo:page-number-citation-last ref-id="page-sequence1"/></fo:block>
+          <fo:block>block= <fo:page-number-citation-last ref-id="block1"/></fo:block>
+          <fo:block>list= <fo:page-number-citation-last ref-id="list1"/></fo:block>
+          <fo:block>item= <fo:page-number-citation-last ref-id="item1"/></fo:block>
+          <fo:block>item-label= <fo:page-number-citation-last ref-id="item1-label"/></fo:block>
+          <fo:block>item-body= <fo:page-number-citation-last ref-id="item1-body"/></fo:block>
+          <fo:block>table= <fo:page-number-citation-last ref-id="table1"/></fo:block>
+          <fo:block>table-header= <fo:page-number-citation-last ref-id="table-header1"/></fo:block>
+          <fo:block>table-footer= <fo:page-number-citation-last ref-id="table-footer1"/></fo:block>
+          <fo:block>table-body= <fo:page-number-citation-last ref-id="table-body1"/></fo:block>
+          <fo:block>table-row= <fo:page-number-citation-last ref-id="table-row1"/></fo:block>
+          <fo:block>table-cell= <fo:page-number-citation-last ref-id="table-cell1"/></fo:block>
+          <fo:block>block-container= <fo:page-number-citation-last ref-id="block-container1"/></fo:block>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <true fail-msg="no ID for page-sequence" xpath="'page-sequence= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[1]"/>
+    <true fail-msg="no ID for block" xpath="'block= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[2]"/>
+    <true fail-msg="no ID for list-block" xpath="'list= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[3]"/>
+    <true fail-msg="no ID for list-item" xpath="'item= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[4]"/>
+    <true fail-msg="no ID for list-item-label" xpath="'item-label= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[5]"/>
+    <true fail-msg="no ID for list-item-body" xpath="'item-body= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[6]"/>
+    <true fail-msg="no ID for table" xpath="'table= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[7]"/>
+   <!-- <true fail-msg="no ID for table-header" xpath="'table-header= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[8]"/>
+    <true fail-msg="no ID for table-footer" xpath="'table-footer= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[9]"/>
+    <true fail-msg="no ID for table-body" xpath="'table-body= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[10]"/>
+    <true fail-msg="no ID for table-row" xpath="'table-row= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[11]"/>-->
+    <true fail-msg="no ID for table-cell" xpath="'table-cell= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[12]"/>
+    <true fail-msg="no ID for block-container" xpath="'block-container= 1' = //pageViewport[@nr=2]/page/regionViewport/regionBody/mainReference/span/flow/block[13]"/>
+  </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-number-citation-last_page-sequence.xml b/test/layoutengine/standard-testcases/page-number-citation-last_page-sequence.xml
new file mode 100644 (file)
index 0000000..51fc27f
--- /dev/null
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright 2006 The Apache Software Foundation
+
+  Licensed 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 fo:page-number-citation-last associated to a page-sequence id.
+    </p>
+  </info>
+  <fo>
+    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
+      <fo:layout-master-set>
+        <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
+          <fo:region-body margin-bottom="1in" column-count="2" column-gap="10pt" background-color="lightgray"/>
+          <fo:region-after extent="1in" display-align="after"/>
+        </fo:simple-page-master>
+        <fo:simple-page-master master-name="last" page-width="5in" page-height="5in">
+          <fo:region-body margin-bottom="3in" column-count="2" column-gap="10pt" background-color="rgb(250,250,240)"/>
+          <fo:region-after extent="1in" display-align="after"/>
+        </fo:simple-page-master>
+        <fo:page-sequence-master master-name="master">
+          <fo:repeatable-page-master-alternatives>
+            <fo:conditional-page-master-reference master-reference="last" page-position="last"/>
+            <fo:conditional-page-master-reference master-reference="normal" page-position="any"/>
+          </fo:repeatable-page-master-alternatives>
+        </fo:page-sequence-master>
+      </fo:layout-master-set>
+      <fo:page-sequence master-reference="master" id="replace-last">
+        <fo:static-content flow-name="xsl-region-after">
+          <fo:block text-align="end">page <fo:page-number/> of <fo:page-number-citation-last ref-id="replace-last"/></fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block-container id="boxA0" height="1.5in" background-color="yellow" text-align="center" display-align="center" break-after="page">
+            <fo:block>box0</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA1" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box1</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA2" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box2</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA3" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box3</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA4" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box4</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA5" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box5</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA6" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box6</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA7" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box7</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA8" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box8</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA9" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box9</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxA10" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box10</fo:block>
+          </fo:block-container>
+          <fo:block id="eof"/>
+        </fo:flow>
+      </fo:page-sequence>
+      <fo:page-sequence master-reference="master" id="blank-last">
+        <fo:static-content flow-name="xsl-region-after">
+          <fo:block text-align="end">page <fo:page-number/> of <fo:page-number-citation-last ref-id="blank-last"/></fo:block>
+        </fo:static-content>
+        <fo:flow flow-name="xsl-region-body">
+          <fo:block-container id="boxB1" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box1</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB2" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box2</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB3" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box3</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB4" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box4</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB5" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box5</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB6" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box6</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB7" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box7</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB8" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box8</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB9" height="1.5in" background-color="yellow" text-align="center" display-align="center">
+            <fo:block>box9</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB10" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box10</fo:block>
+          </fo:block-container>
+          <fo:block-container id="boxB11" height="1.5in" background-color="orange" text-align="center" display-align="center">
+            <fo:block>box11</fo:block>
+          </fo:block-container>
+        </fo:flow>
+      </fo:page-sequence>
+    </fo:root>
+  </fo>
+  <checks>
+    <eval expected="2" xpath="count(//pageSequence)"/>
+    <eval expected="4" xpath="count(//pageSequence[1]/pageViewport)"/>
+    <eval expected="4" xpath="count(//pageSequence[2]/pageViewport)"/>
+    
+    <eval expected="page 1 of 4" xpath="//pageSequence[1]/pageViewport[@nr=1]/page/regionViewport[1]/regionAfter/block[2]/lineArea"/>
+    <eval expected="page 2 of 4" xpath="//pageSequence[1]/pageViewport[@nr=2]/page/regionViewport[1]/regionAfter/block[2]/lineArea"/>
+    <eval expected="page 3 of 4" xpath="//pageSequence[1]/pageViewport[@nr=3]/page/regionViewport[1]/regionAfter/block[2]/lineArea"/>
+    <eval expected="page 4 of 4" xpath="//pageSequence[1]/pageViewport[@nr=4]/page/regionViewport[1]/regionAfter/block[2]/lineArea"/>
+    
+    <eval expected="page 5 of 8" xpath="//pageSequence[2]/pageViewport[@nr=5]/page/regionViewport[1]/regionAfter/block[2]/lineArea"/>
+    <eval expected="page 6 of 8" xpath="//pageSequence[2]/pageViewport[@nr=6]/page/regionViewport[1]/regionAfter/block[2]/lineArea"/>
+    <eval expected="page 7 of 8" xpath="//pageSequence[2]/pageViewport[@nr=7]/page/regionViewport[1]/regionAfter/block[2]/lineArea"/>
+    <eval expected="page 8 of 8" xpath="//pageSequence[2]/pageViewport[@nr=8]/page/regionViewport[1]/regionAfter/block[2]/lineArea"/>
+  </checks>
+</testcase>
index bb83c28086e0b910ee3b2a43dc3c80189187eab7..793ff851d26dc78b754a860cd62d760b9c71af3b 100644 (file)
@@ -41,7 +41,7 @@
       </fo:layout-master-set>
       <fo:page-sequence master-reference="master" id="replace-last">
         <fo:static-content flow-name="xsl-region-after">
-          <fo:block text-align="end">page <fo:page-number/> of <fo:page-number-citation ref-id="eof"/></fo:block>
+          <fo:block text-align="end">page <fo:page-number/> of <fo:page-number-citation-last ref-id="replace-last"/></fo:block>
         </fo:static-content>
         <fo:flow flow-name="xsl-region-body">
           <fo:block-container id="boxA0" height="1.5in" background-color="yellow" text-align="center" display-align="center" break-after="page">
@@ -82,7 +82,7 @@
       </fo:page-sequence>
       <fo:page-sequence master-reference="master" id="blank-last">
         <fo:static-content flow-name="xsl-region-after">
-          <fo:block text-align="end">page <fo:page-number/> of <fo:page-number-citation ref-id="eof"/></fo:block>
+          <fo:block text-align="end">page <fo:page-number/> of <fo:page-number-citation-last ref-id="blank-last"/></fo:block>
         </fo:static-content>
         <fo:flow flow-name="xsl-region-body">
           <fo:block-container id="boxB1" height="1.5in" background-color="yellow" text-align="center" display-align="center">