// Java
import java.io.OutputStream;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.HashSet;
import java.util.Iterator;
// XML
* type of renderer.
*/
public class AreaTreeHandler extends FOEventHandler {
+
+ private static Log log = LogFactory.getLog(AreaTreeHandler.class);
- /** debug statistics */
+ // Recorder of debug statistics
private Statistics statistics = null;
- private static Log log = LogFactory.getLog(AreaTreeHandler.class);
-
- // the LayoutManager maker
+ // The LayoutManager maker
private LayoutManagerMaker lmMaker;
- /** AreaTreeModel in use */
+ /** The AreaTreeModel in use */
protected AreaTreeModel model;
+ // Keeps track of all meaningful id references
+ private IDTracker idTracker;
+
// The fo:root node of the document
private Root rootFObj;
-
- // HashMap of ID's whose area is located on one or more consecutive
- // PageViewports. Each ID has an arraylist of PageViewports that
- // form the defined area of this ID
- private Map idLocations = new HashMap();
-
- // 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();
lmMaker = new LayoutManagerMapping();
}
+ idTracker = new IDTracker();
+
if (log.isDebugEnabled()) {
statistics = new Statistics();
}
}
/**
- * Tie a PageViewport with an ID found on a child area of the PV. Note that
- * an area with a given ID may be on more than one PV, hence an ID may have
- * more than one PV associated with it.
+ * Get the IDTracker for this area tree.
*
- * @param id the property ID of the area
- * @param pv a page viewport that contains the area with this ID
+ * @return IDTracker used to track reference ids for items in this area tree
*/
- public void associateIDWithPageViewport(String id, PageViewport pv) {
- if (log.isDebugEnabled()) {
- log.debug("associateIDWithPageViewport(" + id + ", " + pv + ")");
- }
- List pvList = (List) idLocations.get(id);
- if (pvList == null) { // first time ID located
- pvList = new ArrayList();
- idLocations.put(id, pvList);
- pvList.add(pv);
- // signal the PageViewport that it is the first PV to contain this id:
- pv.setFirstWithID(id);
- /*
- * See if this ID is in the unresolved idref list, if so resolve
- * Resolvable objects tied to it.
- */
- 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.
- *
- * @param id ID to resolve
- * @param pv page viewport whose ID refs to resolve
- * @param List of PageViewports
- */
- private void tryIDResolution(String id, PageViewport pv, List pvList) {
- Set todo = (Set) unresolvedIDRefs.get(id);
- if (todo != null) {
- for (Iterator iter = todo.iterator(); iter.hasNext();) {
- Resolvable res = (Resolvable) iter.next();
- if (!unfinishedIDs.contains(id)) {
- res.resolveIDRef(id, pvList);
- } else {
- return;
- }
- }
- alreadyResolvedIDs.add(id);
- unresolvedIDRefs.remove(id);
- }
- }
-
- /**
- * Tries to resolve all unresolved ID references on the given page.
- *
- * @param pv page viewport whose ID refs to resolve
- */
- public void tryIDResolution(PageViewport pv) {
- String[] ids = pv.getIDRefs();
- if (ids != null) {
- for (int i = 0; i < ids.length; i++) {
- List pvList = (List) idLocations.get(ids[i]);
- if (pvList != null) {
- tryIDResolution(ids[i], pv, pvList);
- }
- }
- }
- }
-
- /**
- * Get the list of page viewports that have an area with a given id.
- *
- * @param id the id to lookup
- * @return the list of PageViewports
- */
- public List getPageViewportsContainingID(String id) {
- return (List) idLocations.get(id);
+ public IDTracker getIDTracker() {
+ return idTracker;
}
/**
return this.results;
}
- /**
- * Add an Resolvable object with an unresolved idref
- *
- * @param idref the idref whose target id has not yet been located
- * @param res the Resolvable object needing the idref to be resolved
- */
- public void addUnresolvedIDRef(String idref, Resolvable res) {
- Set todo = (Set) unresolvedIDRefs.get(idref);
- if (todo == null) {
- todo = new HashSet();
- unresolvedIDRefs.put(idref, todo);
- }
- // add Resolvable object to this HashSet
- todo.add(res);
- }
-
/**
* Prepare AreaTreeHandler for document processing This is called from
* FOTreeBuilder.startDocument()
Resolvable res = (Resolvable) odi;
String[] ids = res.getIDRefs();
for (int count = 0; count < ids.length; count++) {
- if (idLocations.containsKey(ids[count])) {
- res.resolveIDRef(ids[count], (List) idLocations.get(ids[count]));
+ List pageVPList = idTracker.getPageViewportsContainingID(ids[count]);
+ if (pageVPList != null) {
+ res.resolveIDRef(ids[count], pageVPList);
} else {
log.warn(odi.getName() + ": Unresolved id reference \""
+ ids[count] + "\" found.");
- addUnresolvedIDRef(ids[count], res);
+ idTracker.addUnresolvedIDRef(ids[count], res);
}
}
// check to see if ODI is now fully resolved, if so process it
}
/**
- * Gather statistics when log is debug
+ * Tie a PageViewport with an ID found on a child area of the PV. Note that
+ * an area with a given ID may be on more than one PV, hence an ID may have
+ * more than one PV associated with it.
+ *
+ * @param id the property ID of the area
+ * @param pv a page viewport that contains the area with this ID
+ * @deprecated use getIdTracker().associateIDWithPageViewport(id, pv) instead
+ */
+ public void associateIDWithPageViewport(String id, PageViewport pv) {
+ idTracker.associateIDWithPageViewport(id, 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
+ * @deprecated use getIdTracker().signalPendingID(id) instead
+ */
+ public void signalPendingID(String id) {
+ idTracker.signalPendingID(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
+ * @deprecated use getIdTracker().signalIDProcessed(id) instead
+ */
+ public void signalIDProcessed(String id) {
+ idTracker.signalIDProcessed(id);
+ }
+
+ /**
+ * Check if an ID has already been resolved
+ *
+ * @param id the id to check
+ * @return true if the ID has been resolved
+ * @deprecated use getIdTracker().alreadyResolvedID(id) instead
+ */
+ public boolean alreadyResolvedID(String id) {
+ return idTracker.alreadyResolvedID(id);
+ }
+
+ /**
+ * Tries to resolve all unresolved ID references on the given page.
+ *
+ * @param pv page viewport whose ID refs to resolve
+ * @deprecated use getIdTracker().tryIDResolution(pv) instead
+ */
+ public void tryIDResolution(PageViewport pv) {
+ idTracker.tryIDResolution(pv);
+ }
+
+ /**
+ * Get the list of page viewports that have an area with a given id.
+ *
+ * @param id the id to lookup
+ * @return the list of PageViewports
+ * @deprecated use getIdTracker().getPageViewportsContainingID(id) instead
+ */
+ public List getPageViewportsContainingID(String id) {
+ return idTracker.getPageViewportsContainingID(id);
+ }
+
+ /**
+ * Add an Resolvable object with an unresolved idref
+ *
+ * @param idref the idref whose target id has not yet been located
+ * @param res the Resolvable object needing the idref to be resolved
+ * @deprecated use getIdTracker().addUnresolvedIDRef(idref, res) instead
*/
- private final class Statistics {
+ public void addUnresolvedIDRef(String idref, Resolvable res) {
+ idTracker.addUnresolvedIDRef(idref, res);
+ }
+
+ private class Statistics {
// for statistics gathering
private Runtime runtime;
// time used in rendering (for statistics)
private long startTime;
- private Statistics() {
- runtime = Runtime.getRuntime();
+ /**
+ * Default constructor
+ * @param areaTreeHandler area tree handler
+ */
+ protected Statistics() {
+ this.runtime = Runtime.getRuntime();
}
- public void start() {
- initialMemory = runtime.totalMemory() - runtime.freeMemory();
- startTime = System.currentTimeMillis();
+ /**
+ * starts the area tree handler statistics gathering
+ */
+ protected void start() {
+ this.initialMemory = runtime.totalMemory() - runtime.freeMemory();
+ this.startTime = System.currentTimeMillis();
}
- public void end() {
+ /**
+ * ends the area tree handler statistics gathering
+ */
+ protected void end() {
long memoryNow = runtime.totalMemory() - runtime.freeMemory();
log.debug("Current heap size: " + (memoryNow / 1024L) + "KB");
}
- public void logResults() {
+ /**
+ * logs the results of the area tree handler statistics gathering
+ */
+ protected void logResults() {
long memoryNow = runtime.totalMemory() - runtime.freeMemory();
long memoryUsed = (memoryNow - initialMemory) / 1024L;
long timeUsed = System.currentTimeMillis() - startTime;
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.area;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Used by the AreaTreeHandler to keep track of ID reference usage
+ * on a PageViewport level.
+ */
+public class IDTracker {
+
+ private static Log log = LogFactory.getLog(IDTracker.class);
+
+ // HashMap of ID's whose area is located on one or more consecutive
+ // PageViewports. Each ID has an arraylist of PageViewports that
+ // form the defined area of this ID
+ private Map idLocations = new HashMap();
+
+ // 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();
+
+ /**
+ * Tie a PageViewport with an ID found on a child area of the PV. Note that
+ * an area with a given ID may be on more than one PV, hence an ID may have
+ * more than one PV associated with it.
+ *
+ * @param id the property ID of the area
+ * @param pv a page viewport that contains the area with this ID
+ */
+ public void associateIDWithPageViewport(String id, PageViewport pv) {
+ if (log.isDebugEnabled()) {
+ log.debug("associateIDWithPageViewport(" + id + ", " + pv + ")");
+ }
+ List pvList = (List) idLocations.get(id);
+ if (pvList == null) { // first time ID located
+ pvList = new ArrayList();
+ idLocations.put(id, pvList);
+ pvList.add(pv);
+ // signal the PageViewport that it is the first PV to contain this id:
+ pv.setFirstWithID(id);
+ /*
+ * See if this ID is in the unresolved idref list, if so resolve
+ * Resolvable objects tied to it.
+ */
+ 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.
+ *
+ * @param id ID to resolve
+ * @param pv page viewport whose ID refs to resolve
+ * @param List of PageViewports
+ */
+ private void tryIDResolution(String id, PageViewport pv, List pvList) {
+ Set todo = (Set) unresolvedIDRefs.get(id);
+ if (todo != null) {
+ for (Iterator iter = todo.iterator(); iter.hasNext();) {
+ Resolvable res = (Resolvable) iter.next();
+ if (!unfinishedIDs.contains(id)) {
+ res.resolveIDRef(id, pvList);
+ } else {
+ return;
+ }
+ }
+ alreadyResolvedIDs.add(id);
+ unresolvedIDRefs.remove(id);
+ }
+ }
+
+ /**
+ * Tries to resolve all unresolved ID references on the given page.
+ *
+ * @param pv page viewport whose ID refs to resolve
+ */
+ public void tryIDResolution(PageViewport pv) {
+ String[] ids = pv.getIDRefs();
+ if (ids != null) {
+ for (int i = 0; i < ids.length; i++) {
+ List pvList = (List) idLocations.get(ids[i]);
+ if (pvList != null) {
+ tryIDResolution(ids[i], pv, pvList);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the list of page viewports that have an area with a given id.
+ *
+ * @param id the id to lookup
+ * @return the list of PageViewports
+ */
+ public List getPageViewportsContainingID(String id) {
+ return (List) idLocations.get(id);
+ }
+
+ /**
+ * Add an Resolvable object with an unresolved idref
+ *
+ * @param idref the idref whose target id has not yet been located
+ * @param res the Resolvable object needing the idref to be resolved
+ */
+ public void addUnresolvedIDRef(String idref, Resolvable res) {
+ Set todo = (Set) unresolvedIDRefs.get(idref);
+ if (todo == null) {
+ todo = new HashSet();
+ unresolvedIDRefs.put(idref, todo);
+ }
+ // add Resolvable object to this HashSet
+ todo.add(res);
+ }
+}
/**
* Check prepared pages
*
- * @param newpage the new page being added
+ * @param newPageViewport the new page being added
* @param renderUnresolved render pages with unresolved idref's
* (done at end-of-document processing)
* @return true if the current page should be rendered
* false if the renderer doesn't support out of order
* rendering and there are pending pages
*/
- protected boolean checkPreparedPages(PageViewport newpage, boolean
+ protected boolean checkPreparedPages(PageViewport newPageViewport, boolean
renderUnresolved) {
for (Iterator iter = prepared.iterator(); iter.hasNext();) {
- PageViewport p = (PageViewport)iter.next();
- if (p.isResolved() || renderUnresolved) {
- if (!renderer.supportsOutOfOrder() && p.getPageSequence().isFirstPage(p)) {
+ PageViewport pageViewport = (PageViewport)iter.next();
+ if (pageViewport.isResolved() || renderUnresolved) {
+ if (!renderer.supportsOutOfOrder()
+ && pageViewport.getPageSequence().isFirstPage(pageViewport)) {
renderer.startPageSequence(this.currentPageSequence.getTitle());
}
try {
- renderer.renderPage(p);
- if (!p.isResolved()) {
- String[] idrefs = p.getIDRefs();
+ renderer.renderPage(pageViewport);
+ if (!pageViewport.isResolved()) {
+ String[] idrefs = pageViewport.getIDRefs();
for (int count = 0; count < idrefs.length; count++) {
- log.warn("Page " + p.getPageNumberString()
+ log.warn("Page " + pageViewport.getPageNumberString()
+ ": Unresolved id reference \"" + idrefs[count]
+ "\" found.");
}
// use error handler to handle this FOP or IO Exception
log.error(e);
}
- p.clear();
+ pageViewport.clear();
iter.remove();
} else {
// if keeping order then stop at first page not resolved
/** Markers added to this element. */
private Map markers = null;
+ // The value of properties relevant for all fo objects
+ private String id = null;
+ // End of property values
+
/**
* Create a new formatting object.
* All formatting object classes extend this class.
* @throws FOPException if there is a problem binding the values
*/
public void bind(PropertyList pList) throws FOPException {
+ id = pList.get(PR_ID).getString();
+ }
+
+ /**
+ * @see org.apache.fop.fo.FONode#startOfNode
+ * @throws FOPException FOP Exception
+ */
+ protected void startOfNode() throws FOPException {
+ if (id != null) {
+ checkId(id);
+ }
}
/**
* @throws ValidationException if the ID is already defined elsewhere
* (strict validation only)
*/
- protected void checkId(String id) throws ValidationException {
+ private void checkId(String id) throws ValidationException {
if (!inMarker() && !id.equals("")) {
Set idrefs = getFOEventHandler().getIDReferences();
if (!idrefs.contains(id)) {
protected void addChildNode(FONode child) throws FOPException {
if (canHaveMarkers() && child.getNameId() == FO_MARKER) {
addMarker((Marker) child);
- } else {
+ } else {
ExtensionAttachment attachment = child.getExtensionAttachment();
if (attachment != null) {
/* This removes the element from the normal children,
return -1;
}
+ /** @return the "id" property. */
+ public String getId() {
+ return id;
+ }
+ /** @return whether this object has an id set */
+ public boolean hasId() {
+ return id != null && id.length() > 0;
+ }
+
/** @see org.apache.fop.fo.FONode#getNamespaceURI() */
public String getNamespaceURI() {
return FOElementMapping.URI;
*/
public abstract class AbstractListItemPart extends FObj {
// The value of properties relevant for fo:list-item-label and fo:list-item-body.
- private String id;
private KeepProperty keepTogether;
// Valid properties, commented out for performance:
// private CommonAccessibility commonAccessibility;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
- id = pList.get(PR_ID).getString();
+ super.bind(pList);
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
* XSL Content Model: marker* (%block;)+
public KeepProperty getKeepTogether() {
return keepTogether;
}
-
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
}
return externalDestination;
}
+ /**
+ * @return whether or not this basic link has an internal destination or not
+ */
+ public boolean hasInternalDestination() {
+ return internalDestination != null && internalDestination.length() > 0;
+ }
+
+ /**
+ * @return whether or not this basic link has an external destination or not
+ */
+ public boolean hasExternalDestination() {
+ return externalDestination != null && externalDestination.length() > 0;
+ }
+
/** @see org.apache.fop.fo.FObj#getLocalName() */
public String getLocalName() {
return "basic-link";
import org.apache.fop.fo.NullCharIterator;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
-import org.apache.fop.fo.properties.CommonAccessibility;
-import org.apache.fop.fo.properties.CommonAural;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonFont;
import org.apache.fop.fo.properties.CommonHyphenation;
private boolean initialPropertySetFound = false;
// The value of properties relevant for fo:block.
- private CommonAccessibility commonAccessibility;
- private CommonAural commonAural;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
private CommonFont commonFont;
private CommonHyphenation commonHyphenation;
private Color color;
private int hyphenationKeep;
private Numeric hyphenationLadderCount;
- private String id;
private int intrusionDisplace;
private KeepProperty keepTogether;
private KeepProperty keepWithNext;
private Numeric widows;
private int wrapOption;
// Unused but valid items, commented out for performance:
+ // private CommonAccessibility commonAccessibility;
+ // private CommonAural commonAural;
// private Length textDepth;
// private Length textAltitude;
// private int visibility;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
- commonAccessibility = pList.getAccessibilityProps();
- commonAural = pList.getAuralProps();
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonFont = pList.getFontProps();
commonHyphenation = pList.getHyphenationProps();
color = pList.get(PR_COLOR).getColor(getUserAgent());
hyphenationKeep = pList.get(PR_HYPHENATION_KEEP).getEnum();
hyphenationLadderCount = pList.get(PR_HYPHENATION_LADDER_COUNT).getNumeric();
- id = pList.get(PR_ID).getString();
intrusionDisplace = pList.get(PR_INTRUSION_DISPLACE).getEnum();
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().startBlock(this);
}
return color;
}
- /**
- * @return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/**
* @return the "line-height" property.
*/
return whiteSpaceCollapse;
}
- /**
- * @return Returns the commonAccessibility.
- */
- public CommonAccessibility getCommonAccessibility() {
- return this.commonAccessibility;
- }
-
- /**
- * @return Returns the commonAural.
- */
- public CommonAural getCommonAural() {
- return this.commonAural;
- }
-
/**
* @return Returns the commonRelativePosition.
*/
// private ToBeImplementedProperty clip;
private int displayAlign;
private Length height;
- private String id;
private LengthRangeProperty inlineProgressionDimension;
private KeepProperty keepTogether;
private KeepProperty keepWithNext;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonAbsolutePosition = pList.getAbsolutePositionProps();
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginBlock = pList.getMarginBlockProps();
// clip = pList.get(PR_CLIP);
displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum();
height = pList.get(PR_HEIGHT).getLength();
- id = pList.get(PR_ID).getString();
inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().startBlockContainer(this);
}
return keepTogether;
}
- /**
- * @return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/**
* @return the "inline-progression-dimension" property.
*/
private int dominantBaseline;
// private ToBeImplementedProperty glyphOrientationHorizontal;
// private ToBeImplementedProperty glyphOrientationVertical;
- private String id;
private Property letterSpacing;
private SpaceProperty lineHeight;
/** Holds the text decoration values. May be null */
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonFont = pList.getFontProps();
commonHyphenation = pList.getHyphenationProps();
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
// glyphOrientationHorizontal = pList.get(PR_GLYPH_ORIENTATION_HORIZONTAL);
// glyphOrientationVertical = pList.get(PR_GLYPH_ORIENTATION_VERTICAL);
- id = pList.get(PR_ID).getString();
letterSpacing = pList.get(PR_LETTER_SPACING);
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
textDecoration = pList.getTextDecorationProps();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().character(this);
}
return dominantBaseline;
}
- /**
- * @return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/**
* @return the "letter-spacing" property.
*/
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(getId());
+ super.startOfNode();
getFOEventHandler().image(this);
}
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
- id = pList.get(PR_ID).getString();
+ super.bind(pList);
// letterSpacing = pList.get(PR_LETTER_SPACING);
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
// textShadow = pList.get(PR_TEXT_SHADOW);
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
* XSL Content Model: empty
private int alignmentBaseline;
private Length baselineShift;
private int dominantBaseline;
- private String id;
// Unused but valid items, commented out for performance:
// private CommonRelativePosition commonRelativePosition;
// private LengthRangeProperty blockProgressionDimension;
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
- id = pList.get(PR_ID).getString();
}
/**
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
+ super.startOfNode();
+
/* Check to see if this node can have block-level children.
* See validateChildNode() below.
*/
}
}
- checkId(id);
-
- getFOEventHandler().startInline(this);
+ getFOEventHandler().startInline(this);
}
/**
}
}
- /**
- * Return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/**
* @return the "alignment-adjust" property
*/
private Length baselineShift;
// private ToBeImplementedProperty clip;
private int dominantBaseline;
- private String id;
private SpaceProperty lineHeight;
// Unused but valid items, commented out for performance:
// private CommonBorderPaddingBackground commonBorderPaddingBackground;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
// clip = pList.get(PR_CLIP);
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
- id = pList.get(PR_ID).getString();
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
* XSL Content Model: marker* (%block;)+
return lineHeight;
}
- /**
- * @return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return "inline-container";
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonAccessibility = pList.getAccessibilityProps();
commonMarginInline = pList.getMarginInlineProps();
super(parent);
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(getId());
- }
-
/**
* Make sure content model satisfied, if so then tell the
* FOEventHandler that we are at the end of the flow.
private int alignmentBaseline;
private Length baselineShift;
private int dominantBaseline;
- private String id;
private int leaderAlignment;
private LengthRangeProperty leaderLength;
private int leaderPattern;
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
- id = pList.get(PR_ID).getString();
leaderAlignment = pList.get(PR_LEADER_ALIGNMENT).getEnum();
leaderLength = pList.get(PR_LEADER_LENGTH).getLengthRange();
leaderPattern = pList.get(PR_LEADER_PATTERN).getEnum();
// textShadow = pList.get(PR_TEXT_SHADOW);
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
-
- /**
- * @return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/**
* @return the "rule-style" property.
*/
private CommonMarginBlock commonMarginBlock;
private int breakAfter;
private int breakBefore;
- private String id;
private KeepProperty keepTogether;
private KeepProperty keepWithNext;
private KeepProperty keepWithPrevious;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginBlock = pList.getMarginBlockProps();
breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
breakBefore = pList.get(PR_BREAK_BEFORE).getEnum();
- id = pList.get(PR_ID).getString();
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().startList(this);
}
return orphanContentLimit;
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return "list-block";
private CommonMarginBlock commonMarginBlock;
private int breakAfter;
private int breakBefore;
- private String id;
private KeepProperty keepTogether;
private KeepProperty keepWithNext;
private KeepProperty keepWithPrevious;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginBlock = pList.getMarginBlockProps();
breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
breakBefore = pList.get(PR_BREAK_BEFORE).getEnum();
- id = pList.get(PR_ID).getString();
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
keepWithPrevious = pList.get(PR_KEEP_WITH_PREVIOUS).getKeep();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().startListItem(this);
}
return keepTogether;
}
- /**
- * @return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/**
* @return the label of the list item
*/
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
- id = pList.get(PR_ID).getString();
+ super.bind(pList);
startingState = pList.get(PR_STARTING_STATE).getEnum();
// caseName = pList.get(PR_CASE_NAME);
// caseTitle = pList.get(PR_CASE_TITLE);
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* Return the "starting-state" property.
*/
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
-import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.CommonAccessibility;
*/
public class MultiProperties extends FObj {
// The value of properties relevant for fo:multi-properties.
- private String id;
// Unused but valid items, commented out for performance:
// private CommonAccessibility commonAccessibility;
// End of property values
}
}
- /**
- * @see org.apache.fop.fo.FObj#bind(PropertyList)
- */
- public void bind(PropertyList pList) throws FOPException {
- id = pList.get(PR_ID).getString();
- }
-
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* Make sure content model satisfied, if so then tell the
* FOEventHandler that we are at the end of the flow.
invalidChildError(loc, nsURI, localName);
}
}
-
- /**
- * Return the "id" property.
- */
- public String getId() {
- return id;
- }
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
*/
public class MultiPropertySet extends FObj {
// The value of properties relevant for fo:multi-property-set.
- private String id;
// private ToBeImplementedProperty activeState;
// End of property values
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
- id = pList.get(PR_ID).getString();
+ super.bind(pList);
// activeState = pList.get(PR_ACTIVE_STATE);
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
* XSL Content Model: empty
invalidChildError(loc, nsURI, localName);
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return "multi-property-set";
public class MultiSwitch extends FObj {
// The value of properties relevant for fo:multi-switch.
// private ToBeImplementedProperty autoRestore;
- private String id;
// Unused but valid items, commented out for performance:
// private CommonAccessibility commonAccessibility;
// End of property values
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
// autoRestore = pList.get(PR_AUTO_RESTORE);
- id = pList.get(PR_ID).getString();
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
/**
* Make sure content model satisfied.
}
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return "multi-switch";
private int alignmentBaseline;
private Length baselineShift;
private int dominantBaseline;
- private String id;
// private ToBeImplementedProperty letterSpacing;
private SpaceProperty lineHeight;
/** Holds the text decoration values. May be null */
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonFont = pList.getFontProps();
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
- id = pList.get(PR_ID).getString();
// letterSpacing = pList.get(PR_LETTER_SPACING);
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
textDecoration = pList.getTextDecorationProps();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().startPageNumber(this);
}
return commonBorderPaddingBackground;
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @return the "text-decoration" property. */
public CommonTextDecoration getTextDecoration() {
return textDecoration;
private int alignmentBaseline;
private Length baselineShift;
private int dominantBaseline;
- private String id;
// private ToBeImplementedProperty letterSpacing;
private SpaceProperty lineHeight;
private String refId;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonFont = pList.getFontProps();
alignmentAdjust = pList.get(PR_ALIGNMENT_ADJUST).getLength();
alignmentBaseline = pList.get(PR_ALIGNMENT_BASELINE).getEnum();
baselineShift = pList.get(PR_BASELINE_SHIFT).getLength();
dominantBaseline = pList.get(PR_DOMINANT_BASELINE).getEnum();
- id = pList.get(PR_ID).getString();
// letterSpacing = pList.get(PR_LETTER_SPACING);
lineHeight = pList.get(PR_LINE_HEIGHT).getSpace();
refId = pList.get(PR_REF_ID).getString();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
if (refId.equals("")) {
missingPropertyError("ref-id");
}
return lineHeight;
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @return the "ref-id" property. */
public String getRefId() {
return refId;
private LengthPairProperty borderSeparation;
private int breakAfter;
private int breakBefore;
- private String id;
private LengthRangeProperty inlineProgressionDimension;
private KeepProperty keepTogether;
private KeepProperty keepWithNext;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
commonMarginBlock = pList.getMarginBlockProps();
blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
borderSeparation = pList.get(PR_BORDER_SEPARATION).getLengthPair();
breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
breakBefore = pList.get(PR_BREAK_BEFORE).getEnum();
- id = pList.get(PR_ID).getString();
inlineProgressionDimension = pList.get(PR_INLINE_PROGRESSION_DIMENSION).getLengthRange();
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
tableLayout = pList.get(PR_TABLE_LAYOUT).getEnum();
tableOmitFooterAtBreak = pList.get(PR_TABLE_OMIT_FOOTER_AT_BREAK).getEnum();
tableOmitHeaderAtBreak = pList.get(PR_TABLE_OMIT_HEADER_AT_BREAK).getEnum();
- super.bind(pList);
//Bind extension properties
widowContentLimit = pList.get(PR_X_WIDOW_CONTENT_LIMIT).getLength();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().startTable(this);
}
return orphanContentLimit;
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return "table";
*/
public class TableAndCaption extends FObj {
// The value of properties relevant for fo:table-and-caption.
- private String id;
// Unused but valid items, commented out for performance:
// private CommonAccessibility commonAccessibility;
// private CommonAural commonAural;
}
}
- /**
- * @see org.apache.fop.fo.FObj#bind(PropertyList)
- */
- public void bind(PropertyList pList) throws FOPException {
- id = pList.get(PR_ID).getString();
- }
-
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* Make sure content model satisfied, if so then tell the
* FOEventHandler that we are at the end of the flow.
}
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return "table-and-caption";
// The value of properties relevant for fo:table-caption.
private CommonAccessibility commonAccessibility;
private CommonBorderPaddingBackground commonBorderPaddingBackground;
- private String id;
// Unused but valid items, commented out for performance:
// private CommonAural commonAural;
// private CommonRelativePosition commonRelativePosition;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonAccessibility = pList.getAccessibilityProps();
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
- id = pList.get(PR_ID).getString();
- }
-
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
}
/**
}
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return "table-caption";
private int displayAlign;
private int emptyCells;
private int endsRow;
- private String id;
private int numberColumnsSpanned;
private int numberRowsSpanned;
private int startsRow;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
blockProgressionDimension = pList.get(PR_BLOCK_PROGRESSION_DIMENSION).getLengthRange();
displayAlign = pList.get(PR_DISPLAY_ALIGN).getEnum();
emptyCells = pList.get(PR_EMPTY_CELLS).getEnum();
endsRow = pList.get(PR_ENDS_ROW).getEnum();
- id = pList.get(PR_ID).getString();
columnNumber = pList.get(PR_COLUMN_NUMBER).getNumeric().getValue();
numberColumnsSpanned = pList.get(PR_NUMBER_COLUMNS_SPANNED).getNumeric().getValue();
numberRowsSpanned = pList.get(PR_NUMBER_ROWS_SPANNED).getNumeric().getValue();
startsRow = pList.get(PR_STARTS_ROW).getEnum();
- width = pList.get(PR_WIDTH).getLength();
-
- super.bind(pList);
+ width = pList.get(PR_WIDTH).getLength();
}
/**
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().startCell(this);
}
return (this.emptyCells == EN_SHOW);
}
- /**
- * @return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/**
* @return the "number-columns-spanned" property.
*/
* @see FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric();
borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric();
borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric();
private int breakAfter;
private int breakBefore;
private Length height;
- private String id;
private KeepProperty keepTogether;
private KeepProperty keepWithNext;
private KeepProperty keepWithPrevious;
commonBorderPaddingBackground = pList.getBorderPaddingBackgroundProps();
breakAfter = pList.get(PR_BREAK_AFTER).getEnum();
breakBefore = pList.get(PR_BREAK_BEFORE).getEnum();
- id = pList.get(PR_ID).getString();
height = pList.get(PR_HEIGHT).getLength();
keepTogether = pList.get(PR_KEEP_TOGETHER).getKeep();
keepWithNext = pList.get(PR_KEEP_WITH_NEXT).getKeep();
* @see org.apache.fop.fo.FONode#startOfNode
*/
protected void startOfNode() throws FOPException {
- checkId(id);
+ super.startOfNode();
getFOEventHandler().startRow(this);
}
}
}
- /**
- * @return the "id" property.
- */
- public String getId() {
- return id;
- }
-
/** @return the "break-after" property. */
public int getBreakAfter() {
return breakAfter;
*/
public class Wrapper extends FObjMixed {
// The value of properties relevant for fo:wrapper.
- private String id;
// End of property values
// used for FO validation
super(parent);
}
- /**
- * @see org.apache.fop.fo.FObj#bind(PropertyList)
- */
- public void bind(PropertyList pList) throws FOPException {
- id = pList.get(PR_ID).getString();
- }
-
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
* XSL Content Model: marker* (#PCDATA|%inline;|%block;)*
}
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return "wrapper";
private int letterValue;
private char groupingSeparator;
private int groupingSize;
- private String id;
private Numeric initialPageNumber;
private int forcePageCount;
private String masterReference;
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
+ super.bind(pList);
country = pList.get(PR_COUNTRY).getString();
format = pList.get(PR_FORMAT).getString();
language = pList.get(PR_LANGUAGE).getString();
letterValue = pList.get(PR_LETTER_VALUE).getEnum();
groupingSeparator = pList.get(PR_GROUPING_SEPARATOR).getCharacter();
groupingSize = pList.get(PR_GROUPING_SIZE).getNumber().intValue();
- id = pList.get(PR_ID).getString();
initialPageNumber = pList.get(PR_INITIAL_PAGE_NUMBER).getNumeric();
forcePageCount = pList.get(PR_FORCE_PAGE_COUNT).getEnum();
masterReference = pList.get(PR_MASTER_REFERENCE).getString();
* @see org.apache.fop.fo.FONode#startOfNode()
*/
protected void startOfNode() throws FOPException {
+ super.startOfNode();
this.root = (Root) parent;
flowMap = new java.util.HashMap();
this.pageNumberGenerator = new PageNumberGenerator(
format, groupingSeparator, groupingSize, letterValue);
- checkId(id);
getFOEventHandler().startPageSequence(this);
}
return (StaticContent) flowMap.get(name);
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/**
* Accessor method for titleFO
* @return titleFO for this object
*/
public class PageSequenceWrapper extends FObj {
// The value of properties relevant for this FO
- private String id;
private String indexClass;
private String indexKey;
// End of property values
* @see org.apache.fop.fo.FObj#bind(PropertyList)
*/
public void bind(PropertyList pList) throws FOPException {
- id = pList.get(PR_ID).getString();
+ super.bind(pList);
indexClass = pList.get(PR_INDEX_CLASS).getString();
indexKey = pList.get(PR_INDEX_KEY).getString();
}
- /**
- * @see org.apache.fop.fo.FONode#startOfNode
- */
- protected void startOfNode() throws FOPException {
- checkId(id);
- }
-
/**
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
XSL/FOP: (bookmark+)
}
}
- /** @return the "id" property. */
- public String getId() {
- return id;
- }
-
/** @return the "index-class" property. */
public String getIndexClass() {
return indexClass;
* algorithm.
* @return the applicable PageProvider, or null if not applicable
*/
- protected PageSequenceLayoutManager.PageProvider getPageProvider() {
+ protected PageProvider getPageProvider() {
return null;
}
/** @return true if there's no content that could be handled. */
public boolean isEmpty() {
- return (blockLists.size() == 0);
+ return (this.blockLists.size() == 0);
}
protected void startPart(BlockSequence list, int breakClass) {
childLC.setBPAlignment(alignment);
BlockSequence blockList;
- blockLists = new java.util.ArrayList();
+ this.blockLists = new java.util.ArrayList();
log.debug("PLM> flow BPD =" + flowBPD);
while (hasMoreContent()) {
blockLists.clear();
- nextSequenceStartsOn = getNextBlockList(childLC, nextSequenceStartsOn, blockLists);
+ nextSequenceStartsOn = getNextBlockList(childLC, nextSequenceStartsOn);
//*** Phase 2: Alignment and breaking ***
log.debug("PLM> blockLists.size() = " + blockLists.size());
* Gets the next block list (sequence) and adds it to a list of block lists if it's not empty.
* @param childLC LayoutContext to use
* @param nextSequenceStartsOn indicates on what page the next sequence should start
- * @param blockLists list of block lists (sequences)
* @return the page on which the next content should appear after a hard break
*/
protected int getNextBlockList(LayoutContext childLC,
- int nextSequenceStartsOn,
- List blockLists) {
+ int nextSequenceStartsOn) {
updateLayoutContext(childLC);
//Make sure the span change signal is reset
childLC.signalSpanChange(Constants.NOT_SET);
- LinkedList returnedList;
BlockSequence blockList;
- if ((returnedList = getNextKnuthElements(childLC, alignment)) != null) {
+ LinkedList returnedList = getNextKnuthElements(childLC, alignment);
+ if (returnedList != null) {
if (returnedList.size() == 0) {
nextSequenceStartsOn = handleSpanChange(childLC, nextSequenceStartsOn);
return nextSequenceStartsOn;
BlockSequence seq = null;
seq = blockList.endBlockSequence(breakPosition);
if (seq != null) {
- blockLists.add(seq);
+ this.blockLists.add(seq);
}
}
return nextSequenceStartsOn;
\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;\r
import org.apache.fop.traits.MinOptMax;\r
\r
/**\r
private int idealPartLen;\r
\r
public BalancingColumnBreakingAlgorithm(LayoutManager topLevelLM,\r
- PageSequenceLayoutManager.PageProvider pageProvider,\r
+ PageProvider pageProvider,
PageBreakingLayoutListener layoutListener,\r
int alignment, int alignmentLast,\r
MinOptMax footnoteSeparatorLength,\r
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.fop.area.Block;
+import org.apache.fop.area.Footnote;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Region;
+import org.apache.fop.fo.pagination.RegionBody;
+import org.apache.fop.fo.pagination.StaticContent;
+import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
+import org.apache.fop.traits.MinOptMax;
+
+/**
+ * Handles the breaking of pages in an fo:flow
+ */
+public class PageBreaker extends AbstractBreaker {
+
+ private PageSequenceLayoutManager pslm;
+ private boolean firstPart = true;
+ private boolean pageBreakHandled;
+ private boolean needColumnBalancing;
+ private PageProvider pageProvider;
+ private Block separatorArea;
+
+ /**
+ * The FlowLayoutManager object, which processes
+ * the single fo:flow of the fo:page-sequence
+ */
+ private FlowLayoutManager childFLM = null;
+
+ private StaticContentLayoutManager footnoteSeparatorLM = null;
+
+ public PageBreaker(PageSequenceLayoutManager pslm) {
+ this.pslm = pslm;
+ this.pageProvider = pslm.getPageProvider();
+ this.childFLM = pslm.getLayoutManagerMaker().makeFlowLayoutManager(
+ pslm, pslm.getPageSequence().getMainFlow());
+ }
+
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker */
+ protected void updateLayoutContext(LayoutContext context) {
+ int flowIPD = pslm.getCurrentPV().getCurrentSpan().getColumnWidth();
+ context.setRefIPD(flowIPD);
+ }
+
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker#getTopLevelLM() */
+ protected LayoutManager getTopLevelLM() {
+ return pslm;
+ }
+
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker#getPageProvider() */
+ protected PageProvider getPageProvider() {
+ return pslm.getPageProvider();
+ }
+
+ /**
+ * @see org.apache.fop.layoutmgr.AbstractBreaker#getLayoutListener()
+ */
+ protected PageBreakingLayoutListener getLayoutListener() {
+ return new PageBreakingLayoutListener() {
+
+ public void notifyOverflow(int part, FObj obj) {
+ Page p = pageProvider.getPage(
+ false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST);
+ RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion(
+ Region.FO_REGION_BODY);
+ String err = FONode.decorateWithContextInfo(
+ "Content of the region-body on page "
+ + p.getPageViewport().getPageNumberString()
+ + " overflows the available area in block-progression dimension.",
+ obj);
+ if (body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW) {
+ throw new RuntimeException(err);
+ } else {
+ log.warn(err);
+ }
+ }
+
+ };
+ }
+
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker */
+ protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
+ needColumnBalancing = false;
+ if (childLC.getNextSpan() != Constants.NOT_SET) {
+ //Next block list will have a different span.
+ nextSequenceStartsOn = childLC.getNextSpan();
+ needColumnBalancing = (childLC.getNextSpan() == Constants.EN_ALL);
+ }
+ if (needColumnBalancing) {
+ AbstractBreaker.log.debug(
+ "Column balancing necessary for the next element list!!!");
+ }
+ return nextSequenceStartsOn;
+ }
+
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker */
+ protected int getNextBlockList(LayoutContext childLC,
+ int nextSequenceStartsOn) {
+ if (!firstPart) {
+ // if this is the first page that will be created by
+ // the current BlockSequence, it could have a break
+ // condition that must be satisfied;
+ // otherwise, we may simply need a new page
+ handleBreakTrait(nextSequenceStartsOn);
+ }
+ firstPart = false;
+ pageBreakHandled = true;
+ pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
+ pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+ return super.getNextBlockList(childLC, nextSequenceStartsOn);
+ }
+
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker */
+ protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
+ LinkedList contentList = null;
+
+ while (!childFLM.isFinished() && contentList == null) {
+ contentList = childFLM.getNextKnuthElements(context, alignment);
+ }
+
+ // scan contentList, searching for footnotes
+ boolean bFootnotesPresent = false;
+ if (contentList != null) {
+ ListIterator contentListIterator = contentList.listIterator();
+ while (contentListIterator.hasNext()) {
+ ListElement element = (ListElement) contentListIterator.next();
+ if (element instanceof KnuthBlockBox
+ && ((KnuthBlockBox) element).hasAnchors()) {
+ // element represents a line with footnote citations
+ bFootnotesPresent = true;
+ LayoutContext footnoteContext = new LayoutContext(context);
+ footnoteContext.setStackLimit(context.getStackLimit());
+ footnoteContext.setRefIPD(pslm.getCurrentPV()
+ .getRegionReference(Constants.FO_REGION_BODY).getIPD());
+ LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs();
+ ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator();
+ // store the lists of elements representing the footnote bodies
+ // in the box representing the line containing their references
+ while (footnoteBodyIterator.hasNext()) {
+ FootnoteBodyLayoutManager fblm
+ = (FootnoteBodyLayoutManager) footnoteBodyIterator.next();
+ fblm.setParent(childFLM);
+ fblm.initialize();
+ ((KnuthBlockBox) element).addElementList(
+ fblm.getNextKnuthElements(footnoteContext, alignment));
+ }
+ }
+ }
+ }
+
+ if (bFootnotesPresent) {
+ // handle the footnote separator
+ StaticContent footnoteSeparator;
+ footnoteSeparator = pslm.getPageSequence().getStaticContent("xsl-footnote-separator");
+ if (footnoteSeparator != null) {
+ // the footnote separator can contain page-dependent content such as
+ // page numbers or retrieve markers, so its areas cannot simply be
+ // obtained now and repeated in each page;
+ // we need to know in advance the separator bpd: the actual separator
+ // could be different from page to page, but its bpd would likely be
+ // always the same
+
+ // create a Block area that will contain the separator areas
+ separatorArea = new Block();
+ separatorArea.setIPD(pslm.getCurrentPV()
+ .getRegionReference(Constants.FO_REGION_BODY).getIPD());
+ // create a StaticContentLM for the footnote separator
+ footnoteSeparatorLM = (StaticContentLayoutManager)
+ pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
+ pslm, footnoteSeparator, separatorArea);
+ footnoteSeparatorLM.doLayout();
+
+ footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
+ }
+ }
+ return contentList;
+ }
+
+ /**
+ * @return current display alignment
+ */
+ protected int getCurrentDisplayAlign() {
+ return pslm.getCurrentPage().getSimplePageMaster().getRegion(
+ Constants.FO_REGION_BODY).getDisplayAlign();
+ }
+
+ /**
+ * @return whether or not this flow has more page break opportunities
+ */
+ protected boolean hasMoreContent() {
+ return !childFLM.isFinished();
+ }
+
+ /**
+ * Adds an area to the flow layout manager
+ * @param posIter the position iterator
+ * @param context the layout context
+ */
+ protected void addAreas(PositionIterator posIter, LayoutContext context) {
+ if (footnoteSeparatorLM != null) {
+ StaticContent footnoteSeparator = pslm.getPageSequence().getStaticContent(
+ "xsl-footnote-separator");
+ // create a Block area that will contain the separator areas
+ separatorArea = new Block();
+ separatorArea.setIPD(
+ pslm.getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD());
+ // create a StaticContentLM for the footnote separator
+ footnoteSeparatorLM = (StaticContentLayoutManager)
+ pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
+ pslm, footnoteSeparator, separatorArea);
+ footnoteSeparatorLM.doLayout();
+ }
+
+ childFLM.addAreas(posIter, context);
+ }
+
+ /**
+ * Performs phase 3 operation
+ *
+ * @param alg page breaking algorithm
+ * @param partCount part count
+ * @param originalList the block sequence original list
+ * @param effectiveList the block sequence effective list
+ */
+ protected void doPhase3(PageBreakingAlgorithm alg, int partCount,
+ BlockSequence originalList, BlockSequence effectiveList) {
+ if (needColumnBalancing) {
+ doPhase3WithColumnBalancing(alg, partCount, originalList, effectiveList);
+ } else {
+ if (!hasMoreContent() && pslm.getPageSequence().hasPagePositionLast()) {
+ //last part is reached and we have a "last page" condition
+ doPhase3WithLastPage(alg, partCount, originalList, effectiveList);
+ } else {
+ //Directly add areas after finding the breaks
+ addAreas(alg, partCount, originalList, effectiveList);
+ }
+ }
+ }
+
+ private void doPhase3WithLastPage(PageBreakingAlgorithm alg, int partCount,
+ BlockSequence originalList, BlockSequence effectiveList) {
+ int newStartPos;
+ int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
+ if (restartPoint > 0) {
+ //Add definitive areas before last page
+ addAreas(alg, restartPoint, originalList, effectiveList);
+ //Get page break from which we restart
+ PageBreakPosition pbp = (PageBreakPosition)
+ alg.getPageBreaks().get(restartPoint - 1);
+ newStartPos = pbp.getLeafPos();
+ //Handle page break right here to avoid any side-effects
+ if (newStartPos > 0) {
+ handleBreakTrait(Constants.EN_PAGE);
+ }
+ } else {
+ newStartPos = 0;
+ }
+ AbstractBreaker.log.debug("Last page handling now!!!");
+ AbstractBreaker.log.debug("===================================================");
+ AbstractBreaker.log.debug("Restarting at " + restartPoint
+ + ", new start position: " + newStartPos);
+
+ pageBreakHandled = true;
+ //Update so the available BPD is reported correctly
+ int currentPageNum = pslm.getCurrentPageNum();
+ pageProvider.setStartOfNextElementList(currentPageNum,
+ pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+ pageProvider.setLastPageIndex(currentPageNum);
+
+ //Restart last page
+ PageBreakingAlgorithm algRestart = new PageBreakingAlgorithm(
+ getTopLevelLM(),
+ getPageProvider(), getLayoutListener(),
+ alg.getAlignment(), alg.getAlignmentLast(),
+ footnoteSeparatorLength,
+ isPartOverflowRecoveryActivated(), false, false);
+ //alg.setConstantLineWidth(flowBPD);
+ int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
+ newStartPos,
+ 1, true, BreakingAlgorithm.ALL_BREAKS);
+ AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
+ + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
+ boolean replaceLastPage
+ = iOptPageCount <= pslm.getCurrentPV().getBodyRegion().getColumnCount();
+ if (replaceLastPage) {
+ //Replace last page
+ pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
+ //Make sure we only add the areas we haven't added already
+ effectiveList.ignoreAtStart = newStartPos;
+ addAreas(algRestart, iOptPageCount, originalList, effectiveList);
+ } else {
+ effectiveList.ignoreAtStart = newStartPos;
+ addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
+ //Add blank last page
+ pageProvider.setLastPageIndex(currentPageNum + 1);
+ pslm.setCurrentPage(pslm.makeNewPage(true, true));
+ }
+ AbstractBreaker.log.debug("===================================================");
+ }
+
+ private void doPhase3WithColumnBalancing(PageBreakingAlgorithm alg, int partCount,
+ BlockSequence originalList, BlockSequence effectiveList) {
+ AbstractBreaker.log.debug("Column balancing now!!!");
+ AbstractBreaker.log.debug("===================================================");
+ int newStartPos;
+ int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
+ if (restartPoint > 0) {
+ //Add definitive areas
+ addAreas(alg, restartPoint, originalList, effectiveList);
+ //Get page break from which we restart
+ PageBreakPosition pbp = (PageBreakPosition)
+ alg.getPageBreaks().get(restartPoint - 1);
+ newStartPos = pbp.getLeafPos();
+ //Handle page break right here to avoid any side-effects
+ if (newStartPos > 0) {
+ handleBreakTrait(Constants.EN_PAGE);
+ }
+ } else {
+ newStartPos = 0;
+ }
+ AbstractBreaker.log.debug("Restarting at " + restartPoint
+ + ", new start position: " + newStartPos);
+
+ pageBreakHandled = true;
+ //Update so the available BPD is reported correctly
+ pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
+ pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+
+ //Restart last page
+ PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm(
+ getTopLevelLM(),
+ getPageProvider(), getLayoutListener(),
+ alignment, Constants.EN_START, footnoteSeparatorLength,
+ isPartOverflowRecoveryActivated(),
+ pslm.getCurrentPV().getBodyRegion().getColumnCount());
+ //alg.setConstantLineWidth(flowBPD);
+ int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
+ newStartPos,
+ 1, true, BreakingAlgorithm.ALL_BREAKS);
+ AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
+ + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
+ if (iOptPageCount > pslm.getCurrentPV().getBodyRegion().getColumnCount()) {
+ AbstractBreaker.log.warn(
+ "Breaking algorithm produced more columns than are available.");
+ /* reenable when everything works
+ throw new IllegalStateException(
+ "Breaking algorithm must not produce more columns than available.");
+ */
+ }
+ //Make sure we only add the areas we haven't added already
+ effectiveList.ignoreAtStart = newStartPos;
+ addAreas(algRestart, iOptPageCount, originalList, effectiveList);
+ AbstractBreaker.log.debug("===================================================");
+ }
+
+ protected void startPart(BlockSequence list, int breakClass) {
+ AbstractBreaker.log.debug("startPart() breakClass=" + breakClass);
+ if (pslm.getCurrentPage() == null) {
+ throw new IllegalStateException("curPage must not be null");
+ }
+ if (!pageBreakHandled) {
+
+ //firstPart is necessary because we need the first page before we start the
+ //algorithm so we have a BPD and IPD. This may subject to change later when we
+ //start handling more complex cases.
+ if (!firstPart) {
+ // if this is the first page that will be created by
+ // the current BlockSequence, it could have a break
+ // condition that must be satisfied;
+ // otherwise, we may simply need a new page
+ handleBreakTrait(breakClass);
+ }
+ pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
+ pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
+ }
+ pageBreakHandled = false;
+ // add static areas and resolve any new id areas
+ // finish page and add to area tree
+ firstPart = false;
+ }
+
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker#handleEmptyContent() */
+ protected void handleEmptyContent() {
+ pslm.getCurrentPV().getPage().fakeNonEmpty();
+ }
+
+ protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
+ // add footnote areas
+ if (pbp.footnoteFirstListIndex < pbp.footnoteLastListIndex
+ || pbp.footnoteFirstElementIndex <= pbp.footnoteLastElementIndex) {
+ // call addAreas() for each FootnoteBodyLM
+ for (int i = pbp.footnoteFirstListIndex; i <= pbp.footnoteLastListIndex; i++) {
+ LinkedList elementList = alg.getFootnoteList(i);
+ int firstIndex = (i == pbp.footnoteFirstListIndex
+ ? pbp.footnoteFirstElementIndex : 0);
+ int lastIndex = (i == pbp.footnoteLastListIndex
+ ? pbp.footnoteLastElementIndex : elementList.size() - 1);
+
+ SpaceResolver.performConditionalsNotification(elementList,
+ firstIndex, lastIndex, -1);
+ LayoutContext childLC = new LayoutContext(0);
+ AreaAdditionUtil.addAreas(null,
+ new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1),
+ childLC);
+ }
+ // set the offset from the top margin
+ Footnote parentArea = (Footnote) pslm.getCurrentPV().getBodyRegion().getFootnote();
+ int topOffset = (int) pslm.getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
+ if (separatorArea != null) {
+ topOffset -= separatorArea.getBPD();
+ }
+ parentArea.setTop(topOffset);
+ parentArea.setSeparator(separatorArea);
+ }
+ pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished();
+ }
+
+ /**
+ * @return the current child flow layout manager
+ */
+ protected LayoutManager getCurrentChildLM() {
+ return childFLM;
+ }
+
+ /** @see org.apache.fop.layoutmgr.AbstractBreaker#observeElementList(java.util.List) */
+ protected void observeElementList(List elementList) {
+ ElementListObserver.observe(elementList, "breaker",
+ ((PageSequence)pslm.getFObj()).getId());
+ }
+
+ /**
+ * Depending on the kind of break condition, move to next column
+ * or page. May need to make an empty page if next page would
+ * not have the desired "handedness".
+ * @param breakVal - value of break-before or break-after trait.
+ */
+ private void handleBreakTrait(int breakVal) {
+ Page curPage = pslm.getCurrentPage();
+ if (breakVal == Constants.EN_ALL) {
+ //break due to span change in multi-column layout
+ curPage.getPageViewport().createSpan(true);
+ return;
+ } else if (breakVal == Constants.EN_NONE) {
+ curPage.getPageViewport().createSpan(false);
+ return;
+ } else if (breakVal == Constants.EN_COLUMN || breakVal <= 0) {
+ PageViewport pv = curPage.getPageViewport();
+
+ //Check if previous page was spanned
+ boolean forceNewPageWithSpan = false;
+ RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
+ Constants.FO_REGION_BODY);
+ if (breakVal < 0
+ && rb.getColumnCount() > 1
+ && pv.getCurrentSpan().getColumnCount() == 1) {
+ forceNewPageWithSpan = true;
+ }
+
+ if (forceNewPageWithSpan) {
+ curPage = pslm.makeNewPage(false, false);
+ curPage.getPageViewport().createSpan(true);
+ } else if (pv.getCurrentSpan().hasMoreFlows()) {
+ pv.getCurrentSpan().moveToNextFlow();
+ } else {
+ curPage = pslm.makeNewPage(false, false);
+ }
+ return;
+ }
+ log.debug("handling break-before after page " + pslm.getCurrentPageNum()
+ + " breakVal=" + breakVal);
+ if (needBlankPageBeforeNew(breakVal)) {
+ curPage = pslm.makeNewPage(true, false);
+ }
+ if (needNewPage(breakVal)) {
+ curPage = pslm.makeNewPage(false, false);
+ }
+ }
+
+ /**
+ * Check if a blank page is needed to accomodate
+ * desired even or odd page number.
+ * @param breakVal - value of break-before or break-after trait.
+ */
+ private boolean needBlankPageBeforeNew(int breakVal) {
+ if (breakVal == Constants.EN_PAGE || (pslm.getCurrentPage().getPageViewport().getPage().isEmpty())) {
+ // any page is OK or we already have an empty page
+ return false;
+ } else {
+ /* IF we are on the kind of page we need, we'll need a new page. */
+ if (pslm.getCurrentPageNum() % 2 == 0) { // even page
+ return (breakVal == Constants.EN_EVEN_PAGE);
+ } else { // odd page
+ return (breakVal == Constants.EN_ODD_PAGE);
+ }
+ }
+ }
+
+ /**
+ * See if need to generate a new page
+ * @param breakVal - value of break-before or break-after trait.
+ */
+ private boolean needNewPage(int breakVal) {
+ if (pslm.getCurrentPage().getPageViewport().getPage().isEmpty()) {
+ if (breakVal == Constants.EN_PAGE) {
+ return false;
+ } else if (pslm.getCurrentPageNum() % 2 == 0) { // even page
+ return (breakVal == Constants.EN_ODD_PAGE);
+ } else { // odd page
+ return (breakVal == Constants.EN_EVEN_PAGE);
+ }
+ } else {
+ return true;
+ }
+ }
+}
\ No newline at end of file
private static Log log = LogFactory.getLog(PageBreakingAlgorithm.class);
private LayoutManager topLevelLM;
- private PageSequenceLayoutManager.PageProvider pageProvider;
+ private PageProvider pageProvider;
private PageBreakingLayoutListener layoutListener;
/** List of PageBreakPosition elements. */
private LinkedList pageBreaks = null;
private boolean favorSinglePart = false;
public PageBreakingAlgorithm(LayoutManager topLevelLM,
- PageSequenceLayoutManager.PageProvider pageProvider,
+ PageProvider pageProvider,
PageBreakingLayoutListener layoutListener,
int alignment, int alignmentLast,
MinOptMax footnoteSeparatorLength,
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.layoutmgr;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.area.AreaTreeHandler;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.pagination.PageSequence;
+import org.apache.fop.fo.pagination.Region;
+import org.apache.fop.fo.pagination.SimplePageMaster;
+
+/**
+ * <p>This class delivers Page instances. It also caches them as necessary.
+ * </p>
+ * <p>Additional functionality makes sure that surplus instances that are requested by the
+ * page breaker are properly discarded, especially in situations where hard breaks cause
+ * blank pages. The reason for that: The page breaker sometimes needs to preallocate
+ * additional pages since it doesn't know exactly until the end how many pages it really needs.
+ * </p>
+ */
+public class PageProvider implements Constants {
+
+ private Log log = LogFactory.getLog(PageProvider.class);
+
+ /** Indices are evaluated relative to the first page in the page-sequence. */
+ public static final int RELTO_PAGE_SEQUENCE = 0;
+ /** Indices are evaluated relative to the first page in the current element list. */
+ public static final int RELTO_CURRENT_ELEMENT_LIST = 1;
+
+ private int startPageOfPageSequence;
+ private int startPageOfCurrentElementList;
+ private int startColumnOfCurrentElementList;
+ private List cachedPages = new java.util.ArrayList();
+
+ private int lastPageIndex = -1;
+ private int indexOfCachedLastPage = -1;
+
+ //Cache to optimize getAvailableBPD() calls
+ private int lastRequestedIndex = -1;
+ private int lastReportedBPD = -1;
+
+ /**
+ * AreaTreeHandler which activates the PSLM and controls
+ * the rendering of its pages.
+ */
+ private AreaTreeHandler areaTreeHandler;
+
+ /**
+ * fo:page-sequence formatting object being
+ * processed by this class
+ */
+ private PageSequence pageSeq;
+
+ /**
+ * Main constructor.
+ * @param ps The page-sequence the provider operates on
+ */
+ public PageProvider(AreaTreeHandler ath, PageSequence ps) {
+ this.areaTreeHandler = ath;
+ this.pageSeq = ps;
+ this.startPageOfPageSequence = ps.getStartingPageNumber();
+ }
+
+ /**
+ * The page breaker notifies the provider about the page number an element list starts
+ * on so it can later retrieve PageViewports relative to this first page.
+ * @param startPage the number of the first page for the element list.
+ * @param startColumn the starting column number for the element list.
+ */
+ public void setStartOfNextElementList(int startPage, int startColumn) {
+ log.debug("start of the next element list is:"
+ + " page=" + startPage + " col=" + startColumn);
+ this.startPageOfCurrentElementList = startPage - startPageOfPageSequence + 1;
+ this.startColumnOfCurrentElementList = startColumn;
+ //Reset Cache
+ this.lastRequestedIndex = -1;
+ this.lastReportedBPD = -1;
+ }
+
+ /**
+ * Sets the index of the last page. This is done as soon as the position of the last page
+ * is known or assumed.
+ * @param index the index relative to the first page in the page-sequence
+ */
+ public void setLastPageIndex(int index) {
+ this.lastPageIndex = index;
+ }
+
+ /**
+ * Returns the available BPD for the part/page indicated by the index parameter.
+ * The index is the part/page relative to the start of the current element list.
+ * This method takes multiple columns into account.
+ * @param index zero-based index of the requested part/page
+ * @return the available BPD
+ */
+ public int getAvailableBPD(int index) {
+ //Special optimization: There may be many equal calls by the BreakingAlgorithm
+ if (this.lastRequestedIndex == index) {
+ if (log.isTraceEnabled()) {
+ log.trace("getAvailableBPD(" + index + ") -> (cached) " + lastReportedBPD);
+ }
+ return this.lastReportedBPD;
+ }
+ int c = index;
+ int pageIndex = 0;
+ int colIndex = startColumnOfCurrentElementList;
+ Page page = getPage(
+ false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+ while (c > 0) {
+ colIndex++;
+ if (colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount()) {
+ colIndex = 0;
+ pageIndex++;
+ page = getPage(
+ false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+ }
+ c--;
+ }
+ this.lastRequestedIndex = index;
+ this.lastReportedBPD = page.getPageViewport().getBodyRegion().getRemainingBPD();
+ if (log.isTraceEnabled()) {
+ log.trace("getAvailableBPD(" + index + ") -> " + lastReportedBPD);
+ }
+ return this.lastReportedBPD;
+ }
+
+ /**
+ * Returns the part index (0<x<partCount) which denotes the first part on the last page
+ * generated by the current element list.
+ * @param partCount Number of parts determined by the breaking algorithm
+ * @return the requested part index
+ */
+ public int getStartingPartIndexForLastPage(int partCount) {
+ int result = 0;
+ int idx = 0;
+ int pageIndex = 0;
+ int colIndex = startColumnOfCurrentElementList;
+ Page page = getPage(
+ false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+ while (idx < partCount) {
+ if ((colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount())) {
+ colIndex = 0;
+ pageIndex++;
+ page = getPage(
+ false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
+ result = idx;
+ }
+ colIndex++;
+ idx++;
+ }
+ return result;
+ }
+
+ /**
+ * Returns a Page.
+ * @param isBlank true if this page is supposed to be blank.
+ * @param index Index of the page (see relativeTo)
+ * @param relativeTo Defines which value the index parameter should be evaluated relative
+ * to. (One of PageProvider.RELTO_*)
+ * @return the requested Page
+ */
+ public Page getPage(boolean isBlank, int index, int relativeTo) {
+ if (relativeTo == RELTO_PAGE_SEQUENCE) {
+ return getPage(isBlank, index);
+ } else if (relativeTo == RELTO_CURRENT_ELEMENT_LIST) {
+ int effIndex = startPageOfCurrentElementList + index;
+ effIndex += startPageOfPageSequence - 1;
+ return getPage(isBlank, effIndex);
+ } else {
+ throw new IllegalArgumentException(
+ "Illegal value for relativeTo: " + relativeTo);
+ }
+ }
+
+ /**
+ *
+ * @param isBlank
+ * @param index
+ * @return
+ */
+ protected Page getPage(boolean isBlank, int index) {
+ boolean isLastPage = (lastPageIndex >= 0) && (index == lastPageIndex);
+ if (log.isTraceEnabled()) {
+ log.trace("getPage(" + index + " " + (isBlank ? "blank" : "non-blank")
+ + (isLastPage ? " <LAST>" : "") + ")");
+ }
+ int intIndex = index - startPageOfPageSequence;
+ if (log.isTraceEnabled()) {
+ if (isBlank) {
+ log.trace("blank page requested: " + index);
+ }
+ if (isLastPage) {
+ log.trace("last page requested: " + index);
+ }
+ }
+ while (intIndex >= cachedPages.size()) {
+ if (log.isTraceEnabled()) {
+ log.trace("Caching " + index);
+ }
+ cacheNextPage(index, isBlank, isLastPage);
+ }
+ Page page = (Page)cachedPages.get(intIndex);
+ boolean replace = false;
+ if (page.getPageViewport().isBlank() != isBlank) {
+ log.debug("blank condition doesn't match. Replacing PageViewport.");
+ replace = true;
+ }
+ if ((isLastPage && indexOfCachedLastPage != intIndex)
+ || (!isLastPage && indexOfCachedLastPage >= 0)) {
+ log.debug("last page condition doesn't match. Replacing PageViewport.");
+ replace = true;
+ indexOfCachedLastPage = (isLastPage ? intIndex : -1);
+ }
+ if (replace) {
+ disardCacheStartingWith(intIndex);
+ page = cacheNextPage(index, isBlank, isLastPage);
+ }
+ return page;
+ }
+
+ private void disardCacheStartingWith(int index) {
+ while (index < cachedPages.size()) {
+ this.cachedPages.remove(cachedPages.size() - 1);
+ if (!pageSeq.goToPreviousSimplePageMaster()) {
+ log.warn("goToPreviousSimplePageMaster() on the first page called!");
+ }
+ }
+ }
+
+ private Page cacheNextPage(int index, boolean isBlank, boolean isLastPage) {
+ try {
+ String pageNumberString = pageSeq.makeFormattedPageNumber(index);
+ SimplePageMaster spm = pageSeq.getNextSimplePageMaster(
+ index, (startPageOfPageSequence == index), isLastPage, isBlank);
+
+ Region body = spm.getRegion(FO_REGION_BODY);
+ if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) {
+ // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to
+ // any region), but we don't support it yet.
+ throw new FOPException("Flow '" + pageSeq.getMainFlow().getFlowName()
+ + "' does not map to the region-body in page-master '"
+ + spm.getMasterName() + "'. FOP presently "
+ + "does not support this.");
+ }
+ Page page = new Page(spm, index, pageNumberString, isBlank);
+ //Set unique key obtained from the AreaTreeHandler
+ page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey());
+ page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
+ cachedPages.add(page);
+ return page;
+ } catch (FOPException e) {
+ //TODO Maybe improve. It'll mean to propagate this exception up several
+ //methods calls.
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+
+}
\ No newline at end of file
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Numeric;
import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.area.AreaTreeModel;
-import org.apache.fop.area.Block;
-import org.apache.fop.area.Footnote;
+import org.apache.fop.area.IDTracker;
import org.apache.fop.area.PageViewport;
import org.apache.fop.area.LineArea;
import org.apache.fop.area.Resolvable;
import org.apache.fop.fo.Constants;
-import org.apache.fop.fo.FONode;
-import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.flow.RetrieveMarker;
-import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.PageSequenceMaster;
-import org.apache.fop.fo.pagination.Region;
-import org.apache.fop.fo.pagination.RegionBody;
import org.apache.fop.fo.pagination.SideRegion;
-import org.apache.fop.fo.pagination.SimplePageMaster;
import org.apache.fop.fo.pagination.StaticContent;
-import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
import org.apache.fop.layoutmgr.inline.ContentLayoutManager;
-import org.apache.fop.traits.MinOptMax;
-
-import java.util.LinkedList;
import java.util.List;
-import java.util.ListIterator;
/**
* LayoutManager for a PageSequence. This class is instantiated by
private PageSequence pageSeq;
private PageProvider pageProvider;
-
+
+ private IDTracker idTracker;
+
/**
* Current page with page-viewport-area being filled by
* the PSLM.
*/
- private Page curPage = null;
-
- /**
- * The FlowLayoutManager object, which processes
- * the single fo:flow of the fo:page-sequence
- */
- private FlowLayoutManager childFLM = null;
+ private Page curPage;
private int startPageNum = 0;
private int currentPageNum = 0;
-
- private Block separatorArea = null;
/**
* Constructor
public PageSequenceLayoutManager(AreaTreeHandler ath, PageSequence pseq) {
super(pseq);
this.areaTreeHandler = ath;
+ this.idTracker = ath.getIDTracker();
this.pageSeq = pseq;
- this.pageProvider = new PageProvider(this.pageSeq);
+ this.pageProvider = new PageProvider(ath, pseq);
}
/**
return this.pageProvider;
}
+ /**
+ * @return the PageSequence being managed by this layout manager
+ */
+ protected PageSequence getPageSequence() {
+ return pageSeq;
+ }
+
/**
* Activate the layout of this page sequence.
* PageViewports corresponding to each page generated by this
curPage = makeNewPage(false, false);
- Flow mainFlow = pageSeq.getMainFlow();
- childFLM = getLayoutManagerMaker().
- makeFlowLayoutManager(this, mainFlow);
-
PageBreaker breaker = new PageBreaker(this);
int flowBPD = (int)getCurrentPV().getBodyRegion().getRemainingBPD();
breaker.doLayout(flowBPD);
* Finished the page-sequence and notifies everyone about it.
*/
public void finishPageSequence() {
- if (!pageSeq.getId().equals("")) {
- areaTreeHandler.signalIDProcessed(pageSeq.getId());
+ if (pageSeq.hasId()) {
+ idTracker.signalIDProcessed(pageSeq.getId());
}
pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum,
log.debug("Ending layout");
}
}
-
-
- private class PageBreaker extends AbstractBreaker {
-
- private PageSequenceLayoutManager pslm;
- private boolean firstPart = true;
- private boolean pageBreakHandled;
- private boolean needColumnBalancing;
-
- private StaticContentLayoutManager footnoteSeparatorLM = null;
-
- public PageBreaker(PageSequenceLayoutManager pslm) {
- this.pslm = pslm;
- }
-
- /** @see org.apache.fop.layoutmgr.AbstractBreaker */
- protected void updateLayoutContext(LayoutContext context) {
- int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth();
- context.setRefIPD(flowIPD);
- }
-
- /** @see org.apache.fop.layoutmgr.AbstractBreaker#getTopLevelLM() */
- protected LayoutManager getTopLevelLM() {
- return pslm;
- }
-
- /** @see org.apache.fop.layoutmgr.AbstractBreaker#getPageProvider() */
- protected PageSequenceLayoutManager.PageProvider getPageProvider() {
- return pageProvider;
- }
-
- /**
- * @see org.apache.fop.layoutmgr.AbstractBreaker#getLayoutListener()
- */
- protected PageBreakingLayoutListener getLayoutListener() {
- return new PageBreakingLayoutListener() {
-
- public void notifyOverflow(int part, FObj obj) {
- Page p = pageProvider.getPage(
- false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST);
- RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion(
- Region.FO_REGION_BODY);
- String err = FONode.decorateWithContextInfo(
- "Content of the region-body on page "
- + p.getPageViewport().getPageNumberString()
- + " overflows the available area in block-progression dimension.",
- obj);
- if (body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW) {
- throw new RuntimeException(err);
- } else {
- PageSequenceLayoutManager.log.warn(err);
- }
- }
-
- };
- }
-
- /** @see org.apache.fop.layoutmgr.AbstractBreaker */
- protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
- needColumnBalancing = false;
- if (childLC.getNextSpan() != Constants.NOT_SET) {
- //Next block list will have a different span.
- nextSequenceStartsOn = childLC.getNextSpan();
- needColumnBalancing = (childLC.getNextSpan() == Constants.EN_ALL);
- }
- if (needColumnBalancing) {
- AbstractBreaker.log.debug(
- "Column balancing necessary for the next element list!!!");
- }
- return nextSequenceStartsOn;
- }
-
- /** @see org.apache.fop.layoutmgr.AbstractBreaker */
- protected int getNextBlockList(LayoutContext childLC,
- int nextSequenceStartsOn,
- List blockLists) {
- if (!firstPart) {
- // if this is the first page that will be created by
- // the current BlockSequence, it could have a break
- // condition that must be satisfied;
- // otherwise, we may simply need a new page
- handleBreakTrait(nextSequenceStartsOn);
- }
- firstPart = false;
- pageBreakHandled = true;
- pageProvider.setStartOfNextElementList(currentPageNum,
- getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
- return super.getNextBlockList(childLC, nextSequenceStartsOn, blockLists);
- }
-
- /** @see org.apache.fop.layoutmgr.AbstractBreaker */
- protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
- LinkedList contentList = null;
-
- while (!childFLM.isFinished() && contentList == null) {
- contentList = childFLM.getNextKnuthElements(context, alignment);
- }
-
- // scan contentList, searching for footnotes
- boolean bFootnotesPresent = false;
- if (contentList != null) {
- ListIterator contentListIterator = contentList.listIterator();
- while (contentListIterator.hasNext()) {
- ListElement element = (ListElement) contentListIterator.next();
- if (element instanceof KnuthBlockBox
- && ((KnuthBlockBox) element).hasAnchors()) {
- // element represents a line with footnote citations
- bFootnotesPresent = true;
- LayoutContext footnoteContext = new LayoutContext(context);
- footnoteContext.setStackLimit(context.getStackLimit());
- footnoteContext.setRefIPD(getCurrentPV()
- .getRegionReference(Constants.FO_REGION_BODY).getIPD());
- LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs();
- ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator();
- // store the lists of elements representing the footnote bodies
- // in the box representing the line containing their references
- while (footnoteBodyIterator.hasNext()) {
- FootnoteBodyLayoutManager fblm
- = (FootnoteBodyLayoutManager) footnoteBodyIterator.next();
- fblm.setParent(childFLM);
- fblm.initialize();
- ((KnuthBlockBox) element).addElementList(
- fblm.getNextKnuthElements(footnoteContext, alignment));
- }
- }
- }
- }
-
- // handle the footnote separator
- StaticContent footnoteSeparator;
- if (bFootnotesPresent
- && (footnoteSeparator = pageSeq.getStaticContent(
- "xsl-footnote-separator")) != null) {
- // the footnote separator can contain page-dependent content such as
- // page numbers or retrieve markers, so its areas cannot simply be
- // obtained now and repeated in each page;
- // we need to know in advance the separator bpd: the actual separator
- // could be different from page to page, but its bpd would likely be
- // always the same
-
- // create a Block area that will contain the separator areas
- separatorArea = new Block();
- separatorArea.setIPD(pslm.getCurrentPV()
- .getRegionReference(Constants.FO_REGION_BODY).getIPD());
- // create a StaticContentLM for the footnote separator
- footnoteSeparatorLM = (StaticContentLayoutManager)
- getLayoutManagerMaker().makeStaticContentLayoutManager(
- pslm, footnoteSeparator, separatorArea);
- footnoteSeparatorLM.doLayout();
-
- footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
- }
- return contentList;
- }
-
- protected int getCurrentDisplayAlign() {
- return curPage.getSimplePageMaster().getRegion(
- Constants.FO_REGION_BODY).getDisplayAlign();
- }
-
- protected boolean hasMoreContent() {
- return !childFLM.isFinished();
- }
-
- protected void addAreas(PositionIterator posIter, LayoutContext context) {
- if (footnoteSeparatorLM != null) {
- StaticContent footnoteSeparator = pageSeq.getStaticContent(
- "xsl-footnote-separator");
- // create a Block area that will contain the separator areas
- separatorArea = new Block();
- separatorArea.setIPD(
- getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD());
- // create a StaticContentLM for the footnote separator
- footnoteSeparatorLM = (StaticContentLayoutManager)
- getLayoutManagerMaker().makeStaticContentLayoutManager(
- pslm, footnoteSeparator, separatorArea);
- footnoteSeparatorLM.doLayout();
- }
-
- childFLM.addAreas(posIter, context);
- }
-
- protected void doPhase3(PageBreakingAlgorithm alg, int partCount,
- BlockSequence originalList, BlockSequence effectiveList) {
- if (needColumnBalancing) {
- doPhase3WithColumnBalancing(alg, partCount, originalList, effectiveList);
- } else {
- if (!hasMoreContent() && pageSeq.hasPagePositionLast()) {
- //last part is reached and we have a "last page" condition
- doPhase3WithLastPage(alg, partCount, originalList, effectiveList);
- } else {
- //Directly add areas after finding the breaks
- addAreas(alg, partCount, originalList, effectiveList);
- }
- }
- }
-
- private void doPhase3WithLastPage(PageBreakingAlgorithm alg, int partCount,
- BlockSequence originalList, BlockSequence effectiveList) {
- int newStartPos;
- int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
- if (restartPoint > 0) {
- //Add definitive areas before last page
- addAreas(alg, restartPoint, originalList, effectiveList);
- //Get page break from which we restart
- PageBreakPosition pbp = (PageBreakPosition)
- alg.getPageBreaks().get(restartPoint - 1);
- newStartPos = pbp.getLeafPos();
- //Handle page break right here to avoid any side-effects
- if (newStartPos > 0) {
- handleBreakTrait(EN_PAGE);
- }
- } else {
- newStartPos = 0;
- }
- AbstractBreaker.log.debug("Last page handling now!!!");
- AbstractBreaker.log.debug("===================================================");
- AbstractBreaker.log.debug("Restarting at " + restartPoint
- + ", new start position: " + newStartPos);
-
- pageBreakHandled = true;
- //Update so the available BPD is reported correctly
- pageProvider.setStartOfNextElementList(currentPageNum,
- getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
- pageProvider.setLastPageIndex(currentPageNum);
-
- //Restart last page
- PageBreakingAlgorithm algRestart = new PageBreakingAlgorithm(
- getTopLevelLM(),
- getPageProvider(), getLayoutListener(),
- alg.getAlignment(), alg.getAlignmentLast(),
- footnoteSeparatorLength,
- isPartOverflowRecoveryActivated(), false, false);
- //alg.setConstantLineWidth(flowBPD);
- int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
- newStartPos,
- 1, true, BreakingAlgorithm.ALL_BREAKS);
- AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
- + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
- boolean replaceLastPage
- = iOptPageCount <= getCurrentPV().getBodyRegion().getColumnCount();
- if (replaceLastPage) {
-
- //Replace last page
- pslm.curPage = pageProvider.getPage(false, currentPageNum);
- //Make sure we only add the areas we haven't added already
- effectiveList.ignoreAtStart = newStartPos;
- addAreas(algRestart, iOptPageCount, originalList, effectiveList);
- } else {
- effectiveList.ignoreAtStart = newStartPos;
- addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
- //Add blank last page
- pageProvider.setLastPageIndex(currentPageNum + 1);
- pslm.curPage = makeNewPage(true, true);
- }
- AbstractBreaker.log.debug("===================================================");
- }
-
- private void doPhase3WithColumnBalancing(PageBreakingAlgorithm alg, int partCount,
- BlockSequence originalList, BlockSequence effectiveList) {
- AbstractBreaker.log.debug("Column balancing now!!!");
- AbstractBreaker.log.debug("===================================================");
- int newStartPos;
- int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
- if (restartPoint > 0) {
- //Add definitive areas
- addAreas(alg, restartPoint, originalList, effectiveList);
- //Get page break from which we restart
- PageBreakPosition pbp = (PageBreakPosition)
- alg.getPageBreaks().get(restartPoint - 1);
- newStartPos = pbp.getLeafPos();
- //Handle page break right here to avoid any side-effects
- if (newStartPos > 0) {
- handleBreakTrait(EN_PAGE);
- }
- } else {
- newStartPos = 0;
- }
- AbstractBreaker.log.debug("Restarting at " + restartPoint
- + ", new start position: " + newStartPos);
-
- pageBreakHandled = true;
- //Update so the available BPD is reported correctly
- pageProvider.setStartOfNextElementList(currentPageNum,
- getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
-
- //Restart last page
- PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm(
- getTopLevelLM(),
- getPageProvider(), getLayoutListener(),
- alignment, Constants.EN_START, footnoteSeparatorLength,
- isPartOverflowRecoveryActivated(),
- getCurrentPV().getBodyRegion().getColumnCount());
- //alg.setConstantLineWidth(flowBPD);
- int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
- newStartPos,
- 1, true, BreakingAlgorithm.ALL_BREAKS);
- AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
- + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
- if (iOptPageCount > getCurrentPV().getBodyRegion().getColumnCount()) {
- AbstractBreaker.log.warn(
- "Breaking algorithm produced more columns than are available.");
- /* reenable when everything works
- throw new IllegalStateException(
- "Breaking algorithm must not produce more columns than available.");
- */
- }
- //Make sure we only add the areas we haven't added already
- effectiveList.ignoreAtStart = newStartPos;
- addAreas(algRestart, iOptPageCount, originalList, effectiveList);
- AbstractBreaker.log.debug("===================================================");
- }
-
- protected void startPart(BlockSequence list, int breakClass) {
- AbstractBreaker.log.debug("startPart() breakClass=" + breakClass);
- if (curPage == null) {
- throw new IllegalStateException("curPage must not be null");
- }
- if (!pageBreakHandled) {
-
- //firstPart is necessary because we need the first page before we start the
- //algorithm so we have a BPD and IPD. This may subject to change later when we
- //start handling more complex cases.
- if (!firstPart) {
- // if this is the first page that will be created by
- // the current BlockSequence, it could have a break
- // condition that must be satisfied;
- // otherwise, we may simply need a new page
- handleBreakTrait(breakClass);
- }
- pageProvider.setStartOfNextElementList(currentPageNum,
- getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
- }
- pageBreakHandled = false;
- // add static areas and resolve any new id areas
- // finish page and add to area tree
- firstPart = false;
- }
-
- /** @see org.apache.fop.layoutmgr.AbstractBreaker#handleEmptyContent() */
- protected void handleEmptyContent() {
- getCurrentPV().getPage().fakeNonEmpty();
- }
-
- protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
- // add footnote areas
- if (pbp.footnoteFirstListIndex < pbp.footnoteLastListIndex
- || pbp.footnoteFirstElementIndex <= pbp.footnoteLastElementIndex) {
- // call addAreas() for each FootnoteBodyLM
- for (int i = pbp.footnoteFirstListIndex; i <= pbp.footnoteLastListIndex; i++) {
- LinkedList elementList = alg.getFootnoteList(i);
- int firstIndex = (i == pbp.footnoteFirstListIndex
- ? pbp.footnoteFirstElementIndex : 0);
- int lastIndex = (i == pbp.footnoteLastListIndex
- ? pbp.footnoteLastElementIndex : elementList.size() - 1);
-
- SpaceResolver.performConditionalsNotification(elementList,
- firstIndex, lastIndex, -1);
- LayoutContext childLC = new LayoutContext(0);
- AreaAdditionUtil.addAreas(null,
- new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1),
- childLC);
- }
- // set the offset from the top margin
- Footnote parentArea = (Footnote) getCurrentPV().getBodyRegion().getFootnote();
- int topOffset = (int) getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
- if (separatorArea != null) {
- topOffset -= separatorArea.getBPD();
- }
- parentArea.setTop(topOffset);
- parentArea.setSeparator(separatorArea);
- }
- getCurrentPV().getCurrentSpan().notifyFlowsFinished();
- }
-
- protected LayoutManager getCurrentChildLM() {
- return childFLM;
- }
-
- /** @see org.apache.fop.layoutmgr.AbstractBreaker#observeElementList(java.util.List) */
- protected void observeElementList(List elementList) {
- ElementListObserver.observe(elementList, "breaker",
- ((PageSequence)pslm.getFObj()).getId());
- }
-
- }
/**
* Provides access to the current page.
return curPage;
}
+ /**
+ * Provides access for setting the current page.
+ * @param currentPage the new current Page
+ */
+ protected void setCurrentPage(Page currentPage) {
+ this.curPage = currentPage;
+ }
+
+ /**
+ * Provides access to the current page number
+ * @return the current page number
+ */
+ protected int getCurrentPageNum() {
+ return currentPageNum;
+ }
+
/**
* Provides access to the current page viewport.
* @return the current PageViewport
* @return the first PageViewport that contains the ID trait
*/
public PageViewport getFirstPVWithID(String idref) {
- List list = areaTreeHandler.getPageViewportsContainingID(idref);
+ List list = idTracker.getPageViewportsContainingID(idref);
if (list != null && list.size() > 0) {
return (PageViewport) list.get(0);
}
* @return the last PageViewport that contains the ID trait
*/
public PageViewport getLastPVWithID(String idref) {
- List list = areaTreeHandler.getPageViewportsContainingID(idref);
+ List list = idTracker.getPageViewportsContainingID(idref);
if (list != null && list.size() > 0) {
return (PageViewport) list.get(list.size() - 1);
}
*/
public void addIDToPage(String id) {
if (id != null && id.length() > 0) {
- areaTreeHandler.associateIDWithPageViewport(id, curPage.getPageViewport());
+ idTracker.associateIDWithPageViewport(id, curPage.getPageViewport());
}
}
if (log.isDebugEnabled()) {
log.debug("associateLayoutManagerID(" + id + ")");
}
- if (!areaTreeHandler.alreadyResolvedID(id)) {
- areaTreeHandler.signalPendingID(id);
+ if (!idTracker.alreadyResolvedID(id)) {
+ idTracker.signalPendingID(id);
return false;
} else {
return true;
* @param id the id for which layout has finished
*/
public void notifyEndOfLayout(String id) {
- areaTreeHandler.signalIDProcessed(id);
+ idTracker.signalIDProcessed(id);
}
/**
* resolved, e.g. the internal-destination of an fo:basic-link)
* for both the AreaTreeHandler and PageViewport object.
*
- * The AreaTreeHandler keeps a document-wide list of idref's
+ * The IDTracker keeps a document-wide list of idref's
* and the PV's needing them to be resolved. It uses this to
* send notifications to the PV's when an id has been resolved.
*
*/
public void addUnresolvedArea(String id, Resolvable res) {
curPage.getPageViewport().addUnresolvedIDRef(id, res);
- areaTreeHandler.addUnresolvedIDRef(id, curPage.getPageViewport());
+ idTracker.addUnresolvedIDRef(id, curPage.getPageViewport());
}
/**
}
}
- private Page makeNewPage(boolean bIsBlank, boolean bIsLast) {
+ /**
+ * Makes a new page
+ *
+ * @param bIsBlank whether this page is blank or not
+ * @param bIsLast whether this page is the last page or not
+ * @return a new page
+ */
+ protected Page makeNewPage(boolean bIsBlank, boolean bIsLast) {
if (curPage != null) {
finishPage();
}
// Try to resolve any unresolved IDs for the current page.
//
- areaTreeHandler.tryIDResolution(curPage.getPageViewport());
+ idTracker.tryIDResolution(curPage.getPageViewport());
// Queue for ID resolution and rendering
areaTreeHandler.getAreaTreeModel().addPage(curPage.getPageViewport());
if (log.isDebugEnabled()) {
}
curPage = null;
}
-
- /**
- * Depending on the kind of break condition, move to next column
- * or page. May need to make an empty page if next page would
- * not have the desired "handedness".
- * @param breakVal - value of break-before or break-after trait.
- */
- private void handleBreakTrait(int breakVal) {
- if (breakVal == Constants.EN_ALL) {
- //break due to span change in multi-column layout
- curPage.getPageViewport().createSpan(true);
- return;
- } else if (breakVal == Constants.EN_NONE) {
- curPage.getPageViewport().createSpan(false);
- return;
- } else if (breakVal == Constants.EN_COLUMN || breakVal <= 0) {
- PageViewport pv = curPage.getPageViewport();
-
- //Check if previous page was spanned
- boolean forceNewPageWithSpan = false;
- RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
- Constants.FO_REGION_BODY);
- if (breakVal < 0
- && rb.getColumnCount() > 1
- && pv.getCurrentSpan().getColumnCount() == 1) {
- forceNewPageWithSpan = true;
- }
-
- if (forceNewPageWithSpan) {
- curPage = makeNewPage(false, false);
- curPage.getPageViewport().createSpan(true);
- } else if (pv.getCurrentSpan().hasMoreFlows()) {
- pv.getCurrentSpan().moveToNextFlow();
- } else {
- curPage = makeNewPage(false, false);
- }
- return;
- }
- log.debug("handling break-before after page " + currentPageNum
- + " breakVal=" + breakVal);
- if (needBlankPageBeforeNew(breakVal)) {
- curPage = makeNewPage(true, false);
- }
- if (needNewPage(breakVal)) {
- curPage = makeNewPage(false, false);
- }
- }
-
- /**
- * Check if a blank page is needed to accomodate
- * desired even or odd page number.
- * @param breakVal - value of break-before or break-after trait.
- */
- private boolean needBlankPageBeforeNew(int breakVal) {
- if (breakVal == Constants.EN_PAGE || (curPage.getPageViewport().getPage().isEmpty())) {
- // any page is OK or we already have an empty page
- return false;
- } else {
- /* IF we are on the kind of page we need, we'll need a new page. */
- if (currentPageNum % 2 == 0) { // even page
- return (breakVal == Constants.EN_EVEN_PAGE);
- } else { // odd page
- return (breakVal == Constants.EN_ODD_PAGE);
- }
- }
- }
-
- /**
- * See if need to generate a new page
- * @param breakVal - value of break-before or break-after trait.
- */
- private boolean needNewPage(int breakVal) {
- if (curPage.getPageViewport().getPage().isEmpty()) {
- if (breakVal == Constants.EN_PAGE) {
- return false;
- } else if (currentPageNum % 2 == 0) { // even page
- return (breakVal == Constants.EN_ODD_PAGE);
- } else { // odd page
- return (breakVal == Constants.EN_EVEN_PAGE);
- }
- } else {
- return true;
- }
- }
-
-
- /**
- * <p>This class delivers Page instances. It also caches them as necessary.
- * </p>
- * <p>Additional functionality makes sure that surplus instances that are requested by the
- * page breaker are properly discarded, especially in situations where hard breaks cause
- * blank pages. The reason for that: The page breaker sometimes needs to preallocate
- * additional pages since it doesn't know exactly until the end how many pages it really needs.
- * </p>
- */
- public class PageProvider {
-
- private Log log = LogFactory.getLog(PageProvider.class);
-
- /** Indices are evaluated relative to the first page in the page-sequence. */
- public static final int RELTO_PAGE_SEQUENCE = 0;
- /** Indices are evaluated relative to the first page in the current element list. */
- public static final int RELTO_CURRENT_ELEMENT_LIST = 1;
-
- private int startPageOfPageSequence;
- private int startPageOfCurrentElementList;
- private int startColumnOfCurrentElementList;
- private List cachedPages = new java.util.ArrayList();
-
- private int lastPageIndex = -1;
- private int indexOfCachedLastPage = -1;
-
- //Cache to optimize getAvailableBPD() calls
- private int lastRequestedIndex = -1;
- private int lastReportedBPD = -1;
-
- /**
- * Main constructor.
- * @param ps The page-sequence the provider operates on
- */
- public PageProvider(PageSequence ps) {
- this.startPageOfPageSequence = ps.getStartingPageNumber();
- }
-
- /**
- * The page breaker notifies the provider about the page number an element list starts
- * on so it can later retrieve PageViewports relative to this first page.
- * @param startPage the number of the first page for the element list.
- * @param startColumn the starting column number for the element list.
- */
- public void setStartOfNextElementList(int startPage, int startColumn) {
- log.debug("start of the next element list is:"
- + " page=" + startPage + " col=" + startColumn);
- this.startPageOfCurrentElementList = startPage - startPageOfPageSequence + 1;
- this.startColumnOfCurrentElementList = startColumn;
- //Reset Cache
- this.lastRequestedIndex = -1;
- this.lastReportedBPD = -1;
- }
-
- /**
- * Sets the index of the last page. This is done as soon as the position of the last page
- * is known or assumed.
- * @param index the index relative to the first page in the page-sequence
- */
- public void setLastPageIndex(int index) {
- this.lastPageIndex = index;
- }
-
- /**
- * Returns the available BPD for the part/page indicated by the index parameter.
- * The index is the part/page relative to the start of the current element list.
- * This method takes multiple columns into account.
- * @param index zero-based index of the requested part/page
- * @return the available BPD
- */
- public int getAvailableBPD(int index) {
- //Special optimization: There may be many equal calls by the BreakingAlgorithm
- if (this.lastRequestedIndex == index) {
- if (log.isTraceEnabled()) {
- log.trace("getAvailableBPD(" + index + ") -> (cached) " + lastReportedBPD);
- }
- return this.lastReportedBPD;
- }
- int c = index;
- int pageIndex = 0;
- int colIndex = startColumnOfCurrentElementList;
- Page page = getPage(
- false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
- while (c > 0) {
- colIndex++;
- if (colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount()) {
- colIndex = 0;
- pageIndex++;
- page = getPage(
- false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
- }
- c--;
- }
- this.lastRequestedIndex = index;
- this.lastReportedBPD = page.getPageViewport().getBodyRegion().getRemainingBPD();
- if (log.isTraceEnabled()) {
- log.trace("getAvailableBPD(" + index + ") -> " + lastReportedBPD);
- }
- return this.lastReportedBPD;
- }
-
- /**
- * Returns the part index (0<x<partCount) which denotes the first part on the last page
- * generated by the current element list.
- * @param partCount Number of parts determined by the breaking algorithm
- * @return the requested part index
- */
- public int getStartingPartIndexForLastPage(int partCount) {
- int result = 0;
- int idx = 0;
- int pageIndex = 0;
- int colIndex = startColumnOfCurrentElementList;
- Page page = getPage(
- false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
- while (idx < partCount) {
- if ((colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount())) {
- colIndex = 0;
- pageIndex++;
- page = getPage(
- false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
- result = idx;
- }
- colIndex++;
- idx++;
- }
- return result;
- }
-
- /**
- * Returns a Page.
- * @param isBlank true if this page is supposed to be blank.
- * @param index Index of the page (see relativeTo)
- * @param relativeTo Defines which value the index parameter should be evaluated relative
- * to. (One of PageProvider.RELTO_*)
- * @return the requested Page
- */
- public Page getPage(boolean isBlank, int index, int relativeTo) {
- if (relativeTo == RELTO_PAGE_SEQUENCE) {
- return getPage(isBlank, index);
- } else if (relativeTo == RELTO_CURRENT_ELEMENT_LIST) {
- int effIndex = startPageOfCurrentElementList + index;
- effIndex += startPageOfPageSequence - 1;
- return getPage(isBlank, effIndex);
- } else {
- throw new IllegalArgumentException(
- "Illegal value for relativeTo: " + relativeTo);
- }
- }
- private Page getPage(boolean isBlank, int index) {
- boolean isLastPage = (lastPageIndex >= 0) && (index == lastPageIndex);
- if (log.isTraceEnabled()) {
- log.trace("getPage(" + index + " " + (isBlank ? "blank" : "non-blank")
- + (isLastPage ? " <LAST>" : "") + ")");
- }
- int intIndex = index - startPageOfPageSequence;
- if (log.isTraceEnabled()) {
- if (isBlank) {
- log.trace("blank page requested: " + index);
- }
- if (isLastPage) {
- log.trace("last page requested: " + index);
- }
- }
- while (intIndex >= cachedPages.size()) {
- if (log.isTraceEnabled()) {
- log.trace("Caching " + index);
- }
- cacheNextPage(index, isBlank, isLastPage);
- }
- Page page = (Page)cachedPages.get(intIndex);
- boolean replace = false;
- if (page.getPageViewport().isBlank() != isBlank) {
- log.debug("blank condition doesn't match. Replacing PageViewport.");
- replace = true;
- }
- if ((isLastPage && indexOfCachedLastPage != intIndex)
- || (!isLastPage && indexOfCachedLastPage >= 0)) {
- log.debug("last page condition doesn't match. Replacing PageViewport.");
- replace = true;
- indexOfCachedLastPage = (isLastPage ? intIndex : -1);
- }
- if (replace) {
- disardCacheStartingWith(intIndex);
- page = cacheNextPage(index, isBlank, isLastPage);
- }
- return page;
- }
-
- private void disardCacheStartingWith(int index) {
- while (index < cachedPages.size()) {
- this.cachedPages.remove(cachedPages.size() - 1);
- if (!pageSeq.goToPreviousSimplePageMaster()) {
- log.warn("goToPreviousSimplePageMaster() on the first page called!");
- }
- }
- }
-
- private Page cacheNextPage(int index, boolean isBlank, boolean isLastPage) {
- try {
- String pageNumberString = pageSeq.makeFormattedPageNumber(index);
- SimplePageMaster spm = pageSeq.getNextSimplePageMaster(
- index, (startPageOfPageSequence == index), isLastPage, isBlank);
-
- Region body = spm.getRegion(FO_REGION_BODY);
- if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) {
- // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to
- // any region), but we don't support it yet.
- throw new FOPException("Flow '" + pageSeq.getMainFlow().getFlowName()
- + "' does not map to the region-body in page-master '"
- + spm.getMasterName() + "'. FOP presently "
- + "does not support this.");
- }
- Page page = new Page(spm, index, pageNumberString, isBlank);
- //Set unique key obtained from the AreaTreeHandler
- page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey());
- page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
- cachedPages.add(page);
- return page;
- } catch (FOPException e) {
- //TODO Maybe improve. It'll mean to propagate this exception up several
- //methods calls.
- throw new IllegalStateException(e.getMessage());
- }
- }
-
- }
-
/**
* Act upon the force-page-count trait,
* in relation to the initial-page-number trait of the following page-sequence.
*/
private void setupBasicLinkArea(LayoutManager parentLM, InlineArea area) {
// internal destinations take precedence:
- String idref = fobj.getInternalDestination();
- if (idref != null && idref.length() > 0) {
+ if (fobj.hasInternalDestination()) {
+ String idref = fobj.getInternalDestination();
PageSequenceLayoutManager pslm = getPSLM();
// the INTERNAL_LINK trait is added by the LinkResolver
// if and when the link is resolved:
if (!res.isResolved()) {
pslm.addUnresolvedArea(idref, res);
}
- } else {
- String extdest = fobj.getExternalDestination();
- if (extdest != null) {
- String url = URISpecification.getURL(extdest);
- if (url.length() > 0) {
- area.addTrait(Trait.EXTERNAL_LINK, url);
- }
+ } else if (fobj.hasExternalDestination()) {
+ String url = URISpecification.getURL(fobj.getExternalDestination());
+ if (url.length() > 0) {
+ area.addTrait(Trait.EXTERNAL_LINK, url);
}
}
}
RtfHyperLink link = textrun.addHyperlink(new RtfAttributes());
- if (basicLink.getExternalDestination() != null) {
+ if (basicLink.hasExternalDestination()) {
link.setExternalURL(basicLink.getExternalDestination());
} else {
link.setInternalURL(basicLink.getInternalDestination());
<changes>
<release version="FOP Trunk">
+ <action context="code" dev="AD" type="update" fixes-bug="42089" due-to="Adrian Cumiskey">
+ Code cleanup and restructuring.
+ </action>
+ <action context="Code" dev="AD" type="add">
+ Slight improvement of relative font-weight handling in the properties
+ package.
+ </action>
<action context="Code" dev="JM" type="update">
Updated PDF/A-1b support according to ISO-19005-1:2005/Cor.1:2007.
</action>