You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LayoutHandler.java 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. package org.apache.fop.apps;
  8. // Java
  9. import java.io.IOException;
  10. import java.io.OutputStream;
  11. import java.util.List;
  12. // SAX
  13. import org.xml.sax.SAXException;
  14. // FOP
  15. import org.apache.fop.area.AreaTree;
  16. import org.apache.fop.area.AreaTreeModel;
  17. import org.apache.fop.area.StorePagesModel;
  18. import org.apache.fop.area.Title;
  19. import org.apache.fop.area.TreeExt;
  20. import org.apache.fop.fo.pagination.LayoutMasterSet;
  21. import org.apache.fop.fo.pagination.PageSequence;
  22. import org.apache.fop.layout.FontInfo;
  23. import org.apache.fop.render.Renderer;
  24. /**
  25. * Layout handler that receives the structure events.
  26. * This initiates layout processes and corresponding
  27. * rendering processes such as start/end.
  28. */
  29. public class LayoutHandler extends StructureHandler {
  30. // TODO: Collecting of statistics should be configurable
  31. private final boolean collectStatistics = true;
  32. private final boolean MEM_PROFILE_WITH_GC = false;
  33. /**
  34. Somewhere to get our stats from.
  35. */
  36. private Runtime runtime;
  37. /**
  38. Keep track of the number of pages rendered.
  39. */
  40. private int pageCount;
  41. /**
  42. Keep track of heap memory allocated,
  43. for statistical purposes.
  44. */
  45. private long initialMemory;
  46. /**
  47. Keep track of time used by renderer.
  48. */
  49. private long startTime;
  50. /**
  51. The stream to which this rendering is to be
  52. written to. <B>Note</B> that some renderers
  53. do not render to a stream, and that this
  54. member can therefore be null.
  55. */
  56. private OutputStream outputStream;
  57. /**
  58. The renderer being used.
  59. */
  60. private Renderer renderer;
  61. /**
  62. The FontInfo for this renderer.
  63. */
  64. private FontInfo fontInfo = new FontInfo();
  65. /**
  66. * The current AreaTree for the PageSequence being rendered.
  67. */
  68. private AreaTree areaTree;
  69. private AreaTreeModel atModel;
  70. /**
  71. * @param outputStream the stream that the result is rendered to
  72. * @param renderer the renderer to call
  73. * @param store if true then use the store pages model and keep the
  74. * area tree in memory
  75. */
  76. public LayoutHandler(OutputStream outputStream, Renderer renderer,
  77. boolean store) {
  78. if (collectStatistics)
  79. runtime = Runtime.getRuntime();
  80. this.outputStream = outputStream;
  81. this.renderer = renderer;
  82. this.areaTree = new AreaTree();
  83. this.atModel = AreaTree.createRenderPagesModel(renderer);
  84. //this.atModel = new CachedRenderPagesModel(renderer);
  85. areaTree.setTreeModel(atModel);
  86. }
  87. /**
  88. * Get the area tree for this layout handler.
  89. *
  90. * @return the area tree for this document
  91. */
  92. public AreaTree getAreaTree() {
  93. return areaTree;
  94. }
  95. /**
  96. * Start the document.
  97. * This starts the document in the renderer.
  98. *
  99. * @throws SAXException if there is an error
  100. */
  101. public void startDocument() throws SAXException {
  102. //Initialize statistics
  103. if (collectStatistics) {
  104. pageCount = 0;
  105. if (MEM_PROFILE_WITH_GC) {
  106. System.gc(); // This takes time but gives better results
  107. }
  108. initialMemory = runtime.totalMemory() - runtime.freeMemory();
  109. startTime = System.currentTimeMillis();
  110. }
  111. try {
  112. renderer.setupFontInfo(fontInfo);
  113. // check that the "any,normal,400" font exists
  114. if(!fontInfo.isSetupValid()) {
  115. throw new SAXException(new FOPException("no default font defined by OutputConverter"));
  116. }
  117. renderer.startRenderer(outputStream);
  118. } catch (IOException e) {
  119. throw new SAXException(e);
  120. }
  121. }
  122. /**
  123. * End the document.
  124. *
  125. * @throws SAXException if there is some error
  126. */
  127. public void endDocument() throws SAXException {
  128. try {
  129. //processAreaTree(atModel);
  130. areaTree.endDocument();
  131. renderer.stopRenderer();
  132. } catch (Exception e) {
  133. throw new SAXException(e);
  134. }
  135. if (collectStatistics) {
  136. if (MEM_PROFILE_WITH_GC) {
  137. // This takes time but gives better results
  138. System.gc();
  139. }
  140. long memoryNow = runtime.totalMemory() - runtime.freeMemory();
  141. long memoryUsed = (memoryNow - initialMemory) / 1024L;
  142. long timeUsed = System.currentTimeMillis() - startTime;
  143. if (getLogger().isDebugEnabled()) {
  144. getLogger().debug("Initial heap size: " + (initialMemory / 1024L) + "Kb");
  145. getLogger().debug("Current heap size: " + (memoryNow / 1024L) + "Kb");
  146. getLogger().debug("Total memory used: " + memoryUsed + "Kb");
  147. if (!MEM_PROFILE_WITH_GC) {
  148. getLogger().debug(" Memory use is indicative; no GC was performed");
  149. getLogger().debug(" These figures should not be used comparatively");
  150. }
  151. getLogger().debug("Total time used: " + timeUsed + "ms");
  152. getLogger().debug("Pages rendered: " + pageCount);
  153. if (pageCount > 0) {
  154. getLogger().debug("Avg render time: " + (timeUsed / pageCount) + "ms/page");
  155. }
  156. }
  157. }
  158. }
  159. /**
  160. * Start a page sequence.
  161. * At the start of a page sequence it can start the page sequence
  162. * on the area tree with the page sequence title.
  163. *
  164. * @param pageSeq the page sequence starting
  165. * @param seqTitle the title of the page sequence
  166. * @param lms the layout master set
  167. */
  168. public void startPageSequence(PageSequence pageSeq, org.apache.fop.fo.Title seqTitle, LayoutMasterSet lms) {
  169. Title title = null;
  170. if (seqTitle != null) {
  171. title = seqTitle.getTitleArea();
  172. }
  173. areaTree.startPageSequence(title);
  174. }
  175. /**
  176. * End the PageSequence.
  177. * The PageSequence formats Pages and adds them to the AreaTree.
  178. * The area tree then handles what happens with the pages.
  179. *
  180. * @param pageSequence the page sequence ending
  181. * @throws FOPException if there is an error formatting the pages
  182. */
  183. public void endPageSequence(PageSequence pageSequence)
  184. throws FOPException {
  185. //areaTree.setFontInfo(fontInfo);
  186. if (collectStatistics) {
  187. if (MEM_PROFILE_WITH_GC) {
  188. // This takes time but gives better results
  189. System.gc();
  190. }
  191. long memoryNow = runtime.totalMemory() - runtime.freeMemory();
  192. if (getLogger().isDebugEnabled()) {
  193. getLogger().debug("Current heap size: " + (memoryNow / 1024L) + "Kb");
  194. }
  195. }
  196. pageSequence.format(areaTree);
  197. }
  198. /**
  199. * Process an area tree.
  200. * If a store pages model is used this can read and send all the
  201. * pages to the renderer.
  202. *
  203. * @param model the store pages model
  204. * @throws FOPException if there is an error
  205. */
  206. private void processAreaTree(StorePagesModel model) throws FOPException {
  207. int count = 0;
  208. int seqc = model.getPageSequenceCount();
  209. while (count < seqc) {
  210. Title title = model.getTitle(count);
  211. renderer.startPageSequence(title);
  212. int pagec = model.getPageCount(count);
  213. for (int c = 0; c < pagec; c++) {
  214. try {
  215. renderer.renderPage(model.getPage(count, c));
  216. } catch (IOException ioex) {
  217. throw new FOPException("I/O Error rendering page",
  218. ioex);
  219. }
  220. }
  221. count++;
  222. }
  223. List list = model.getEndExtensions();
  224. for(count = 0; count < list.size(); count++) {
  225. TreeExt ext = (TreeExt)list.get(count);
  226. renderer.renderExtension(ext);
  227. }
  228. }
  229. /**
  230. * Get the font information for the layout handler.
  231. *
  232. * @return the font information
  233. */
  234. public FontInfo getFontInfo() {
  235. return this.fontInfo;
  236. }
  237. }