1 17 18 19 20 package org.apache.fop.area; 21 22 import java.io.OutputStream ; 24 import java.util.ArrayList ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.HashMap ; 28 import java.util.Set ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 32 import org.xml.sax.SAXException ; 34 35 import org.apache.commons.logging.Log; 37 import org.apache.commons.logging.LogFactory; 38 import org.apache.fop.apps.FOPException; 39 import org.apache.fop.apps.FOUserAgent; 40 import org.apache.fop.apps.FormattingResults; 41 import org.apache.fop.datatypes.Numeric; 42 import org.apache.fop.fo.FOEventHandler; 43 import org.apache.fop.fo.extensions.ExtensionAttachment; 44 import org.apache.fop.fo.pagination.PageSequence; 45 import org.apache.fop.fo.pagination.Root; 46 import org.apache.fop.fo.pagination.bookmarks.BookmarkTree; 47 import org.apache.fop.layoutmgr.PageSequenceLayoutManager; 48 import org.apache.fop.layoutmgr.LayoutManagerMaker; 49 import org.apache.fop.layoutmgr.LayoutManagerMapping; 50 51 68 public class AreaTreeHandler extends FOEventHandler { 69 70 private static Log log = LogFactory.getLog(AreaTreeHandler.class); 71 72 private boolean outputStatistics; 74 75 private Runtime runtime; 77 78 private long initialMemory; 80 81 private long startTime; 83 84 private LayoutManagerMaker lmMaker; 86 87 88 protected AreaTreeModel model; 89 90 private Root rootFObj; 92 93 private Map idLocations = new HashMap (); 97 98 private Map unresolvedIDRefs = new HashMap (); 101 102 private Set unfinishedIDs = new HashSet (); 103 private Set alreadyResolvedIDs = new HashSet (); 104 105 private FormattingResults results = new FormattingResults(); 107 108 private PageSequenceLayoutManager prevPageSeqLM; 109 110 private int idGen = 0; 111 112 119 public AreaTreeHandler (FOUserAgent userAgent, String outputFormat, 120 OutputStream stream) throws FOPException { 121 super(userAgent); 122 123 setupModel(userAgent, outputFormat, stream); 124 125 lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride(); 126 if (lmMaker == null) { 127 lmMaker = new LayoutManagerMapping(); 128 } 129 130 outputStatistics = log.isDebugEnabled(); 131 132 if (outputStatistics) { 133 runtime = Runtime.getRuntime(); 134 } 135 } 136 137 144 protected void setupModel(FOUserAgent userAgent, String outputFormat, 145 OutputStream stream) throws FOPException { 146 model = new RenderPagesModel(userAgent, outputFormat, fontInfo, 147 stream); 148 } 149 150 155 public AreaTreeModel getAreaTreeModel() { 156 return model; 157 } 158 159 164 public LayoutManagerMaker getLayoutManagerMaker() { 165 return lmMaker; 166 } 167 168 175 public void associateIDWithPageViewport(String id, PageViewport pv) { 176 if (log.isDebugEnabled()) { 177 log.debug("associateIDWithPageViewport(" + id + ", " + pv + ")"); 178 } 179 List pvList = (List ) idLocations.get(id); 180 if (pvList == null) { pvList = new ArrayList (); 182 idLocations.put(id, pvList); 183 pvList.add(pv); 184 185 189 if (!unfinishedIDs.contains(id)) { 190 tryIDResolution(id, pv, pvList); 191 } 192 } else { 193 pvList.add(pv); 194 } 195 } 196 197 203 public void signalPendingID(String id) { 204 if (log.isDebugEnabled()) { 205 log.debug("signalPendingID(" + id + ")"); 206 } 207 unfinishedIDs.add(id); 208 } 209 210 215 public void signalIDProcessed(String id) { 216 if (log.isDebugEnabled()) { 217 log.debug("signalIDProcessed(" + id + ")"); 218 } 219 220 alreadyResolvedIDs.add(id); 221 if (!unfinishedIDs.contains(id)) { 222 return; 223 } 224 unfinishedIDs.remove(id); 225 226 List pvList = (List ) idLocations.get(id); 227 Set todo = (Set ) unresolvedIDRefs.get(id); 228 if (todo != null) { 229 for (Iterator iter = todo.iterator(); iter.hasNext();) { 230 Resolvable res = (Resolvable) iter.next(); 231 res.resolveIDRef(id, pvList); 232 } 233 unresolvedIDRefs.remove(id); 234 } 235 } 236 237 242 public boolean alreadyResolvedID(String id) { 243 return (alreadyResolvedIDs.contains(id)); 244 } 245 246 252 private void tryIDResolution(String id, PageViewport pv, List pvList) { 253 Set todo = (Set ) unresolvedIDRefs.get(id); 254 if (todo != null) { 255 for (Iterator iter = todo.iterator(); iter.hasNext();) { 256 Resolvable res = (Resolvable) iter.next(); 257 if (!unfinishedIDs.contains(id)) { 258 res.resolveIDRef(id, pvList); 259 } else { 260 return; 261 } 262 } 263 alreadyResolvedIDs.add(id); 264 unresolvedIDRefs.remove(id); 265 } 266 } 267 268 272 public void tryIDResolution(PageViewport pv) { 273 String [] ids = pv.getIDRefs(); 274 if (ids != null) { 275 for (int i = 0; i < ids.length; i++) { 276 List pvList = (List ) idLocations.get(ids[i]); 277 if (pvList != null) { 278 tryIDResolution(ids[i], pv, pvList); 279 } 280 } 281 } 282 } 283 284 289 public List getPageViewportsContainingID(String id) { 290 return (List ) idLocations.get(id); 291 } 292 293 298 public FormattingResults getResults() { 299 return this.results; 300 } 301 302 307 public void addUnresolvedIDRef(String idref, Resolvable res) { 308 Set todo = (Set ) unresolvedIDRefs.get(idref); 309 if (todo == null) { 310 todo = new HashSet (); 311 unresolvedIDRefs.put(idref, todo); 312 } 313 todo.add(res); 315 } 316 317 323 public void startDocument() throws SAXException { 324 if (outputStatistics) { 326 initialMemory = runtime.totalMemory() - runtime.freeMemory(); 327 startTime = System.currentTimeMillis(); 328 } 329 } 330 331 334 private void finishPrevPageSequence(Numeric initialPageNumber) { 335 if (prevPageSeqLM != null) { 336 prevPageSeqLM.doForcePageCount(initialPageNumber); 337 prevPageSeqLM.finishPageSequence(); 338 prevPageSeqLM = null; 339 } 340 } 341 342 346 public void startPageSequence(PageSequence pageSequence) { 347 rootFObj = pageSequence.getRoot(); 348 finishPrevPageSequence(pageSequence.getInitialPageNumber()); 349 pageSequence.initPageNumber(); 350 wrapAndAddExtensionAttachments(rootFObj.getExtensionAttachments()); 352 if (rootFObj.getDeclarations() != null) { 354 wrapAndAddExtensionAttachments(rootFObj.getDeclarations().getExtensionAttachments()); 355 } 356 } 357 358 private void wrapAndAddExtensionAttachments(List list) { 359 Iterator i = list.iterator(); 360 while (i.hasNext()) { 361 ExtensionAttachment attachment = (ExtensionAttachment)i.next(); 362 addOffDocumentItem(new OffDocumentExtensionAttachment(attachment)); 363 } 364 } 365 366 373 public void endPageSequence(PageSequence pageSequence) { 374 375 if (outputStatistics) { 376 long memoryNow = runtime.totalMemory() - runtime.freeMemory(); 377 log.debug("Current heap size: " + (memoryNow / 1024L) + "Kb"); 378 } 379 380 if (pageSequence.getMainFlow() != null) { 382 PageSequenceLayoutManager pageSLM; 383 pageSLM = getLayoutManagerMaker().makePageSequenceLayoutManager( 384 this, pageSequence); 385 pageSLM.activateLayout(); 386 prevPageSeqLM = pageSLM; 389 } 390 } 391 392 397 public void notifyPageSequenceFinished(PageSequence pageSequence, 398 int pageCount) { 399 this.results.haveFormattedPageSequence(pageSequence, 400 pageCount); 401 if (log.isDebugEnabled()) { 402 log.debug("Last page-sequence produced " 403 + pageCount + " pages."); 404 } 405 } 406 407 412 public void endDocument() throws SAXException { 413 414 finishPrevPageSequence(null); 415 BookmarkTree bookmarkTree = rootFObj.getBookmarkTree(); 417 if (bookmarkTree != null) { 418 BookmarkData data = new BookmarkData(bookmarkTree); 419 addOffDocumentItem(data); 420 if (!data.isResolved()) { 421 model.handleOffDocumentItem(data); 423 } 424 } 425 426 model.endDocument(); 427 428 if (outputStatistics) { 429 long memoryNow = runtime.totalMemory() - runtime.freeMemory(); 430 long memoryUsed = (memoryNow - initialMemory) / 1024L; 431 long timeUsed = System.currentTimeMillis() - startTime; 432 int pageCount = rootFObj.getTotalPagesGenerated(); 433 log.debug("Initial heap size: " + (initialMemory / 1024L) + "Kb"); 434 log.debug("Current heap size: " + (memoryNow / 1024L) + "Kb"); 435 log.debug("Total memory used: " + memoryUsed + "Kb"); 436 log.debug("Total time used: " + timeUsed + "ms"); 437 log.debug("Pages rendered: " + pageCount); 438 if (pageCount > 0) { 439 long perPage = (timeUsed / pageCount); 440 long ppm = (timeUsed != 0 ? Math.round(60000 * pageCount / (double)timeUsed) : -1); 441 log.debug("Avg render time: " + perPage + "ms/page (" + ppm + "pages/min)"); 442 } 443 } 444 } 445 446 452 private void addOffDocumentItem(OffDocumentItem odi) { 453 if (odi instanceof Resolvable) { 454 Resolvable res = (Resolvable) odi; 455 String [] ids = res.getIDRefs(); 456 for (int count = 0; count < ids.length; count++) { 457 if (idLocations.containsKey(ids[count])) { 458 res.resolveIDRef(ids[count], (List ) idLocations.get(ids[count])); 459 } else { 460 log.warn(odi.getName() + ": Unresolved id reference \"" 461 + ids[count] + "\" found."); 462 addUnresolvedIDRef(ids[count], res); 463 } 464 } 465 if (res.isResolved()) { 467 model.handleOffDocumentItem(odi); 468 } 469 } else { 470 model.handleOffDocumentItem(odi); 471 } 472 } 473 474 478 public String generatePageViewportKey() { 479 this.idGen++; 480 return "P" + this.idGen; 481 } 482 483 } 484 485 | Popular Tags |