// 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();
* 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.
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);
}
}
/*
- * 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.
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;
}
/**
* @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);
font = null;
} else {
log.warn("Cannot update the IPD of an unresolved page number."
- + " No font information avilable.");
+ + " No font information available.");
}
}
}
int lineStretch, int lineShrink) {
return true;
}
-
}
/*
- * 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.
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
/**
/*
- * 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.
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());
}
}
+ 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);
|| 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
/*
- * 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.
/* $Id$ */
-
package org.apache.fop.fo;
import org.apache.fop.fo.Constants;
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();
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);
}
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);
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();
* 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++;
}
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();
--- /dev/null
+/*
+ * 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;
+ }
+}
viewportBlockArea = null;
referenceArea = null;
resetSpaces();
+
+ getPSLM().notifyEndOfLayout(((BlockContainer)getFObj()).getId());
}
/**
curBlockArea = null;
resetSpaces();
+
+ // Notify end of block layout manager to the PSLM
+ getPSLM().notifyEndOfLayout(getBlockFO().getId());
}
/**
*/
/* $Id$ */
+
package org.apache.fop.layoutmgr;
import java.util.ArrayList;
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;
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;
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());
}
}
+ 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;
curPage = makeNewPage(false, false);
- addIDToPage(pageSeq.getId());
+
Flow mainFlow = pageSeq.getMainFlow();
childFLM = getLayoutManagerMaker().
makeFlowLayoutManager(this, mainFlow);
* 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,
log.debug("Ending layout");
}
+
private class PageBreaker extends AbstractBreaker {
private PageSequenceLayoutManager pslm;
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.
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)
log.debug("[" + curPage.getPageViewport().getPageNumberString()
+ (bIsBlank ? "*" : "") + "]");
}
+
+ addIDToPage(pageSeq.getId());
return curPage;
}
--- /dev/null
+/*
+ * 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;
+ }
+}
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
*/
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));
curBlockArea = null;
resetSpaces();
+
+ getPSLM().notifyEndOfLayout(((ListBlock)getFObj()).getId());
}
/**
flush();
curBlockArea = null;
+
+ getPSLM().notifyEndOfLayout(((AbstractListItemPart)getFObj()).getId());
}
/**
curBlockArea = null;
resetSpaces();
+
+ getPSLM().notifyEndOfLayout(((ListItem)getFObj()).getId());
}
/**
//Space resolution
SpaceResolver.resolveElementList(returnList);
+ getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId());
+
setFinished(true);
return returnList;
}
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;
resetSpaces();
curBlockArea = null;
+
+ getPSLM().notifyEndOfLayout(((Table)getFObj()).getId());
}
/**
<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">
<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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
</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">
</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">