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.

AbstractRenderer.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 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.render;
  8. // FOP
  9. import org.apache.fop.apps.FOPException;
  10. import org.apache.fop.area.*;
  11. import org.apache.fop.area.inline.*;
  12. import org.apache.fop.area.inline.Character;
  13. import org.apache.fop.fo.FOUserAgent;
  14. // Avalon
  15. import org.apache.avalon.framework.logger.AbstractLogEnabled;
  16. // Java
  17. import java.awt.geom.Rectangle2D;
  18. import java.io.IOException;
  19. import java.io.OutputStream;
  20. import java.util.HashMap;
  21. import java.util.List;
  22. import java.util.Iterator;
  23. /**
  24. * Abstract base class for all renderers.
  25. * The Abstract renderer does all the top level processing
  26. * of the area tree and adds some abstract methods to handle
  27. * viewports. This keeps track of the current block and inline
  28. * position.
  29. */
  30. public abstract class AbstractRenderer extends AbstractLogEnabled implements Renderer {
  31. protected FOUserAgent userAgent;
  32. protected HashMap options;
  33. // block progression position
  34. protected int currentBPPosition = 0;
  35. // inline progression position
  36. protected int currentIPPosition = 0;
  37. protected int currentBlockIPPosition = 0;
  38. public void setUserAgent(FOUserAgent agent) {
  39. userAgent = agent;
  40. }
  41. public void setOptions(HashMap opt) {
  42. options = opt;
  43. }
  44. /**
  45. * Check if this renderer supports out of order rendering.
  46. * If this renderer supports out of order rendering then it
  47. * means that the pages that are not ready will be prepared
  48. * and a future page will be rendered.
  49. */
  50. public boolean supportsOutOfOrder() {
  51. return false;
  52. }
  53. /**
  54. * Prepare a page for rendering.
  55. * This is called if the renderer supports out of order rendering.
  56. * The renderer should prepare the page so that a page further on
  57. * in the set of pages can be rendered. The body of the page should
  58. * not be rendered. The page will be rendered at a later time
  59. * by the call to render page.
  60. */
  61. public void preparePage(PageViewport page) {
  62. }
  63. /**
  64. * Utility method to convert a page sequence title to a string.
  65. * Some renderers may only be able to use a string title.
  66. * A title is a sequence of inline areas that this method
  67. * attempts to convert to an equivalent string.
  68. */
  69. public String convertTitleToString(Title title) {
  70. String str = "";
  71. List children = title.getInlineAreas();
  72. for (int count = 0; count < children.size(); count++) {
  73. InlineArea inline = (InlineArea) children.get(count);
  74. if (inline instanceof Character) {
  75. str += ((Character) inline).getChar();
  76. } else if (inline instanceof Word) {
  77. str += ((Word) inline).getWord();
  78. } else {
  79. str += " ";
  80. }
  81. }
  82. return str.trim();
  83. }
  84. public void startPageSequence(Title seqTitle) {
  85. }
  86. // normally this would be overriden to create a page in the
  87. // output
  88. public void renderPage(PageViewport page) throws IOException,
  89. FOPException {
  90. Page p = page.getPage();
  91. renderPageAreas(p);
  92. }
  93. protected void renderPageAreas(Page page) {
  94. RegionViewport viewport;
  95. viewport = page.getRegion(RegionReference.BEFORE);
  96. renderRegionViewport(viewport);
  97. viewport = page.getRegion(RegionReference.START);
  98. renderRegionViewport(viewport);
  99. viewport = page.getRegion(RegionReference.BODY);
  100. renderRegionViewport(viewport);
  101. viewport = page.getRegion(RegionReference.END);
  102. renderRegionViewport(viewport);
  103. viewport = page.getRegion(RegionReference.AFTER);
  104. renderRegionViewport(viewport);
  105. }
  106. // the region may clip the area and it establishes
  107. // a position from where the region is placed
  108. protected void renderRegionViewport(RegionViewport port) {
  109. if (port != null) {
  110. Rectangle2D view = port.getViewArea();
  111. // The CTM will transform coordinates relative to
  112. // this region-reference area into page coords, so
  113. // set origin for the region to 0,0.
  114. currentBPPosition = 0; // (int) (view.getY() / 1000);
  115. currentIPPosition = 0; // (int) (view.getX() / 1000);
  116. currentBlockIPPosition = currentIPPosition;
  117. RegionReference region = port.getRegion();
  118. startVParea(region.getCTM());
  119. if (region.getRegionClass() == RegionReference.BODY) {
  120. renderBodyRegion((BodyRegion) region);
  121. } else {
  122. renderRegion(region);
  123. }
  124. endVParea();
  125. }
  126. }
  127. protected void startVParea(CTM ctm) { }
  128. protected void endVParea() { }
  129. protected void renderRegion(RegionReference region) {
  130. List blocks = region.getBlocks();
  131. renderBlocks(blocks);
  132. }
  133. protected void renderBodyRegion(BodyRegion region) {
  134. BeforeFloat bf = region.getBeforeFloat();
  135. if (bf != null) {
  136. renderBeforeFloat(bf);
  137. }
  138. MainReference mr = region.getMainReference();
  139. if (mr != null) {
  140. renderMainReference(mr);
  141. }
  142. Footnote foot = region.getFootnote();
  143. if (foot != null) {
  144. renderFootnote(foot);
  145. }
  146. }
  147. protected void renderBeforeFloat(BeforeFloat bf) {
  148. List blocks = bf.getBlocks();
  149. if (blocks != null) {
  150. renderBlocks(blocks);
  151. Block sep = bf.getSeparator();
  152. if (sep != null) {
  153. renderBlock(sep);
  154. }
  155. }
  156. }
  157. protected void renderFootnote(Footnote footnote) {
  158. List blocks = footnote.getBlocks();
  159. if (blocks != null) {
  160. Block sep = footnote.getSeparator();
  161. if (sep != null) {
  162. renderBlock(sep);
  163. }
  164. renderBlocks(blocks);
  165. }
  166. }
  167. // the main reference area contains a list of spans that are
  168. // stacked on the page
  169. // the spans contain a list of normal flow reference areas
  170. // that are positioned into columns.
  171. protected void renderMainReference(MainReference mr) {
  172. int saveIPPos = currentIPPosition;
  173. Span span = null;
  174. List spans = mr.getSpans();
  175. for (int count = 0; count < spans.size(); count++) {
  176. span = (Span) spans.get(count);
  177. int offset = (mr.getWidth() -
  178. (span.getColumnCount() - 1) * mr.getColumnGap()) /
  179. span.getColumnCount() + mr.getColumnGap();
  180. for (int c = 0; c < span.getColumnCount(); c++) {
  181. Flow flow = (Flow) span.getFlow(c);
  182. renderFlow(flow);
  183. currentIPPosition += offset;
  184. }
  185. currentIPPosition = saveIPPos;
  186. currentBPPosition += span.getHeight();
  187. }
  188. }
  189. // the normal flow reference area contains stacked blocks
  190. protected void renderFlow(Flow flow) {
  191. List blocks = flow.getBlocks();
  192. renderBlocks(blocks);
  193. }
  194. protected void renderBlock(Block block) {
  195. List children = block.getChildAreas();
  196. if (children == null) {
  197. // simply move position
  198. } else {
  199. renderBlocks(children);
  200. }
  201. }
  202. // a line area may have grouped styling for its children
  203. // such as underline, background
  204. protected void renderLineArea(LineArea line) {
  205. List children = line.getInlineAreas();
  206. for (int count = 0; count < children.size(); count++) {
  207. InlineArea inline = (InlineArea) children.get(count);
  208. inline.render(this);
  209. }
  210. }
  211. public void renderViewport(Viewport viewport) {
  212. Area content = viewport.getContent();
  213. int saveBP = currentBPPosition;
  214. currentBPPosition += viewport.getOffset();
  215. Rectangle2D contpos = viewport.getContentPosition();
  216. if (content instanceof Image) {
  217. renderImage((Image) content, contpos);
  218. } else if (content instanceof Container) {
  219. renderContainer((Container) content);
  220. } else if (content instanceof ForeignObject) {
  221. renderForeignObject((ForeignObject) content, contpos);
  222. }
  223. currentBlockIPPosition += viewport.getWidth();
  224. currentBPPosition = saveBP;
  225. }
  226. public void renderImage(Image image, Rectangle2D pos) {
  227. }
  228. public void renderContainer(Container cont) {
  229. int saveIP = currentIPPosition;
  230. currentIPPosition = currentBlockIPPosition;
  231. int saveBlockIP = currentBlockIPPosition;
  232. int saveBP = currentBPPosition;
  233. List blocks = cont.getBlocks();
  234. renderBlocks(blocks);
  235. currentIPPosition = saveIP;
  236. currentBlockIPPosition = saveBlockIP;
  237. currentBPPosition = saveBP;
  238. }
  239. public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
  240. }
  241. public void renderCharacter(Character ch) {
  242. currentBlockIPPosition += ch.getWidth();
  243. }
  244. // an inline space moves the inline progression position
  245. // for the current block by the width or height of the space
  246. // it may also have styling (only on this object) that needs
  247. // handling
  248. public void renderInlineSpace(Space space) {
  249. currentBlockIPPosition += space.getWidth();
  250. }
  251. public void renderLeader(Leader area) {
  252. currentBlockIPPosition += area.getWidth();
  253. }
  254. public void renderWord(Word word) {
  255. currentBlockIPPosition += word.getWidth();
  256. }
  257. public void renderInlineParent(InlineParent ip) {
  258. // currentBlockIPPosition += ip.getWidth();
  259. Iterator iter = ip.getChildAreas().iterator();
  260. while (iter.hasNext()) {
  261. ((InlineArea)iter.next()).render(this);
  262. }
  263. }
  264. protected void renderBlocks(List blocks) {
  265. for (int count = 0; count < blocks.size(); count++) {
  266. Object obj = blocks.get(count);
  267. if(obj instanceof Block) {
  268. renderBlock((Block)obj);
  269. } else {
  270. // a line area is rendered from the top left position
  271. // of the line, each inline object is offset from there
  272. LineArea line = (LineArea) obj;
  273. currentBlockIPPosition = currentIPPosition;
  274. renderLineArea(line);
  275. currentBPPosition += line.getHeight();
  276. }
  277. }
  278. }
  279. }