|
|
@@ -53,36 +53,23 @@ import org.apache.fop.fo.extensions.destination.Destination; |
|
|
|
|
|
|
|
/** |
|
|
|
* Area tree handler for formatting objects. |
|
|
|
* |
|
|
|
* Concepts: |
|
|
|
* The area tree is to be as small as possible. With minimal classes |
|
|
|
* and data to fully represent an area tree for formatting objects. |
|
|
|
* The area tree needs to be simple to render and follow the spec |
|
|
|
* closely. |
|
|
|
* This area tree has the concept of page sequences. |
|
|
|
* Wherever possible information is discarded or optimized to |
|
|
|
* keep memory use low. The data is also organized to make it |
|
|
|
* possible for renderers to minimize their output. |
|
|
|
* A page can be saved if not fully resolved and once rendered |
|
|
|
* a page contains only size and id reference information. |
|
|
|
* The area tree pages are organized in a model that depends on the |
|
|
|
* |
|
|
|
* Concepts: The area tree is to be as small as possible. With minimal classes |
|
|
|
* and data to fully represent an area tree for formatting objects. The area |
|
|
|
* tree needs to be simple to render and follow the spec closely. This area tree |
|
|
|
* has the concept of page sequences. Wherever possible information is discarded |
|
|
|
* or optimized to keep memory use low. The data is also organized to make it |
|
|
|
* possible for renderers to minimize their output. A page can be saved if not |
|
|
|
* fully resolved and once rendered a page contains only size and id reference |
|
|
|
* information. The area tree pages are organized in a model that depends on the |
|
|
|
* type of renderer. |
|
|
|
*/ |
|
|
|
public class AreaTreeHandler extends FOEventHandler { |
|
|
|
|
|
|
|
private static Log log = LogFactory.getLog(AreaTreeHandler.class); |
|
|
|
|
|
|
|
// show statistics after document complete? |
|
|
|
private boolean outputStatistics; |
|
|
|
|
|
|
|
// for statistics gathering |
|
|
|
private Runtime runtime; |
|
|
|
|
|
|
|
// heap memory allocated (for statistics) |
|
|
|
private long initialMemory; |
|
|
|
/** debug statistics */ |
|
|
|
private Statistics statistics = null; |
|
|
|
|
|
|
|
// time used in rendering (for statistics) |
|
|
|
private long startTime; |
|
|
|
private static Log log = LogFactory.getLog(AreaTreeHandler.class); |
|
|
|
|
|
|
|
// the LayoutManager maker |
|
|
|
private LayoutManagerMaker lmMaker; |
|
|
@@ -93,66 +80,68 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
// 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 |
|
|
|
// 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. |
|
|
|
// The formatting results to be handed back to the caller. |
|
|
|
private FormattingResults results = new FormattingResults(); |
|
|
|
|
|
|
|
private PageSequenceLayoutManager prevPageSeqLM; |
|
|
|
|
|
|
|
private int idGen = 0; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Constructor. |
|
|
|
* |
|
|
|
* @param userAgent FOUserAgent object for process |
|
|
|
* @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). |
|
|
|
* @param outputFormat the MIME type of the output format to use (ex. |
|
|
|
* "application/pdf"). |
|
|
|
* @param stream OutputStream |
|
|
|
* @throws FOPException if the RenderPagesModel cannot be created |
|
|
|
*/ |
|
|
|
public AreaTreeHandler (FOUserAgent userAgent, String outputFormat, |
|
|
|
OutputStream stream) throws FOPException { |
|
|
|
public AreaTreeHandler(FOUserAgent userAgent, String outputFormat, |
|
|
|
OutputStream stream) throws FOPException { |
|
|
|
super(userAgent); |
|
|
|
|
|
|
|
setupModel(userAgent, outputFormat, stream); |
|
|
|
|
|
|
|
|
|
|
|
lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride(); |
|
|
|
if (lmMaker == null) { |
|
|
|
lmMaker = new LayoutManagerMapping(); |
|
|
|
} |
|
|
|
|
|
|
|
outputStatistics = log.isDebugEnabled(); |
|
|
|
|
|
|
|
if (outputStatistics) { |
|
|
|
runtime = Runtime.getRuntime(); |
|
|
|
if (log.isDebugEnabled()) { |
|
|
|
statistics = new Statistics(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets up the AreaTreeModel instance for use by the AreaTreeHandler. |
|
|
|
* |
|
|
|
* @param userAgent FOUserAgent object for process |
|
|
|
* @param outputFormat the MIME type of the output format to use (ex. "application/pdf"). |
|
|
|
* @param outputFormat the MIME type of the output format to use (ex. |
|
|
|
* "application/pdf"). |
|
|
|
* @param stream OutputStream |
|
|
|
* @throws FOPException if the RenderPagesModel cannot be created |
|
|
|
*/ |
|
|
|
protected void setupModel(FOUserAgent userAgent, String outputFormat, |
|
|
|
protected void setupModel(FOUserAgent userAgent, String outputFormat, |
|
|
|
OutputStream stream) throws FOPException { |
|
|
|
model = new RenderPagesModel(userAgent, outputFormat, fontInfo, |
|
|
|
stream); |
|
|
|
model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Get the area tree model for this area tree. |
|
|
|
* |
|
|
|
* |
|
|
|
* @return AreaTreeModel the model being used for this area tree |
|
|
|
*/ |
|
|
|
public AreaTreeModel getAreaTreeModel() { |
|
|
@@ -161,17 +150,19 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
|
|
|
|
/** |
|
|
|
* Get the LayoutManager maker for this area tree. |
|
|
|
* |
|
|
|
* @return LayoutManagerMaker the LayoutManager maker being used for this area tree |
|
|
|
* |
|
|
|
* @return LayoutManagerMaker the LayoutManager maker being used for this |
|
|
|
* area tree |
|
|
|
*/ |
|
|
|
public LayoutManagerMaker getLayoutManagerMaker() { |
|
|
|
return lmMaker; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 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. |
|
|
|
* 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 |
|
|
|
*/ |
|
|
@@ -185,22 +176,23 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
idLocations.put(id, pvList); |
|
|
|
pvList.add(pv); |
|
|
|
|
|
|
|
/* |
|
|
|
* See if this ID is in the unresolved idref list, if so |
|
|
|
* resolve Resolvable objects tied to it. |
|
|
|
/* |
|
|
|
* 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); |
|
|
|
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. |
|
|
|
* 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) { |
|
|
@@ -209,23 +201,25 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
} |
|
|
|
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. |
|
|
|
* 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) { |
|
|
@@ -236,9 +230,10 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
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 |
|
|
|
*/ |
|
|
@@ -248,6 +243,7 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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 |
|
|
@@ -270,6 +266,7 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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) { |
|
|
@@ -283,9 +280,10 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 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 |
|
|
|
*/ |
|
|
@@ -294,8 +292,8 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get information about the rendered output, like |
|
|
|
* number of pages created. |
|
|
|
* Get information about the rendered output, like number of pages created. |
|
|
|
* |
|
|
|
* @return the results structure |
|
|
|
*/ |
|
|
|
public FormattingResults getResults() { |
|
|
@@ -304,6 +302,7 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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 |
|
|
|
*/ |
|
|
@@ -318,16 +317,16 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Prepare AreaTreeHandler for document processing |
|
|
|
* This is called from FOTreeBuilder.startDocument() |
|
|
|
* |
|
|
|
* @throws SAXException if there is an error |
|
|
|
* Prepare AreaTreeHandler for document processing This is called from |
|
|
|
* FOTreeBuilder.startDocument() |
|
|
|
* |
|
|
|
* @throws SAXException |
|
|
|
* if there is an error |
|
|
|
*/ |
|
|
|
public void startDocument() throws SAXException { |
|
|
|
//Initialize statistics |
|
|
|
if (outputStatistics) { |
|
|
|
initialMemory = runtime.totalMemory() - runtime.freeMemory(); |
|
|
|
startTime = System.currentTimeMillis(); |
|
|
|
// Initialize statistics |
|
|
|
if (statistics != null) { |
|
|
|
statistics.start(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -344,40 +343,39 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
|
|
|
|
/** |
|
|
|
* @see org.apache.fop.fo.FOEventHandler |
|
|
|
* @param pageSequence is the pageSequence being started |
|
|
|
* */ |
|
|
|
* @param pageSequence |
|
|
|
* is the pageSequence being started |
|
|
|
*/ |
|
|
|
public void startPageSequence(PageSequence pageSequence) { |
|
|
|
rootFObj = pageSequence.getRoot(); |
|
|
|
finishPrevPageSequence(pageSequence.getInitialPageNumber()); |
|
|
|
pageSequence.initPageNumber(); |
|
|
|
//extension attachments from fo:root |
|
|
|
// extension attachments from fo:root |
|
|
|
wrapAndAddExtensionAttachments(rootFObj.getExtensionAttachments()); |
|
|
|
//extension attachments from fo:declarations |
|
|
|
// extension attachments from fo:declarations |
|
|
|
if (rootFObj.getDeclarations() != null) { |
|
|
|
wrapAndAddExtensionAttachments(rootFObj.getDeclarations().getExtensionAttachments()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void wrapAndAddExtensionAttachments(List list) { |
|
|
|
Iterator i = list.iterator(); |
|
|
|
while (i.hasNext()) { |
|
|
|
ExtensionAttachment attachment = (ExtensionAttachment)i.next(); |
|
|
|
ExtensionAttachment attachment = (ExtensionAttachment) i.next(); |
|
|
|
addOffDocumentItem(new OffDocumentExtensionAttachment(attachment)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* End the PageSequence. |
|
|
|
* The PageSequence formats Pages and adds them to the AreaTree. |
|
|
|
* The area tree then handles what happens with the pages. |
|
|
|
* |
|
|
|
* End the PageSequence. The PageSequence formats Pages and adds them to the |
|
|
|
* AreaTree. The area tree then handles what happens with the pages. |
|
|
|
* |
|
|
|
* @param pageSequence the page sequence ending |
|
|
|
*/ |
|
|
|
public void endPageSequence(PageSequence pageSequence) { |
|
|
|
|
|
|
|
if (outputStatistics) { |
|
|
|
long memoryNow = runtime.totalMemory() - runtime.freeMemory(); |
|
|
|
log.debug("Current heap size: " + (memoryNow / 1024L) + "Kb"); |
|
|
|
if (statistics != null) { |
|
|
|
statistics.end(); |
|
|
|
} |
|
|
|
|
|
|
|
// If no main flow, nothing to layout! |
|
|
@@ -388,28 +386,28 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
pageSLM.activateLayout(); |
|
|
|
// preserve the current PageSequenceLayoutManger for the |
|
|
|
// force-page-count check at the beginning of the next PageSequence |
|
|
|
prevPageSeqLM = pageSLM; |
|
|
|
prevPageSeqLM = pageSLM; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Called by the PageSequenceLayoutManager when it is finished with a page-sequence. |
|
|
|
* Called by the PageSequenceLayoutManager when it is finished with a |
|
|
|
* page-sequence. |
|
|
|
* |
|
|
|
* @param pageSequence the page-sequence just finished |
|
|
|
* @param pageCount The number of pages generated for the page-sequence |
|
|
|
*/ |
|
|
|
public void notifyPageSequenceFinished(PageSequence pageSequence, |
|
|
|
int pageCount) { |
|
|
|
this.results.haveFormattedPageSequence(pageSequence, |
|
|
|
pageCount); |
|
|
|
int pageCount) { |
|
|
|
this.results.haveFormattedPageSequence(pageSequence, pageCount); |
|
|
|
if (log.isDebugEnabled()) { |
|
|
|
log.debug("Last page-sequence produced " |
|
|
|
+ pageCount + " pages."); |
|
|
|
log.debug("Last page-sequence produced " + pageCount + " pages."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* End the document. |
|
|
|
* |
|
|
|
* |
|
|
|
* @throws SAXException if there is some error |
|
|
|
*/ |
|
|
|
public void endDocument() throws SAXException { |
|
|
@@ -418,8 +416,8 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
// process fox:destination elements |
|
|
|
ArrayList destinationList = rootFObj.getDestinationList(); |
|
|
|
if (destinationList != null) { |
|
|
|
while(destinationList.size() > 0) { |
|
|
|
Destination destination = (Destination)destinationList.remove(0); |
|
|
|
while (destinationList.size() > 0) { |
|
|
|
Destination destination = (Destination) destinationList.remove(0); |
|
|
|
DestinationData destinationData = new DestinationData(destination); |
|
|
|
addOffDocumentItem(destinationData); |
|
|
|
} |
|
|
@@ -430,35 +428,23 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
BookmarkData data = new BookmarkData(bookmarkTree); |
|
|
|
addOffDocumentItem(data); |
|
|
|
if (!data.isResolved()) { |
|
|
|
//bookmarks did not fully resolve, add anyway. (hacky? yeah) |
|
|
|
// bookmarks did not fully resolve, add anyway. (hacky? yeah) |
|
|
|
model.handleOffDocumentItem(data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
model.endDocument(); |
|
|
|
|
|
|
|
if (outputStatistics) { |
|
|
|
long memoryNow = runtime.totalMemory() - runtime.freeMemory(); |
|
|
|
long memoryUsed = (memoryNow - initialMemory) / 1024L; |
|
|
|
long timeUsed = System.currentTimeMillis() - startTime; |
|
|
|
int pageCount = rootFObj.getTotalPagesGenerated(); |
|
|
|
log.debug("Initial heap size: " + (initialMemory / 1024L) + "Kb"); |
|
|
|
log.debug("Current heap size: " + (memoryNow / 1024L) + "Kb"); |
|
|
|
log.debug("Total memory used: " + memoryUsed + "Kb"); |
|
|
|
log.debug("Total time used: " + timeUsed + "ms"); |
|
|
|
log.debug("Pages rendered: " + pageCount); |
|
|
|
if (pageCount > 0) { |
|
|
|
long perPage = (timeUsed / pageCount); |
|
|
|
long ppm = (timeUsed != 0 ? Math.round(60000 * pageCount / (double)timeUsed) : -1); |
|
|
|
log.debug("Avg render time: " + perPage + "ms/page (" + ppm + "pages/min)"); |
|
|
|
} |
|
|
|
if (statistics != null) { |
|
|
|
statistics.logResults(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Add a OffDocumentItem to the area tree model |
|
|
|
* This checks if the OffDocumentItem is resolvable and attempts |
|
|
|
* to resolve or add the resolvable ids for later resolution. |
|
|
|
* Add a OffDocumentItem to the area tree model. This checks if the |
|
|
|
* OffDocumentItem is resolvable and attempts to resolve or add the |
|
|
|
* resolvable ids for later resolution. |
|
|
|
* |
|
|
|
* @param odi the OffDocumentItem to add. |
|
|
|
*/ |
|
|
|
private void addOffDocumentItem(OffDocumentItem odi) { |
|
|
@@ -469,8 +455,8 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
if (idLocations.containsKey(ids[count])) { |
|
|
|
res.resolveIDRef(ids[count], (List) idLocations.get(ids[count])); |
|
|
|
} else { |
|
|
|
log.warn(odi.getName() + ": Unresolved id reference \"" |
|
|
|
+ ids[count] + "\" found."); |
|
|
|
log.warn(odi.getName() + ": Unresolved id reference \"" |
|
|
|
+ ids[count] + "\" found."); |
|
|
|
addUnresolvedIDRef(ids[count], res); |
|
|
|
} |
|
|
|
} |
|
|
@@ -482,15 +468,60 @@ public class AreaTreeHandler extends FOEventHandler { |
|
|
|
model.handleOffDocumentItem(odi); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Generates and returns a unique key for a page viewport. |
|
|
|
* |
|
|
|
* @return the generated key. |
|
|
|
*/ |
|
|
|
public String generatePageViewportKey() { |
|
|
|
this.idGen++; |
|
|
|
return "P" + this.idGen; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Gather statistics when log is debug |
|
|
|
*/ |
|
|
|
private final class Statistics { |
|
|
|
// for statistics gathering |
|
|
|
private Runtime runtime; |
|
|
|
|
|
|
|
// heap memory allocated (for statistics) |
|
|
|
private long initialMemory; |
|
|
|
|
|
|
|
// time used in rendering (for statistics) |
|
|
|
private long startTime; |
|
|
|
|
|
|
|
private Statistics() { |
|
|
|
runtime = Runtime.getRuntime(); |
|
|
|
} |
|
|
|
|
|
|
|
public void start() { |
|
|
|
initialMemory = runtime.totalMemory() - runtime.freeMemory(); |
|
|
|
startTime = System.currentTimeMillis(); |
|
|
|
} |
|
|
|
|
|
|
|
public void end() { |
|
|
|
long memoryNow = runtime.totalMemory() - runtime.freeMemory(); |
|
|
|
log.debug("Current heap size: " + (memoryNow / 1024L) + "KB"); |
|
|
|
} |
|
|
|
|
|
|
|
public void logResults() { |
|
|
|
long memoryNow = runtime.totalMemory() - runtime.freeMemory(); |
|
|
|
long memoryUsed = (memoryNow - initialMemory) / 1024L; |
|
|
|
long timeUsed = System.currentTimeMillis() - startTime; |
|
|
|
int pageCount = rootFObj.getTotalPagesGenerated(); |
|
|
|
log.debug("Initial heap size: " + (initialMemory / 1024L) + "KB"); |
|
|
|
log.debug("Current heap size: " + (memoryNow / 1024L) + "KB"); |
|
|
|
log.debug("Total memory used: " + memoryUsed + "KB"); |
|
|
|
log.debug("Total time used: " + timeUsed + "ms"); |
|
|
|
log.debug("Pages rendered: " + pageCount); |
|
|
|
if (pageCount > 0) { |
|
|
|
long perPage = (timeUsed / pageCount); |
|
|
|
long ppm = (timeUsed != 0 ? Math.round(60000 * pageCount |
|
|
|
/ (double) timeUsed) : -1); |
|
|
|
log.debug("Avg render time: " + perPage + "ms/page (" + ppm + "pages/min)"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |