git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@554094 13f79535-47bb-0310-9956-ffa450edef68tags/fop-0_94
@@ -21,12 +21,7 @@ package org.apache.fop.area; | |||
// 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 | |||
@@ -65,34 +60,24 @@ import org.apache.fop.fo.extensions.destination.Destination; | |||
* 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(); | |||
@@ -120,6 +105,8 @@ public class AreaTreeHandler extends FOEventHandler { | |||
lmMaker = new LayoutManagerMapping(); | |||
} | |||
idTracker = new IDTracker(); | |||
if (log.isDebugEnabled()) { | |||
statistics = new Statistics(); | |||
} | |||
@@ -159,137 +146,12 @@ public class AreaTreeHandler extends FOEventHandler { | |||
} | |||
/** | |||
* 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; | |||
} | |||
/** | |||
@@ -301,22 +163,6 @@ public class AreaTreeHandler extends FOEventHandler { | |||
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() | |||
@@ -453,12 +299,13 @@ public class AreaTreeHandler extends FOEventHandler { | |||
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 | |||
@@ -481,9 +328,86 @@ public class AreaTreeHandler extends FOEventHandler { | |||
} | |||
/** | |||
* 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; | |||
@@ -493,21 +417,34 @@ public class AreaTreeHandler extends FOEventHandler { | |||
// 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; |
@@ -0,0 +1,203 @@ | |||
/* | |||
* 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); | |||
} | |||
} |
@@ -145,27 +145,28 @@ public class RenderPagesModel extends AreaTreeModel { | |||
/** | |||
* 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."); | |||
} | |||
@@ -174,7 +175,7 @@ public class RenderPagesModel extends AreaTreeModel { | |||
// 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 |
@@ -60,6 +60,10 @@ public abstract class FObj extends FONode implements Constants { | |||
/** 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. | |||
@@ -136,6 +140,17 @@ public abstract class FObj extends FONode implements Constants { | |||
* @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); | |||
} | |||
} | |||
/** | |||
@@ -147,7 +162,7 @@ public abstract class FObj extends FONode implements Constants { | |||
* @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)) { | |||
@@ -190,7 +205,7 @@ public abstract class FObj extends FONode implements Constants { | |||
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, | |||
@@ -469,7 +484,16 @@ public abstract class FObj extends FONode implements Constants { | |||
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; |
@@ -34,7 +34,6 @@ import org.apache.fop.fo.properties.KeepProperty; | |||
*/ | |||
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; | |||
@@ -54,17 +53,10 @@ public abstract class AbstractListItemPart extends FObj { | |||
* @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;)+ | |||
@@ -106,11 +98,5 @@ public abstract class AbstractListItemPart extends FObj { | |||
public KeepProperty getKeepTogether() { | |||
return keepTogether; | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
} | |||
@@ -128,6 +128,20 @@ public class BasicLink extends Inline { | |||
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"; |
@@ -32,8 +32,6 @@ import org.apache.fop.fo.FObjMixed; | |||
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; | |||
@@ -52,8 +50,6 @@ public class Block extends FObjMixed { | |||
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; | |||
@@ -64,7 +60,6 @@ public class Block extends FObjMixed { | |||
private Color color; | |||
private int hyphenationKeep; | |||
private Numeric hyphenationLadderCount; | |||
private String id; | |||
private int intrusionDisplace; | |||
private KeepProperty keepTogether; | |||
private KeepProperty keepWithNext; | |||
@@ -84,6 +79,8 @@ public class Block extends FObjMixed { | |||
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; | |||
@@ -101,8 +98,7 @@ public class Block extends FObjMixed { | |||
* @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(); | |||
@@ -114,7 +110,6 @@ public class Block extends FObjMixed { | |||
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(); | |||
@@ -139,7 +134,7 @@ public class Block extends FObjMixed { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
getFOEventHandler().startBlock(this); | |||
} | |||
@@ -231,13 +226,6 @@ public class Block extends FObjMixed { | |||
return color; | |||
} | |||
/** | |||
* @return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the "line-height" property. | |||
*/ | |||
@@ -347,20 +335,6 @@ public class Block extends FObjMixed { | |||
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. | |||
*/ |
@@ -48,7 +48,6 @@ public class BlockContainer extends FObj { | |||
// private ToBeImplementedProperty clip; | |||
private int displayAlign; | |||
private Length height; | |||
private String id; | |||
private LengthRangeProperty inlineProgressionDimension; | |||
private KeepProperty keepTogether; | |||
private KeepProperty keepWithNext; | |||
@@ -77,6 +76,7 @@ public class BlockContainer extends FObj { | |||
* @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(); | |||
@@ -86,7 +86,6 @@ public class BlockContainer extends FObj { | |||
// 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(); | |||
@@ -102,7 +101,7 @@ public class BlockContainer extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
getFOEventHandler().startBlockContainer(this); | |||
} | |||
@@ -203,13 +202,6 @@ public class BlockContainer extends FObj { | |||
return keepTogether; | |||
} | |||
/** | |||
* @return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the "inline-progression-dimension" property. | |||
*/ |
@@ -68,7 +68,6 @@ public class Character extends FObj { | |||
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 */ | |||
@@ -106,6 +105,7 @@ public class Character extends FObj { | |||
* @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(); | |||
@@ -118,7 +118,6 @@ public class Character extends FObj { | |||
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(); | |||
@@ -130,7 +129,7 @@ public class Character extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
getFOEventHandler().character(this); | |||
} | |||
@@ -213,13 +212,6 @@ public class Character extends FObj { | |||
return dominantBaseline; | |||
} | |||
/** | |||
* @return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the "letter-spacing" property. | |||
*/ |
@@ -83,7 +83,7 @@ public class ExternalGraphic extends AbstractGraphics { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(getId()); | |||
super.startOfNode(); | |||
getFOEventHandler().image(this); | |||
} | |||
@@ -69,19 +69,12 @@ public class InitialPropertySet extends FObj { | |||
* @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 |
@@ -42,7 +42,6 @@ public class Inline extends InlineLevel { | |||
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; | |||
@@ -74,13 +73,14 @@ public class Inline extends InlineLevel { | |||
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. | |||
*/ | |||
@@ -99,9 +99,7 @@ public class Inline extends InlineLevel { | |||
} | |||
} | |||
checkId(id); | |||
getFOEventHandler().startInline(this); | |||
getFOEventHandler().startInline(this); | |||
} | |||
/** | |||
@@ -140,13 +138,6 @@ public class Inline extends InlineLevel { | |||
} | |||
} | |||
/** | |||
* Return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the "alignment-adjust" property | |||
*/ |
@@ -46,7 +46,6 @@ public class InlineContainer extends FObj { | |||
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; | |||
@@ -79,22 +78,15 @@ public class InlineContainer extends FObj { | |||
* @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;)+ | |||
@@ -156,13 +148,6 @@ public class InlineContainer extends FObj { | |||
return lineHeight; | |||
} | |||
/** | |||
* @return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||
public String getLocalName() { | |||
return "inline-container"; |
@@ -60,6 +60,7 @@ public abstract class InlineLevel extends FObjMixed { | |||
* @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(); |
@@ -49,13 +49,6 @@ public class InstreamForeignObject extends AbstractGraphics { | |||
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. |
@@ -41,7 +41,6 @@ public class Leader extends InlineLevel { | |||
private int alignmentBaseline; | |||
private Length baselineShift; | |||
private int dominantBaseline; | |||
private String id; | |||
private int leaderAlignment; | |||
private LengthRangeProperty leaderLength; | |||
private int leaderPattern; | |||
@@ -75,7 +74,6 @@ public class Leader extends InlineLevel { | |||
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(); | |||
@@ -103,21 +101,6 @@ public class Leader extends InlineLevel { | |||
// 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. | |||
*/ |
@@ -43,7 +43,6 @@ public class ListBlock extends FObj { | |||
private CommonMarginBlock commonMarginBlock; | |||
private int breakAfter; | |||
private int breakBefore; | |||
private String id; | |||
private KeepProperty keepTogether; | |||
private KeepProperty keepWithNext; | |||
private KeepProperty keepWithPrevious; | |||
@@ -74,11 +73,11 @@ public class ListBlock extends FObj { | |||
* @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(); | |||
@@ -91,7 +90,7 @@ public class ListBlock extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
getFOEventHandler().startList(this); | |||
} | |||
@@ -177,11 +176,6 @@ public class ListBlock extends FObj { | |||
return orphanContentLimit; | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||
public String getLocalName() { | |||
return "list-block"; |
@@ -42,7 +42,6 @@ public class ListItem extends FObj { | |||
private CommonMarginBlock commonMarginBlock; | |||
private int breakAfter; | |||
private int breakBefore; | |||
private String id; | |||
private KeepProperty keepTogether; | |||
private KeepProperty keepWithNext; | |||
private KeepProperty keepWithPrevious; | |||
@@ -68,11 +67,11 @@ public class ListItem extends FObj { | |||
* @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(); | |||
@@ -82,7 +81,7 @@ public class ListItem extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
getFOEventHandler().startListItem(this); | |||
} | |||
@@ -183,13 +182,6 @@ public class ListItem extends FObj { | |||
return keepTogether; | |||
} | |||
/** | |||
* @return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the label of the list item | |||
*/ |
@@ -57,19 +57,12 @@ public class MultiCase extends FObj { | |||
* @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. | |||
*/ |
@@ -25,7 +25,6 @@ import org.xml.sax.Locator; | |||
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; | |||
@@ -34,7 +33,6 @@ 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 | |||
@@ -57,20 +55,6 @@ public class MultiProperties extends FObj { | |||
} | |||
} | |||
/** | |||
* @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. | |||
@@ -104,13 +88,6 @@ public class MultiProperties extends FObj { | |||
invalidChildError(loc, nsURI, localName); | |||
} | |||
} | |||
/** | |||
* Return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||
public String getLocalName() { |
@@ -33,7 +33,6 @@ import org.apache.fop.fo.ValidationException; | |||
*/ | |||
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 | |||
@@ -55,17 +54,10 @@ public class MultiPropertySet extends FObj { | |||
* @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 | |||
@@ -75,11 +67,6 @@ public class MultiPropertySet extends FObj { | |||
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"; |
@@ -36,7 +36,6 @@ import org.apache.fop.fo.properties.CommonAccessibility; | |||
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 | |||
@@ -59,16 +58,10 @@ public class MultiSwitch extends FObj { | |||
* @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. | |||
@@ -91,11 +84,6 @@ public class MultiSwitch extends FObj { | |||
} | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||
public String getLocalName() { | |||
return "multi-switch"; |
@@ -51,7 +51,6 @@ public class PageNumber extends FObj { | |||
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 */ | |||
@@ -87,13 +86,13 @@ public class PageNumber extends FObj { | |||
* @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(); | |||
@@ -107,7 +106,7 @@ public class PageNumber extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
getFOEventHandler().startPageNumber(this); | |||
} | |||
@@ -142,11 +141,6 @@ public class PageNumber extends FObj { | |||
return commonBorderPaddingBackground; | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @return the "text-decoration" property. */ | |||
public CommonTextDecoration getTextDecoration() { | |||
return textDecoration; |
@@ -54,7 +54,6 @@ public class PageNumberCitation extends FObj { | |||
private int alignmentBaseline; | |||
private Length baselineShift; | |||
private int dominantBaseline; | |||
private String id; | |||
// private ToBeImplementedProperty letterSpacing; | |||
private SpaceProperty lineHeight; | |||
private String refId; | |||
@@ -91,13 +90,13 @@ public class PageNumberCitation extends FObj { | |||
* @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(); | |||
@@ -112,7 +111,7 @@ public class PageNumberCitation extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
if (refId.equals("")) { | |||
missingPropertyError("ref-id"); | |||
} | |||
@@ -182,11 +181,6 @@ public class PageNumberCitation extends FObj { | |||
return lineHeight; | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @return the "ref-id" property. */ | |||
public String getRefId() { | |||
return refId; |
@@ -54,7 +54,6 @@ public class Table extends TableFObj { | |||
private LengthPairProperty borderSeparation; | |||
private int breakAfter; | |||
private int breakBefore; | |||
private String id; | |||
private LengthRangeProperty inlineProgressionDimension; | |||
private KeepProperty keepTogether; | |||
private KeepProperty keepWithNext; | |||
@@ -110,6 +109,7 @@ public class Table extends TableFObj { | |||
* @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(); | |||
@@ -117,7 +117,6 @@ public class Table extends TableFObj { | |||
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(); | |||
@@ -125,7 +124,6 @@ public class Table extends TableFObj { | |||
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(); | |||
@@ -161,7 +159,7 @@ public class Table extends TableFObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
getFOEventHandler().startTable(this); | |||
} | |||
@@ -466,11 +464,6 @@ public class Table extends TableFObj { | |||
return orphanContentLimit; | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||
public String getLocalName() { | |||
return "table"; |
@@ -40,7 +40,6 @@ import org.apache.fop.fo.properties.KeepProperty; | |||
*/ | |||
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; | |||
@@ -75,20 +74,6 @@ public class TableAndCaption extends FObj { | |||
} | |||
} | |||
/** | |||
* @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. | |||
@@ -132,11 +117,6 @@ public class TableAndCaption extends FObj { | |||
} | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||
public String getLocalName() { | |||
return "table-and-caption"; |
@@ -44,7 +44,6 @@ public class TableCaption extends FObj { | |||
// 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; | |||
@@ -77,16 +76,9 @@ public class TableCaption extends FObj { | |||
* @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); | |||
} | |||
/** | |||
@@ -124,11 +116,6 @@ public class TableCaption extends FObj { | |||
} | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||
public String getLocalName() { | |||
return "table-caption"; |
@@ -46,7 +46,6 @@ public class TableCell extends TableFObj { | |||
private int displayAlign; | |||
private int emptyCells; | |||
private int endsRow; | |||
private String id; | |||
private int numberColumnsSpanned; | |||
private int numberRowsSpanned; | |||
private int startsRow; | |||
@@ -77,26 +76,24 @@ public class TableCell extends TableFObj { | |||
* @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); | |||
} | |||
@@ -163,13 +160,6 @@ public class TableCell extends TableFObj { | |||
return (this.emptyCells == EN_SHOW); | |||
} | |||
/** | |||
* @return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the "number-columns-spanned" property. | |||
*/ |
@@ -83,6 +83,7 @@ public abstract class TableFObj extends FObj { | |||
* @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(); |
@@ -47,7 +47,6 @@ public class TableRow extends TableFObj { | |||
private int breakAfter; | |||
private int breakBefore; | |||
private Length height; | |||
private String id; | |||
private KeepProperty keepTogether; | |||
private KeepProperty keepWithNext; | |||
private KeepProperty keepWithPrevious; | |||
@@ -80,7 +79,6 @@ public class TableRow extends TableFObj { | |||
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(); | |||
@@ -162,7 +160,7 @@ public class TableRow extends TableFObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
checkId(id); | |||
super.startOfNode(); | |||
getFOEventHandler().startRow(this); | |||
} | |||
@@ -192,13 +190,6 @@ public class TableRow extends TableFObj { | |||
} | |||
} | |||
/** | |||
* @return the "id" property. | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @return the "break-after" property. */ | |||
public int getBreakAfter() { | |||
return breakAfter; |
@@ -34,7 +34,6 @@ import org.xml.sax.Locator; | |||
*/ | |||
public class Wrapper extends FObjMixed { | |||
// The value of properties relevant for fo:wrapper. | |||
private String id; | |||
// End of property values | |||
// used for FO validation | |||
@@ -47,20 +46,6 @@ public class Wrapper extends FObjMixed { | |||
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;)* | |||
@@ -82,11 +67,6 @@ public class Wrapper extends FObjMixed { | |||
} | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||
public String getLocalName() { | |||
return "wrapper"; |
@@ -43,7 +43,6 @@ public class PageSequence extends FObj { | |||
private int letterValue; | |||
private char groupingSeparator; | |||
private int groupingSize; | |||
private String id; | |||
private Numeric initialPageNumber; | |||
private int forcePageCount; | |||
private String masterReference; | |||
@@ -96,13 +95,13 @@ public class PageSequence extends FObj { | |||
* @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(); | |||
@@ -116,6 +115,7 @@ public class PageSequence extends FObj { | |||
* @see org.apache.fop.fo.FONode#startOfNode() | |||
*/ | |||
protected void startOfNode() throws FOPException { | |||
super.startOfNode(); | |||
this.root = (Root) parent; | |||
flowMap = new java.util.HashMap(); | |||
@@ -133,7 +133,6 @@ public class PageSequence extends FObj { | |||
this.pageNumberGenerator = new PageNumberGenerator( | |||
format, groupingSeparator, groupingSize, letterValue); | |||
checkId(id); | |||
getFOEventHandler().startPageSequence(this); | |||
} | |||
@@ -394,11 +393,6 @@ public class PageSequence extends FObj { | |||
return (StaticContent) flowMap.get(name); | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* Accessor method for titleFO | |||
* @return titleFO for this object |
@@ -34,7 +34,6 @@ import org.apache.fop.fo.ValidationException; | |||
*/ | |||
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 | |||
@@ -50,18 +49,11 @@ public class PageSequenceWrapper extends FObj { | |||
* @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+) | |||
@@ -74,11 +66,6 @@ public class PageSequenceWrapper extends FObj { | |||
} | |||
} | |||
/** @return the "id" property. */ | |||
public String getId() { | |||
return id; | |||
} | |||
/** @return the "index-class" property. */ | |||
public String getIndexClass() { | |||
return indexClass; |
@@ -192,7 +192,7 @@ public abstract class AbstractBreaker { | |||
* algorithm. | |||
* @return the applicable PageProvider, or null if not applicable | |||
*/ | |||
protected PageSequenceLayoutManager.PageProvider getPageProvider() { | |||
protected PageProvider getPageProvider() { | |||
return null; | |||
} | |||
@@ -214,7 +214,7 @@ public abstract class AbstractBreaker { | |||
/** @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) { | |||
@@ -289,7 +289,7 @@ public abstract class AbstractBreaker { | |||
childLC.setBPAlignment(alignment); | |||
BlockSequence blockList; | |||
blockLists = new java.util.ArrayList(); | |||
this.blockLists = new java.util.ArrayList(); | |||
log.debug("PLM> flow BPD =" + flowBPD); | |||
@@ -298,7 +298,7 @@ public abstract class AbstractBreaker { | |||
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()); | |||
@@ -539,19 +539,17 @@ public abstract class AbstractBreaker { | |||
* 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; | |||
@@ -594,7 +592,7 @@ public abstract class AbstractBreaker { | |||
BlockSequence seq = null; | |||
seq = blockList.endBlockSequence(breakPosition); | |||
if (seq != null) { | |||
blockLists.add(seq); | |||
this.blockLists.add(seq); | |||
} | |||
} | |||
return nextSequenceStartsOn; |
@@ -21,7 +21,6 @@ package org.apache.fop.layoutmgr; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener; | |||
import org.apache.fop.traits.MinOptMax; | |||
/** | |||
@@ -37,7 +36,7 @@ public class BalancingColumnBreakingAlgorithm extends PageBreakingAlgorithm { | |||
private int idealPartLen; | |||
public BalancingColumnBreakingAlgorithm(LayoutManager topLevelLM, | |||
PageSequenceLayoutManager.PageProvider pageProvider, | |||
PageProvider pageProvider, | |||
PageBreakingLayoutListener layoutListener, | |||
int alignment, int alignmentLast, | |||
MinOptMax footnoteSeparatorLength, |
@@ -0,0 +1,542 @@ | |||
/* | |||
* 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; | |||
} | |||
} | |||
} |
@@ -38,7 +38,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
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; | |||
@@ -94,7 +94,7 @@ class PageBreakingAlgorithm extends BreakingAlgorithm { | |||
private boolean favorSinglePart = false; | |||
public PageBreakingAlgorithm(LayoutManager topLevelLM, | |||
PageSequenceLayoutManager.PageProvider pageProvider, | |||
PageProvider pageProvider, | |||
PageBreakingLayoutListener layoutListener, | |||
int alignment, int alignmentLast, | |||
MinOptMax footnoteSeparatorLength, |
@@ -0,0 +1,279 @@ | |||
/* | |||
* 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()); | |||
} | |||
} | |||
} |
@@ -21,39 +21,26 @@ package org.apache.fop.layoutmgr; | |||
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 | |||
@@ -77,23 +64,17 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
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 | |||
@@ -104,8 +85,9 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
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); | |||
} | |||
/** | |||
@@ -121,6 +103,13 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
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 | |||
@@ -150,10 +139,6 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
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); | |||
@@ -165,8 +150,8 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
* Finished the page-sequence and notifies everyone about it. | |||
*/ | |||
public void finishPageSequence() { | |||
if (!pageSeq.getId().equals("")) { | |||
areaTreeHandler.signalIDProcessed(pageSeq.getId()); | |||
if (pageSeq.hasId()) { | |||
idTracker.signalIDProcessed(pageSeq.getId()); | |||
} | |||
pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum, | |||
@@ -188,392 +173,6 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
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. | |||
@@ -583,6 +182,22 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
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 | |||
@@ -607,7 +222,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
* @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); | |||
} | |||
@@ -622,7 +237,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
* @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); | |||
} | |||
@@ -639,7 +254,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
*/ | |||
public void addIDToPage(String id) { | |||
if (id != null && id.length() > 0) { | |||
areaTreeHandler.associateIDWithPageViewport(id, curPage.getPageViewport()); | |||
idTracker.associateIDWithPageViewport(id, curPage.getPageViewport()); | |||
} | |||
} | |||
@@ -654,8 +269,8 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
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; | |||
@@ -668,7 +283,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
* @param id the id for which layout has finished | |||
*/ | |||
public void notifyEndOfLayout(String id) { | |||
areaTreeHandler.signalIDProcessed(id); | |||
idTracker.signalIDProcessed(id); | |||
} | |||
/** | |||
@@ -676,7 +291,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
* 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. | |||
* | |||
@@ -689,7 +304,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
*/ | |||
public void addUnresolvedArea(String id, Resolvable res) { | |||
curPage.getPageViewport().addUnresolvedIDRef(id, res); | |||
areaTreeHandler.addUnresolvedIDRef(id, curPage.getPageViewport()); | |||
idTracker.addUnresolvedIDRef(id, curPage.getPageViewport()); | |||
} | |||
/** | |||
@@ -750,7 +365,14 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
} | |||
} | |||
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(); | |||
} | |||
@@ -797,7 +419,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
// 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()) { | |||
@@ -806,320 +428,7 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
} | |||
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. |
@@ -58,8 +58,8 @@ public class BasicLinkLayoutManager extends InlineLayoutManager { | |||
*/ | |||
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: | |||
@@ -68,13 +68,10 @@ public class BasicLinkLayoutManager extends InlineLayoutManager { | |||
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); | |||
} | |||
} | |||
} |
@@ -1093,7 +1093,7 @@ public class RTFHandler extends FOEventHandler { | |||
RtfHyperLink link = textrun.addHyperlink(new RtfAttributes()); | |||
if (basicLink.getExternalDestination() != null) { | |||
if (basicLink.hasExternalDestination()) { | |||
link.setExternalURL(basicLink.getExternalDestination()); | |||
} else { | |||
link.setInternalURL(basicLink.getInternalDestination()); |
@@ -28,6 +28,13 @@ | |||
<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> |