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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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.xml;
  8. // FOP
  9. import org.apache.fop.svg.*;
  10. import org.apache.fop.render.Renderer;
  11. import org.apache.fop.render.AbstractRenderer;
  12. import org.apache.fop.render.RendererContext;
  13. import org.apache.fop.render.XMLHandler;
  14. import org.apache.fop.area.*;
  15. import org.apache.fop.area.inline.*;
  16. import org.apache.fop.pdf.*;
  17. import org.apache.fop.fo.properties.LeaderPattern;
  18. import org.apache.fop.fo.FOUserAgent;
  19. import org.apache.fop.layout.FontInfo;
  20. import org.apache.fop.apps.FOPException;
  21. // Avalon
  22. import org.apache.avalon.framework.logger.Logger;
  23. // Java
  24. import java.io.IOException;
  25. import java.io.PrintWriter;
  26. import java.io.OutputStream;
  27. import java.util.Enumeration;
  28. import java.util.List;
  29. import java.util.Map;
  30. import java.util.Iterator;
  31. import java.awt.geom.Rectangle2D;
  32. import org.w3c.dom.Document;
  33. /**
  34. * Renderer that renders areas to XML for debugging purposes.
  35. * This creates an xml that contains the information of the area
  36. * tree. It does not output any state or derived information.
  37. * The output can be used to build a new area tree (@see AreaTreeBuilder)
  38. * which can be rendered to any renderer.
  39. */
  40. public class XMLRenderer extends AbstractRenderer {
  41. public static final String mimeType = "text/xml";
  42. boolean startedSequence = false;
  43. RendererContext context;
  44. public void setProducer(String producer) {
  45. }
  46. /**
  47. * indentation to use for pretty-printing the XML
  48. */
  49. protected int indent = 0;
  50. /**
  51. * the application producing the XML
  52. */
  53. protected String producer;
  54. /**
  55. * the writer used to output the XML
  56. */
  57. protected PrintWriter writer;
  58. /**
  59. * options
  60. */
  61. private boolean consistentOutput = false;
  62. public XMLRenderer() {
  63. context = new RendererContext(mimeType);
  64. }
  65. public void setUserAgent(FOUserAgent agent) {
  66. super.setUserAgent(agent);
  67. //
  68. //userAgent.addExtensionHandler();
  69. XMLHandler handler = new XMLXMLHandler();
  70. userAgent.setDefaultXMLHandler(mimeType, handler);
  71. String svg = "http://www.w3.org/2000/svg";
  72. userAgent.addXMLHandler(mimeType, svg, handler);
  73. }
  74. /**
  75. * write out spaces to make indent
  76. */
  77. protected void writeIndent() {
  78. StringBuffer s = new StringBuffer();
  79. for (int i = 0; i < this.indent; i++) {
  80. s = s.append(" ");
  81. }
  82. this.writer.write(s.toString());
  83. }
  84. /**
  85. * write out an element
  86. *
  87. * @param element the full text of the element including tags
  88. */
  89. protected void writeElement(String element) {
  90. writeIndent();
  91. this.writer.write(element + "\n");
  92. }
  93. /**
  94. * write out an empty-element-tag
  95. *
  96. * @param tag the text of the tag
  97. */
  98. protected void writeEmptyElementTag(String tag) {
  99. writeIndent();
  100. this.writer.write(tag + "\n");
  101. }
  102. /**
  103. * write out an end tag
  104. *
  105. * @param tag the text of the tag
  106. */
  107. protected void writeEndTag(String tag) {
  108. this.indent--;
  109. writeIndent();
  110. this.writer.write(tag + "\n");
  111. }
  112. /**
  113. * write out a start tag
  114. *
  115. * @param tag the text of the tag
  116. */
  117. protected void writeStartTag(String tag) {
  118. writeIndent();
  119. this.writer.write(tag + "\n");
  120. this.indent++;
  121. }
  122. /**
  123. * set up the font info
  124. *
  125. * @param fontInfo the font info object to set up
  126. */
  127. public void setupFontInfo(FontInfo fontInfo) {
  128. /* use PDF's font setup to get PDF metrics */
  129. org.apache.fop.render.pdf.FontSetup.setup(fontInfo, org.apache.fop.configuration.Configuration.getFonts());
  130. }
  131. private boolean isCoarseXml() {
  132. return ((Boolean) options.get("fineDetail")).booleanValue();
  133. }
  134. /**
  135. */
  136. public void startRenderer(OutputStream outputStream)
  137. throws IOException {
  138. getLogger().debug("rendering areas to XML");
  139. this.writer = new PrintWriter(outputStream);
  140. this.writer.write( "<?xml version=\"1.0\"?>\n<!-- produced by " +
  141. this.producer + " -->\n");
  142. writeStartTag("<areaTree>");
  143. }
  144. /**
  145. */
  146. public void stopRenderer() throws IOException {
  147. writeEndTag("</pageSequence>");
  148. writeEndTag("</areaTree>");
  149. this.writer.flush();
  150. getLogger().debug("written out XML");
  151. }
  152. public void renderPage(PageViewport page) throws IOException,
  153. FOPException {
  154. writeStartTag("<pageViewport bounds=\"" +
  155. createString(page.getViewArea()) + "\">");
  156. writeStartTag("<page>");
  157. super.renderPage(page);
  158. writeEndTag("</page>");
  159. writeEndTag("</pageViewport>");
  160. }
  161. private String createString(Rectangle2D rect) {
  162. return "" + (int) rect.getX() + " " + (int) rect.getY() + " " +
  163. (int) rect.getWidth() + " " + (int) rect.getHeight();
  164. }
  165. public void startPageSequence(Title seqTitle) {
  166. if (startedSequence) {
  167. writeEndTag("</pageSequence>");
  168. }
  169. startedSequence = true;
  170. writeStartTag("<pageSequence>");
  171. if (seqTitle != null) {
  172. writeStartTag("<title>");
  173. List children = seqTitle.getInlineAreas();
  174. for (int count = 0; count < children.size(); count++) {
  175. InlineArea inline = (InlineArea) children.get(count);
  176. inline.render(this);
  177. }
  178. writeEndTag("</title>");
  179. }
  180. }
  181. protected void renderRegionViewport(RegionViewport port) {
  182. if (port != null) {
  183. writeStartTag("<regionViewport rect=\"" +
  184. createString(port.getViewArea()) + "\">");
  185. RegionReference region = port.getRegion();
  186. if (region.getRegionClass() == RegionReference.BEFORE) {
  187. writeStartTag("<regionBefore>");
  188. renderRegion(region);
  189. writeEndTag("</regionBefore>");
  190. } else if (region.getRegionClass() == RegionReference.START) {
  191. writeStartTag("<regionStart>");
  192. renderRegion(region);
  193. writeEndTag("</regionStart>");
  194. } else if (region.getRegionClass() == RegionReference.BODY) {
  195. writeStartTag("<regionBody>");
  196. renderBodyRegion((BodyRegion) region);
  197. writeEndTag("</regionBody>");
  198. } else if (region.getRegionClass() == RegionReference.END) {
  199. writeStartTag("<regionEnd>");
  200. renderRegion(region);
  201. writeEndTag("</regionEnd>");
  202. } else if (region.getRegionClass() == RegionReference.AFTER) {
  203. writeStartTag("<regionAfter>");
  204. renderRegion(region);
  205. writeEndTag("</regionAfter>");
  206. }
  207. writeEndTag("</regionViewport>");
  208. }
  209. }
  210. protected void renderBeforeFloat(BeforeFloat bf) {
  211. writeStartTag("<beforeFloat>");
  212. super.renderBeforeFloat(bf);
  213. writeEndTag("</beforeFloat>");
  214. }
  215. protected void renderFootnote(Footnote footnote) {
  216. writeStartTag("<footnote>");
  217. super.renderFootnote(footnote);
  218. writeEndTag("</footnote>");
  219. }
  220. protected void renderMainReference(MainReference mr) {
  221. writeStartTag("<mainReference columnGap=\"" +
  222. mr.getColumnGap() + "\" width=\"" + mr.getWidth() + "\">");
  223. Span span = null;
  224. List spans = mr.getSpans();
  225. for (int count = 0; count < spans.size(); count++) {
  226. span = (Span) spans.get(count);
  227. writeStartTag("<span>");
  228. for (int c = 0; c < span.getColumnCount(); c++) {
  229. Flow flow = (Flow) span.getFlow(c);
  230. renderFlow(flow);
  231. }
  232. writeEndTag("</span>");
  233. }
  234. writeEndTag("</mainReference>");
  235. }
  236. // the normal flow reference area contains stacked blocks
  237. protected void renderFlow(Flow flow) {
  238. writeStartTag("<flow>");
  239. super.renderFlow(flow);
  240. writeEndTag("</flow>");
  241. }
  242. protected void renderBlock(Block block) {
  243. String prop = "";
  244. Map map = block.getTraits();
  245. if (map != null) {
  246. prop = " props=\"" + getPropString(map) + "\"";
  247. }
  248. writeStartTag("<block" + prop + ">");
  249. super.renderBlock(block);
  250. writeEndTag("</block>");
  251. }
  252. protected void renderLineArea(LineArea line) {
  253. String prop = "";
  254. Map map = line.getTraits();
  255. if (map != null) {
  256. prop = " props=\"" + getPropString(map) + "\"";
  257. }
  258. writeStartTag("<lineArea height=\"" + line.getHeight() + "\"" +
  259. prop + ">");
  260. super.renderLineArea(line);
  261. writeEndTag("</lineArea>");
  262. }
  263. public void renderViewport(Viewport viewport) {
  264. writeStartTag("<viewport>");
  265. super.renderViewport(viewport);
  266. writeEndTag("</viewport>");
  267. }
  268. public void renderImage(Image image) {
  269. writeElement("<image url=\"" + image.getURL() + "\"/>");
  270. }
  271. public void renderContainer(Container cont) {
  272. writeStartTag("<container>");
  273. super.renderContainer(cont);
  274. writeEndTag("</container>");
  275. }
  276. public void renderForeignObject(ForeignObject fo) {
  277. writeStartTag("<foreignObject>");
  278. Document doc = fo.getDocument();
  279. String ns = fo.getNameSpace();
  280. context.setProperty(XMLXMLHandler.WRITER, writer);
  281. userAgent.renderXML(context, doc, ns);
  282. writeEndTag("</foreignObject>");
  283. }
  284. public void renderCharacter(org.apache.fop.area.inline.Character ch) {
  285. String prop = "";
  286. Map map = ch.getTraits();
  287. if (map != null) {
  288. prop = " props=\"" + getPropString(map) + "\"";
  289. }
  290. writeElement("<char" + prop + ">" + ch.getChar() + "</char>");
  291. }
  292. public void renderInlineSpace(Space space) {
  293. writeElement("<space width=\"" + space.getWidth() + "\"/>");
  294. }
  295. public void renderWord(Word word) {
  296. String prop = "";
  297. Map map = word.getTraits();
  298. if (map != null) {
  299. prop = " props=\"" + getPropString(map) + "\"";
  300. }
  301. writeElement("<word wsadjust=\"" + word.getWSadjust() + "\"" +
  302. prop + ">" + word.getWord() + "</word>");
  303. super.renderWord(word);
  304. }
  305. public void renderInlineParent(InlineParent ip) {
  306. String prop = "";
  307. Map map = ip.getTraits();
  308. if (map != null) {
  309. prop = " props=\"" + getPropString(map) + "\"";
  310. }
  311. writeStartTag("<inlineparent" + prop + ">");
  312. super.renderInlineParent(ip);
  313. writeEndTag("</inlineparent>");
  314. }
  315. public void renderLeader(Leader area) {
  316. String style = "solid";
  317. switch (area.getRuleStyle()) {
  318. case Leader.DOTTED:
  319. style = "dotted";
  320. break;
  321. case Leader.DASHED:
  322. style = "dashed";
  323. break;
  324. case Leader.SOLID:
  325. break;
  326. case Leader.DOUBLE:
  327. style = "double";
  328. break;
  329. case Leader.GROOVE:
  330. style = "groove";
  331. break;
  332. case Leader.RIDGE:
  333. style = "ridge";
  334. break;
  335. }
  336. writeElement("<leader width=\"" + area.getWidth() + "\" ruleStyle=\"" + style +
  337. "\" ruleThickness=\"" + area.getRuleThickness() + "\"/>");
  338. super.renderLeader(area);
  339. }
  340. protected String getPropString(Map traitMap) {
  341. StringBuffer strbuf = new StringBuffer();
  342. Iterator iter = traitMap.entrySet().iterator();
  343. while (iter.hasNext()) {
  344. Map.Entry traitEntry = (Map.Entry) iter.next();
  345. strbuf.append(Trait.getTraitName(traitEntry.getKey()));
  346. strbuf.append(':');
  347. strbuf.append(traitEntry.getValue().toString());
  348. strbuf.append(';');
  349. }
  350. return strbuf.toString();
  351. }
  352. }