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 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id: XMLRenderer.java,v 1.20 2004/04/25 04:45:28 gmazza Exp $ */
  17. package org.apache.fop.render.xml;
  18. // Java
  19. import java.io.IOException;
  20. import java.io.PrintWriter;
  21. import java.io.OutputStream;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Iterator;
  25. import java.awt.geom.Rectangle2D;
  26. import org.w3c.dom.Document;
  27. // FOP
  28. import org.apache.fop.render.AbstractRenderer;
  29. import org.apache.fop.render.RendererContext;
  30. import org.apache.fop.render.XMLHandler;
  31. import org.apache.fop.apps.FOUserAgent;
  32. import org.apache.fop.apps.FOPException;
  33. import org.apache.fop.area.BeforeFloat;
  34. import org.apache.fop.area.Block;
  35. import org.apache.fop.area.BodyRegion;
  36. import org.apache.fop.area.Flow;
  37. import org.apache.fop.area.Footnote;
  38. import org.apache.fop.area.LineArea;
  39. import org.apache.fop.area.MainReference;
  40. import org.apache.fop.area.PageViewport;
  41. import org.apache.fop.area.RegionReference;
  42. import org.apache.fop.area.RegionViewport;
  43. import org.apache.fop.area.Span;
  44. import org.apache.fop.area.Title;
  45. import org.apache.fop.area.Trait;
  46. import org.apache.fop.area.inline.Container;
  47. import org.apache.fop.area.inline.ForeignObject;
  48. import org.apache.fop.area.inline.Image;
  49. import org.apache.fop.area.inline.InlineArea;
  50. import org.apache.fop.area.inline.InlineParent;
  51. import org.apache.fop.area.inline.Leader;
  52. import org.apache.fop.area.inline.Space;
  53. import org.apache.fop.area.inline.Viewport;
  54. import org.apache.fop.area.inline.TextArea;
  55. import org.apache.fop.fonts.FontSetup;
  56. import org.apache.fop.fonts.FontInfo;
  57. import org.apache.fop.fo.pagination.Region;
  58. /**
  59. * Renderer that renders areas to XML for debugging purposes.
  60. * This creates an xml that contains the information of the area
  61. * tree. It does not output any state or derived information.
  62. * The output can be used to build a new area tree (@see AreaTreeBuilder)
  63. * which can be rendered to any renderer.
  64. */
  65. public class XMLRenderer extends AbstractRenderer {
  66. /** XML MIME type */
  67. public static final String XML_MIME_TYPE = "text/xml";
  68. private boolean startedSequence = false;
  69. private RendererContext context;
  70. /**
  71. * indentation to use for pretty-printing the XML
  72. */
  73. protected int indent = 0;
  74. /**
  75. * the application producing the XML
  76. */
  77. protected String producer;
  78. /**
  79. * the writer used to output the XML
  80. */
  81. protected PrintWriter writer;
  82. /**
  83. * options
  84. */
  85. private boolean consistentOutput = false;
  86. /**
  87. * Creates a new XML renderer.
  88. */
  89. public XMLRenderer() {
  90. context = new RendererContext(XML_MIME_TYPE);
  91. }
  92. /**
  93. * @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
  94. */
  95. public void setUserAgent(FOUserAgent agent) {
  96. super.setUserAgent(agent);
  97. //
  98. //userAgent.addExtensionHandler();
  99. XMLHandler handler = new XMLXMLHandler();
  100. setDefaultXMLHandler(userAgent, XML_MIME_TYPE, handler);
  101. String svg = "http://www.w3.org/2000/svg";
  102. addXMLHandler(userAgent, XML_MIME_TYPE, svg, handler);
  103. }
  104. /**
  105. * write out spaces to make indent
  106. */
  107. protected void writeIndent() {
  108. StringBuffer s = new StringBuffer();
  109. for (int i = 0; i < this.indent; i++) {
  110. s = s.append(" ");
  111. }
  112. this.writer.write(s.toString());
  113. }
  114. /**
  115. * write out an element
  116. *
  117. * @param element the full text of the element including tags
  118. */
  119. protected void writeElement(String element) {
  120. writeIndent();
  121. this.writer.write(element + "\n");
  122. }
  123. /**
  124. * write out an empty-element-tag
  125. *
  126. * @param tag the text of the tag
  127. */
  128. protected void writeEmptyElementTag(String tag) {
  129. writeIndent();
  130. this.writer.write(tag + "\n");
  131. }
  132. /**
  133. * write out an end tag
  134. *
  135. * @param tag the text of the tag
  136. */
  137. protected void writeEndTag(String tag) {
  138. this.indent--;
  139. writeIndent();
  140. this.writer.write(tag + "\n");
  141. }
  142. /**
  143. * write out a start tag
  144. *
  145. * @param tag the text of the tag
  146. */
  147. protected void writeStartTag(String tag) {
  148. writeIndent();
  149. this.writer.write(tag + "\n");
  150. this.indent++;
  151. }
  152. /**
  153. * set up the font info
  154. *
  155. * @param fontInfo the font info object to set up
  156. */
  157. public void setupFontInfo(FontInfo fontInfo) {
  158. FontSetup.setup(fontInfo, null);
  159. }
  160. private boolean isCoarseXml() {
  161. return ((Boolean)
  162. userAgent.getRendererOptions().get("fineDetail")).booleanValue();
  163. }
  164. /**
  165. * @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
  166. */
  167. public void startRenderer(OutputStream outputStream)
  168. throws IOException {
  169. getLogger().debug("rendering areas to XML");
  170. this.writer = new PrintWriter(outputStream);
  171. this.writer.write("<?xml version=\"1.0\"?>\n"
  172. + "<!-- produced by " + this.producer + " -->\n");
  173. writeStartTag("<areaTree>");
  174. }
  175. /**
  176. * @see org.apache.fop.render.Renderer#stopRenderer()
  177. */
  178. public void stopRenderer() throws IOException {
  179. writeEndTag("</pageSequence>");
  180. writeEndTag("</areaTree>");
  181. this.writer.flush();
  182. getLogger().debug("written out XML");
  183. }
  184. /**
  185. * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
  186. */
  187. public void renderPage(PageViewport page) throws IOException, FOPException {
  188. writeStartTag("<pageViewport bounds=\""
  189. + createString(page.getViewArea()) + "\">");
  190. writeStartTag("<page>");
  191. super.renderPage(page);
  192. writeEndTag("</page>");
  193. writeEndTag("</pageViewport>");
  194. }
  195. private String createString(Rectangle2D rect) {
  196. return "" + (int) rect.getX() + " " + (int) rect.getY() + " "
  197. + (int) rect.getWidth() + " " + (int) rect.getHeight();
  198. }
  199. /**
  200. * @see org.apache.fop.render.Renderer#startPageSequence(Title)
  201. */
  202. public void startPageSequence(Title seqTitle) {
  203. if (startedSequence) {
  204. writeEndTag("</pageSequence>");
  205. }
  206. startedSequence = true;
  207. writeStartTag("<pageSequence>");
  208. if (seqTitle != null) {
  209. writeStartTag("<title>");
  210. List children = seqTitle.getInlineAreas();
  211. for (int count = 0; count < children.size(); count++) {
  212. InlineArea inline = (InlineArea) children.get(count);
  213. renderInlineArea(inline);
  214. }
  215. writeEndTag("</title>");
  216. }
  217. }
  218. /**
  219. * @see org.apache.fop.render.AbstractRenderer#renderRegionViewport(RegionViewport)
  220. */
  221. protected void renderRegionViewport(RegionViewport port) {
  222. if (port != null) {
  223. writeStartTag("<regionViewport rect=\""
  224. + createString(port.getViewArea()) + "\">");
  225. RegionReference region = port.getRegion();
  226. if (region.getRegionClass() == Region.BEFORE_CODE) {
  227. writeStartTag("<regionBefore>");
  228. renderRegion(region);
  229. writeEndTag("</regionBefore>");
  230. } else if (region.getRegionClass() == Region.START_CODE) {
  231. writeStartTag("<regionStart>");
  232. renderRegion(region);
  233. writeEndTag("</regionStart>");
  234. } else if (region.getRegionClass() == Region.BODY_CODE) {
  235. writeStartTag("<regionBody>");
  236. renderBodyRegion((BodyRegion) region);
  237. writeEndTag("</regionBody>");
  238. } else if (region.getRegionClass() == Region.END_CODE) {
  239. writeStartTag("<regionEnd>");
  240. renderRegion(region);
  241. writeEndTag("</regionEnd>");
  242. } else if (region.getRegionClass() == Region.AFTER_CODE) {
  243. writeStartTag("<regionAfter>");
  244. renderRegion(region);
  245. writeEndTag("</regionAfter>");
  246. }
  247. writeEndTag("</regionViewport>");
  248. }
  249. }
  250. /**
  251. * @see org.apache.fop.render.AbstractRenderer#renderBeforeFloat(BeforeFloat)
  252. */
  253. protected void renderBeforeFloat(BeforeFloat bf) {
  254. writeStartTag("<beforeFloat>");
  255. super.renderBeforeFloat(bf);
  256. writeEndTag("</beforeFloat>");
  257. }
  258. /**
  259. * @see org.apache.fop.render.AbstractRenderer#renderFootnote(Footnote)
  260. */
  261. protected void renderFootnote(Footnote footnote) {
  262. writeStartTag("<footnote>");
  263. super.renderFootnote(footnote);
  264. writeEndTag("</footnote>");
  265. }
  266. /**
  267. * @see org.apache.fop.render.AbstractRenderer#renderMainReference(MainReference)
  268. */
  269. protected void renderMainReference(MainReference mr) {
  270. writeStartTag("<mainReference columnGap=\""
  271. + mr.getColumnGap() + "\" width=\"" + mr.getWidth() + "\">");
  272. Span span = null;
  273. List spans = mr.getSpans();
  274. for (int count = 0; count < spans.size(); count++) {
  275. span = (Span) spans.get(count);
  276. writeStartTag("<span>");
  277. for (int c = 0; c < span.getColumnCount(); c++) {
  278. Flow flow = (Flow) span.getFlow(c);
  279. renderFlow(flow);
  280. }
  281. writeEndTag("</span>");
  282. }
  283. writeEndTag("</mainReference>");
  284. }
  285. /**
  286. * @see org.apache.fop.render.AbstractRenderer#renderFlow(Flow)
  287. */
  288. protected void renderFlow(Flow flow) {
  289. // the normal flow reference area contains stacked blocks
  290. writeStartTag("<flow>");
  291. super.renderFlow(flow);
  292. writeEndTag("</flow>");
  293. }
  294. /**
  295. * @see org.apache.fop.render.AbstractRenderer#renderBlock(Block)
  296. */
  297. protected void renderBlock(Block block) {
  298. String prop = " width=\"" + block.getWidth() +
  299. "\" ipd=\"" + block.getIPD() +
  300. "\" height=\"" + block.getHeight() + "\"";
  301. Map map = block.getTraits();
  302. if (map != null) {
  303. prop = prop + " props=\"" + getPropString(map) + "\"";
  304. }
  305. writeStartTag("<block" + prop + ">");
  306. super.renderBlock(block);
  307. writeEndTag("</block>");
  308. }
  309. /**
  310. * @see org.apache.fop.render.AbstractRenderer#renderLineArea(LineArea)
  311. */
  312. protected void renderLineArea(LineArea line) {
  313. String prop = "";
  314. Map map = line.getTraits();
  315. if (map != null) {
  316. prop = " props=\"" + getPropString(map) + "\"";
  317. }
  318. writeStartTag("<lineArea height=\"" + line.getHeight() + "\""
  319. + prop + ">");
  320. super.renderLineArea(line);
  321. writeEndTag("</lineArea>");
  322. }
  323. /**
  324. * @see org.apache.fop.render.Renderer#renderViewport(Viewport)
  325. */
  326. protected void renderViewport(Viewport viewport) {
  327. writeStartTag("<viewport>");
  328. super.renderViewport(viewport);
  329. writeEndTag("</viewport>");
  330. }
  331. /**
  332. * Renders an image
  333. * @param image the image
  334. */
  335. public void renderImage(Image image) {
  336. writeElement("<image url=\"" + image.getURL() + "\"/>");
  337. }
  338. /**
  339. * @see org.apache.fop.render.Renderer#renderContainer(Container)
  340. */
  341. public void renderContainer(Container cont) {
  342. writeStartTag("<container>");
  343. super.renderContainer(cont);
  344. writeEndTag("</container>");
  345. }
  346. /**
  347. * Renders an fo:foreing-object.
  348. * @param fo the foreign object
  349. */
  350. public void renderForeignObject(ForeignObject fo) {
  351. writeStartTag("<foreignObject>");
  352. Document doc = fo.getDocument();
  353. String ns = fo.getNameSpace();
  354. context.setProperty(XMLXMLHandler.WRITER, writer);
  355. renderXML(userAgent, context, doc, ns);
  356. writeEndTag("</foreignObject>");
  357. }
  358. /**
  359. * @see org.apache.fop.render.Renderer#renderCharacter(Character)
  360. */
  361. protected void renderCharacter(org.apache.fop.area.inline.Character ch) {
  362. String prop = "";
  363. Map map = ch.getTraits();
  364. if (map != null) {
  365. prop = " props=\"" + getPropString(map) + "\"";
  366. }
  367. writeElement("<char" + prop + ">" + ch.getChar() + "</char>");
  368. }
  369. /**
  370. * @see org.apache.fop.render.Renderer#renderInlineSpace(Space)
  371. */
  372. protected void renderInlineSpace(Space space) {
  373. writeElement("<space width=\"" + space.getWidth() + "\"/>");
  374. }
  375. /**
  376. * @see org.apache.fop.render.Renderer#renderText(TextArea)
  377. */
  378. protected void renderText(TextArea text) {
  379. String prop = "";
  380. Map map = text.getTraits();
  381. if (map != null) {
  382. prop = " props=\"" + getPropString(map) + "\"";
  383. }
  384. writeElement("<text tsadjust=\"" + text.getTextSpaceAdjust() + "\""
  385. + prop + ">" + text.getTextArea() + "</text>");
  386. super.renderText(text);
  387. }
  388. /**
  389. * @see org.apache.fop.render.Renderer#renderInlineParent(InlineParent)
  390. */
  391. protected void renderInlineParent(InlineParent ip) {
  392. String prop = "";
  393. Map map = ip.getTraits();
  394. if (map != null) {
  395. prop = " props=\"" + getPropString(map) + "\"";
  396. }
  397. writeStartTag("<inlineparent" + prop + ">");
  398. super.renderInlineParent(ip);
  399. writeEndTag("</inlineparent>");
  400. }
  401. /**
  402. * @see org.apache.fop.render.Renderer#renderLeader(Leader)
  403. */
  404. protected void renderLeader(Leader area) {
  405. String style = "solid";
  406. switch (area.getRuleStyle()) {
  407. case RuleStyle.DOTTED:
  408. style = "dotted";
  409. break;
  410. case RuleStyle.DASHED:
  411. style = "dashed";
  412. break;
  413. case RuleStyle.SOLID:
  414. break;
  415. case RuleStyle.DOUBLE:
  416. style = "double";
  417. break;
  418. case RuleStyle.GROOVE:
  419. style = "groove";
  420. break;
  421. case RuleStyle.RIDGE:
  422. style = "ridge";
  423. break;
  424. }
  425. writeElement("<leader width=\"" + area.getWidth()
  426. + "\" ruleStyle=\"" + style
  427. + "\" ruleThickness=\"" + area.getRuleThickness()
  428. + "\"/>");
  429. super.renderLeader(area);
  430. }
  431. /**
  432. * Builds a String with attributes from the trait map.
  433. * @param traitMap the trait map
  434. * @return String the generated attributes
  435. */
  436. protected String getPropString(Map traitMap) {
  437. StringBuffer strbuf = new StringBuffer();
  438. Iterator iter = traitMap.entrySet().iterator();
  439. while (iter.hasNext()) {
  440. Map.Entry traitEntry = (Map.Entry) iter.next();
  441. strbuf.append(Trait.getTraitName(traitEntry.getKey()));
  442. strbuf.append(':');
  443. strbuf.append(traitEntry.getValue().toString());
  444. strbuf.append(';');
  445. }
  446. return strbuf.toString();
  447. }
  448. }