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.

XMLRenderer.java 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /*
  2. * $Id: XMLRenderer.java,v 1.43 2003/03/07 09:46:34 jeremias Exp $
  3. * ============================================================================
  4. * The Apache Software License, Version 1.1
  5. * ============================================================================
  6. *
  7. * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without modifica-
  10. * tion, are permitted provided that the following conditions are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright notice,
  13. * this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if any, must
  20. * include the following acknowledgment: "This product includes software
  21. * developed by the Apache Software Foundation (http://www.apache.org/)."
  22. * Alternately, this acknowledgment may appear in the software itself, if
  23. * and wherever such third-party acknowledgments normally appear.
  24. *
  25. * 4. The names "FOP" and "Apache Software Foundation" must not be used to
  26. * endorse or promote products derived from this software without prior
  27. * written permission. For written permission, please contact
  28. * apache@apache.org.
  29. *
  30. * 5. Products derived from this software may not be called "Apache", nor may
  31. * "Apache" appear in their name, without prior written permission of the
  32. * Apache Software Foundation.
  33. *
  34. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  35. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  36. * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  37. * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  38. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  39. * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  40. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  41. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  43. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. * ============================================================================
  45. *
  46. * This software consists of voluntary contributions made by many individuals
  47. * on behalf of the Apache Software Foundation and was originally created by
  48. * James Tauber <jtauber@jtauber.com>. For more information on the Apache
  49. * Software Foundation, please see <http://www.apache.org/>.
  50. */
  51. package org.apache.fop.render.xml;
  52. // Java
  53. import java.io.IOException;
  54. import java.io.PrintWriter;
  55. import java.io.OutputStream;
  56. import java.util.List;
  57. import java.util.Map;
  58. import java.util.Iterator;
  59. import java.awt.geom.Rectangle2D;
  60. // XML
  61. /* org.w3c.dom.Document is not imported to avoid conflict with
  62. org.apache.fop.control.Document */
  63. // FOP
  64. import org.apache.fop.render.AbstractRenderer;
  65. import org.apache.fop.render.RendererContext;
  66. import org.apache.fop.render.XMLHandler;
  67. import org.apache.fop.apps.FOUserAgent;
  68. import org.apache.fop.apps.Document;
  69. import org.apache.fop.apps.FOPException;
  70. import org.apache.fop.area.BeforeFloat;
  71. import org.apache.fop.area.Block;
  72. import org.apache.fop.area.BodyRegion;
  73. import org.apache.fop.area.Flow;
  74. import org.apache.fop.area.Footnote;
  75. import org.apache.fop.area.LineArea;
  76. import org.apache.fop.area.MainReference;
  77. import org.apache.fop.area.PageViewport;
  78. import org.apache.fop.area.RegionReference;
  79. import org.apache.fop.area.RegionViewport;
  80. import org.apache.fop.area.Span;
  81. import org.apache.fop.area.Title;
  82. import org.apache.fop.area.Trait;
  83. import org.apache.fop.area.inline.Container;
  84. import org.apache.fop.area.inline.ForeignObject;
  85. import org.apache.fop.area.inline.Image;
  86. import org.apache.fop.area.inline.InlineArea;
  87. import org.apache.fop.area.inline.InlineParent;
  88. import org.apache.fop.area.inline.Leader;
  89. import org.apache.fop.area.inline.Space;
  90. import org.apache.fop.area.inline.Viewport;
  91. import org.apache.fop.area.inline.TextArea;
  92. import org.apache.fop.fonts.FontSetup;
  93. import org.apache.fop.fo.properties.RuleStyle;
  94. import org.apache.fop.fo.FOTreeControl;
  95. import org.apache.fop.fo.pagination.Region;
  96. /**
  97. * Renderer that renders areas to XML for debugging purposes.
  98. * This creates an xml that contains the information of the area
  99. * tree. It does not output any state or derived information.
  100. * The output can be used to build a new area tree (@see AreaTreeBuilder)
  101. * which can be rendered to any renderer.
  102. */
  103. public class XMLRenderer extends AbstractRenderer {
  104. /** XML MIME type */
  105. public static final String XML_MIME_TYPE = "text/xml";
  106. private boolean startedSequence = false;
  107. private RendererContext context;
  108. /**
  109. * indentation to use for pretty-printing the XML
  110. */
  111. protected int indent = 0;
  112. /**
  113. * the application producing the XML
  114. */
  115. protected String producer;
  116. /**
  117. * the writer used to output the XML
  118. */
  119. protected PrintWriter writer;
  120. /**
  121. * options
  122. */
  123. private boolean consistentOutput = false;
  124. /**
  125. * Creates a new XML renderer.
  126. */
  127. public XMLRenderer() {
  128. context = new RendererContext(XML_MIME_TYPE);
  129. }
  130. /**
  131. * @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
  132. */
  133. public void setUserAgent(FOUserAgent agent) {
  134. super.setUserAgent(agent);
  135. //
  136. //userAgent.addExtensionHandler();
  137. XMLHandler handler = new XMLXMLHandler();
  138. setDefaultXMLHandler(userAgent, XML_MIME_TYPE, handler);
  139. String svg = "http://www.w3.org/2000/svg";
  140. addXMLHandler(userAgent, XML_MIME_TYPE, svg, handler);
  141. }
  142. /**
  143. * write out spaces to make indent
  144. */
  145. protected void writeIndent() {
  146. StringBuffer s = new StringBuffer();
  147. for (int i = 0; i < this.indent; i++) {
  148. s = s.append(" ");
  149. }
  150. this.writer.write(s.toString());
  151. }
  152. /**
  153. * write out an element
  154. *
  155. * @param element the full text of the element including tags
  156. */
  157. protected void writeElement(String element) {
  158. writeIndent();
  159. this.writer.write(element + "\n");
  160. }
  161. /**
  162. * write out an empty-element-tag
  163. *
  164. * @param tag the text of the tag
  165. */
  166. protected void writeEmptyElementTag(String tag) {
  167. writeIndent();
  168. this.writer.write(tag + "\n");
  169. }
  170. /**
  171. * write out an end tag
  172. *
  173. * @param tag the text of the tag
  174. */
  175. protected void writeEndTag(String tag) {
  176. this.indent--;
  177. writeIndent();
  178. this.writer.write(tag + "\n");
  179. }
  180. /**
  181. * write out a start tag
  182. *
  183. * @param tag the text of the tag
  184. */
  185. protected void writeStartTag(String tag) {
  186. writeIndent();
  187. this.writer.write(tag + "\n");
  188. this.indent++;
  189. }
  190. /**
  191. * set up the font info
  192. *
  193. * @param fontInfo the font info object to set up
  194. */
  195. public void setupFontInfo(FOTreeControl foTreeControl) {
  196. FontSetup.setup((Document) foTreeControl, null);
  197. }
  198. private boolean isCoarseXml() {
  199. return ((Boolean) options.get("fineDetail")).booleanValue();
  200. }
  201. /**
  202. * @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
  203. */
  204. public void startRenderer(OutputStream outputStream)
  205. throws IOException {
  206. getLogger().debug("rendering areas to XML");
  207. this.writer = new PrintWriter(outputStream);
  208. this.writer.write("<?xml version=\"1.0\"?>\n"
  209. + "<!-- produced by " + this.producer + " -->\n");
  210. writeStartTag("<areaTree>");
  211. }
  212. /**
  213. * @see org.apache.fop.render.Renderer#stopRenderer()
  214. */
  215. public void stopRenderer() throws IOException {
  216. writeEndTag("</pageSequence>");
  217. writeEndTag("</areaTree>");
  218. this.writer.flush();
  219. getLogger().debug("written out XML");
  220. }
  221. /**
  222. * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
  223. */
  224. public void renderPage(PageViewport page) throws IOException, FOPException {
  225. writeStartTag("<pageViewport bounds=\""
  226. + createString(page.getViewArea()) + "\">");
  227. writeStartTag("<page>");
  228. super.renderPage(page);
  229. writeEndTag("</page>");
  230. writeEndTag("</pageViewport>");
  231. }
  232. private String createString(Rectangle2D rect) {
  233. return "" + (int) rect.getX() + " " + (int) rect.getY() + " "
  234. + (int) rect.getWidth() + " " + (int) rect.getHeight();
  235. }
  236. /**
  237. * @see org.apache.fop.render.Renderer#startPageSequence(Title)
  238. */
  239. public void startPageSequence(Title seqTitle) {
  240. if (startedSequence) {
  241. writeEndTag("</pageSequence>");
  242. }
  243. startedSequence = true;
  244. writeStartTag("<pageSequence>");
  245. if (seqTitle != null) {
  246. writeStartTag("<title>");
  247. List children = seqTitle.getInlineAreas();
  248. for (int count = 0; count < children.size(); count++) {
  249. InlineArea inline = (InlineArea) children.get(count);
  250. inline.acceptVisitor(this);
  251. }
  252. writeEndTag("</title>");
  253. }
  254. }
  255. /**
  256. * @see org.apache.fop.render.AbstractRenderer#renderRegionViewport(RegionViewport)
  257. */
  258. protected void renderRegionViewport(RegionViewport port) {
  259. if (port != null) {
  260. writeStartTag("<regionViewport rect=\""
  261. + createString(port.getViewArea()) + "\">");
  262. RegionReference region = port.getRegion();
  263. if (region.getRegionClass() == Region.BEFORE_CODE) {
  264. writeStartTag("<regionBefore>");
  265. renderRegion(region);
  266. writeEndTag("</regionBefore>");
  267. } else if (region.getRegionClass() == Region.START_CODE) {
  268. writeStartTag("<regionStart>");
  269. renderRegion(region);
  270. writeEndTag("</regionStart>");
  271. } else if (region.getRegionClass() == Region.BODY_CODE) {
  272. writeStartTag("<regionBody>");
  273. renderBodyRegion((BodyRegion) region);
  274. writeEndTag("</regionBody>");
  275. } else if (region.getRegionClass() == Region.END_CODE) {
  276. writeStartTag("<regionEnd>");
  277. renderRegion(region);
  278. writeEndTag("</regionEnd>");
  279. } else if (region.getRegionClass() == Region.AFTER_CODE) {
  280. writeStartTag("<regionAfter>");
  281. renderRegion(region);
  282. writeEndTag("</regionAfter>");
  283. }
  284. writeEndTag("</regionViewport>");
  285. }
  286. }
  287. /**
  288. * @see org.apache.fop.render.AbstractRenderer#renderBeforeFloat(BeforeFloat)
  289. */
  290. protected void renderBeforeFloat(BeforeFloat bf) {
  291. writeStartTag("<beforeFloat>");
  292. super.renderBeforeFloat(bf);
  293. writeEndTag("</beforeFloat>");
  294. }
  295. /**
  296. * @see org.apache.fop.render.AbstractRenderer#renderFootnote(Footnote)
  297. */
  298. protected void renderFootnote(Footnote footnote) {
  299. writeStartTag("<footnote>");
  300. super.renderFootnote(footnote);
  301. writeEndTag("</footnote>");
  302. }
  303. /**
  304. * @see org.apache.fop.render.AbstractRenderer#renderMainReference(MainReference)
  305. */
  306. protected void renderMainReference(MainReference mr) {
  307. writeStartTag("<mainReference columnGap=\""
  308. + mr.getColumnGap() + "\" width=\"" + mr.getWidth() + "\">");
  309. Span span = null;
  310. List spans = mr.getSpans();
  311. for (int count = 0; count < spans.size(); count++) {
  312. span = (Span) spans.get(count);
  313. writeStartTag("<span>");
  314. for (int c = 0; c < span.getColumnCount(); c++) {
  315. Flow flow = (Flow) span.getFlow(c);
  316. renderFlow(flow);
  317. }
  318. writeEndTag("</span>");
  319. }
  320. writeEndTag("</mainReference>");
  321. }
  322. /**
  323. * @see org.apache.fop.render.AbstractRenderer#renderFlow(Flow)
  324. */
  325. protected void renderFlow(Flow flow) {
  326. // the normal flow reference area contains stacked blocks
  327. writeStartTag("<flow>");
  328. super.renderFlow(flow);
  329. writeEndTag("</flow>");
  330. }
  331. /**
  332. * @see org.apache.fop.render.AbstractRenderer#renderBlock(Block)
  333. */
  334. protected void renderBlock(Block block) {
  335. String prop = "";
  336. Map map = block.getTraits();
  337. if (map != null) {
  338. prop = " props=\"" + getPropString(map) + "\"";
  339. }
  340. writeStartTag("<block" + prop + ">");
  341. super.renderBlock(block);
  342. writeEndTag("</block>");
  343. }
  344. /**
  345. * @see org.apache.fop.render.AbstractRenderer#renderLineArea(LineArea)
  346. */
  347. protected void renderLineArea(LineArea line) {
  348. String prop = "";
  349. Map map = line.getTraits();
  350. if (map != null) {
  351. prop = " props=\"" + getPropString(map) + "\"";
  352. }
  353. writeStartTag("<lineArea height=\"" + line.getHeight() + "\""
  354. + prop + ">");
  355. super.renderLineArea(line);
  356. writeEndTag("</lineArea>");
  357. }
  358. /**
  359. * @see org.apache.fop.render.Renderer#renderViewport(Viewport)
  360. */
  361. public void renderViewport(Viewport viewport) {
  362. writeStartTag("<viewport>");
  363. super.renderViewport(viewport);
  364. writeEndTag("</viewport>");
  365. }
  366. /**
  367. * Renders an image
  368. * @param image the image
  369. */
  370. public void renderImage(Image image) {
  371. writeElement("<image url=\"" + image.getURL() + "\"/>");
  372. }
  373. /**
  374. * @see org.apache.fop.render.Renderer#renderContainer(Container)
  375. */
  376. public void renderContainer(Container cont) {
  377. writeStartTag("<container>");
  378. super.renderContainer(cont);
  379. writeEndTag("</container>");
  380. }
  381. /**
  382. * Renders an fo:foreing-object.
  383. * @param fo the foreign object
  384. */
  385. public void renderForeignObject(ForeignObject fo) {
  386. writeStartTag("<foreignObject>");
  387. org.w3c.dom.Document doc = fo.getDocument();
  388. String ns = fo.getNameSpace();
  389. context.setProperty(XMLXMLHandler.WRITER, writer);
  390. renderXML(userAgent, context, doc, ns);
  391. writeEndTag("</foreignObject>");
  392. }
  393. /**
  394. * @see org.apache.fop.render.Renderer#renderCharacter(Character)
  395. */
  396. public void renderCharacter(org.apache.fop.area.inline.Character ch) {
  397. String prop = "";
  398. Map map = ch.getTraits();
  399. if (map != null) {
  400. prop = " props=\"" + getPropString(map) + "\"";
  401. }
  402. writeElement("<char" + prop + ">" + ch.getChar() + "</char>");
  403. }
  404. /**
  405. * @see org.apache.fop.render.Renderer#renderInlineSpace(Space)
  406. */
  407. public void renderInlineSpace(Space space) {
  408. writeElement("<space width=\"" + space.getWidth() + "\"/>");
  409. }
  410. /**
  411. * @see org.apache.fop.render.Renderer#renderText(Text)
  412. */
  413. public void renderText(TextArea text) {
  414. String prop = "";
  415. Map map = text.getTraits();
  416. if (map != null) {
  417. prop = " props=\"" + getPropString(map) + "\"";
  418. }
  419. writeElement("<text tsadjust=\"" + text.getTSadjust() + "\""
  420. + prop + ">" + text.getTextArea() + "</text>");
  421. super.renderText(text);
  422. }
  423. /**
  424. * @see org.apache.fop.render.Renderer#renderInlineParent(InlineParent)
  425. */
  426. public void renderInlineParent(InlineParent ip) {
  427. String prop = "";
  428. Map map = ip.getTraits();
  429. if (map != null) {
  430. prop = " props=\"" + getPropString(map) + "\"";
  431. }
  432. writeStartTag("<inlineparent" + prop + ">");
  433. super.renderInlineParent(ip);
  434. writeEndTag("</inlineparent>");
  435. }
  436. /**
  437. * @see org.apache.fop.render.Renderer#renderLeader(Leader)
  438. */
  439. public void renderLeader(Leader area) {
  440. String style = "solid";
  441. switch (area.getRuleStyle()) {
  442. case RuleStyle.DOTTED:
  443. style = "dotted";
  444. break;
  445. case RuleStyle.DASHED:
  446. style = "dashed";
  447. break;
  448. case RuleStyle.SOLID:
  449. break;
  450. case RuleStyle.DOUBLE:
  451. style = "double";
  452. break;
  453. case RuleStyle.GROOVE:
  454. style = "groove";
  455. break;
  456. case RuleStyle.RIDGE:
  457. style = "ridge";
  458. break;
  459. }
  460. writeElement("<leader width=\"" + area.getWidth()
  461. + "\" ruleStyle=\"" + style
  462. + "\" ruleThickness=\"" + area.getRuleThickness()
  463. + "\"/>");
  464. super.renderLeader(area);
  465. }
  466. /**
  467. * Builds a String with attributes from the trait map.
  468. * @param traitMap the trait map
  469. * @return String the generated attributes
  470. */
  471. protected String getPropString(Map traitMap) {
  472. StringBuffer strbuf = new StringBuffer();
  473. Iterator iter = traitMap.entrySet().iterator();
  474. while (iter.hasNext()) {
  475. Map.Entry traitEntry = (Map.Entry) iter.next();
  476. strbuf.append(Trait.getTraitName(traitEntry.getKey()));
  477. strbuf.append(':');
  478. strbuf.append(traitEntry.getValue().toString());
  479. strbuf.append(';');
  480. }
  481. return strbuf.toString();
  482. }
  483. }