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

Fop.java gets two new constructors: Fop(String) and Fop(String, FOUserAgent) where the String is the MIME type for the desired output format. MimeConstants provides a comprehensive list of MIME types used in Fop.java. Non-standard, FOP-specific MIME types changed to a uniform pattern: application/X-fop-awt-preview, application/X-fop-print and application/X-fop-areatree. RendererFactory now supports manual registration and dynamic discovery of Renderers and FOEventHandlers by their MIME types. Instantitation is done using MIME types everywhere. The RENDER_* constants are mapped to MIME types in Fop.java. RendererFactory is now an instantiable class whose reference is held by FOUserAgent just like it is done for the XLMHandlers. Renderers and FOEventHandlers now each have a *Maker class which is a kind of factory class which is used to register a Renderer/FOEventHandler and additionally serves to provide additional information about the thing, such as the MIME types it supports and if the implementation requires an OutputStream. The command-line gets a new option: -out application/pdf myfile.pdf is the generic way to create an output file. If someone created a WordML output handler and provided the right service resource file he could specify "-out text/xml+msword out.xml". ".out list" lists all MIME types that are available for output. Renderers can now potionally expose a Graphics2DAdapter which in concert with Graphics2DImagePainter can be used by FOP extensions to paint their content directly using a Graphics2D instance. That makes it possible to avoid a detour via SVG/Batik in certain cases. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@332549 13f79535-47bb-0310-9956-ffa450edef68
18 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. /*
  2. * Copyright 1999-2005 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$ */
  17. package org.apache.fop.render;
  18. // Java
  19. import java.awt.Rectangle;
  20. import java.awt.geom.Rectangle2D;
  21. import java.io.IOException;
  22. import java.io.OutputStream;
  23. import java.util.List;
  24. import java.util.Iterator;
  25. import java.util.Set;
  26. // XML
  27. import org.w3c.dom.Document;
  28. // FOP
  29. import org.apache.fop.apps.FOPException;
  30. import org.apache.fop.area.Area;
  31. import org.apache.fop.area.BeforeFloat;
  32. import org.apache.fop.area.Block;
  33. import org.apache.fop.area.BlockViewport;
  34. import org.apache.fop.area.BodyRegion;
  35. import org.apache.fop.area.CTM;
  36. import org.apache.fop.area.NormalFlow;
  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.Span;
  41. import org.apache.fop.area.Page;
  42. import org.apache.fop.area.PageViewport;
  43. import org.apache.fop.area.RegionViewport;
  44. import org.apache.fop.area.RegionReference;
  45. import org.apache.fop.area.Trait;
  46. import org.apache.fop.area.OffDocumentItem;
  47. import org.apache.fop.area.inline.Container;
  48. import org.apache.fop.area.inline.ForeignObject;
  49. import org.apache.fop.area.inline.Image;
  50. import org.apache.fop.area.inline.InlineArea;
  51. import org.apache.fop.area.inline.InlineBlockParent;
  52. import org.apache.fop.area.inline.InlineParent;
  53. import org.apache.fop.area.inline.Leader;
  54. import org.apache.fop.area.inline.Space;
  55. import org.apache.fop.area.inline.Viewport;
  56. import org.apache.fop.area.inline.TextArea;
  57. import org.apache.fop.area.inline.Character;
  58. import org.apache.fop.area.inline.WordArea;
  59. import org.apache.fop.area.inline.SpaceArea;
  60. import org.apache.fop.apps.FOUserAgent;
  61. import org.apache.fop.fo.Constants;
  62. import org.apache.fop.fonts.FontInfo;
  63. import org.apache.commons.logging.Log;
  64. import org.apache.commons.logging.LogFactory;
  65. // Avalon
  66. import org.apache.avalon.framework.configuration.Configurable;
  67. import org.apache.avalon.framework.configuration.Configuration;
  68. import org.apache.avalon.framework.configuration.ConfigurationException;
  69. /**
  70. * Abstract base class for all renderers. The Abstract renderer does all the
  71. * top level processing of the area tree and adds some abstract methods to
  72. * handle viewports. This keeps track of the current block and inline position.
  73. */
  74. public abstract class AbstractRenderer
  75. implements Renderer, Configurable, Constants {
  76. /** logging instance */
  77. protected static Log log = LogFactory.getLog("org.apache.fop.render");
  78. /**
  79. * user agent
  80. */
  81. protected FOUserAgent userAgent;
  82. /**
  83. * block progression position
  84. */
  85. protected int currentBPPosition = 0;
  86. /**
  87. * inline progression position
  88. */
  89. protected int currentIPPosition = 0;
  90. /**
  91. * the block progression position of the containing block used for
  92. * absolutely positioned blocks
  93. */
  94. protected int containingBPPosition = 0;
  95. /**
  96. * the inline progression position of the containing block used for
  97. * absolutely positioned blocks
  98. */
  99. protected int containingIPPosition = 0;
  100. private Set warnedXMLHandlers;
  101. /**
  102. * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
  103. */
  104. public void configure(Configuration conf) throws ConfigurationException {
  105. }
  106. /**
  107. * @see org.apache.fop.render.Renderer#setupFontInfo(FontInfo)
  108. */
  109. public abstract void setupFontInfo(FontInfo fontInfo);
  110. /**
  111. * @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
  112. */
  113. public void setUserAgent(FOUserAgent agent) {
  114. userAgent = agent;
  115. }
  116. /** @see org.apache.fop.render.Renderer#startRenderer(OutputStream) */
  117. public void startRenderer(OutputStream outputStream)
  118. throws IOException { }
  119. /** @see org.apache.fop.render.Renderer#stopRenderer() */
  120. public void stopRenderer()
  121. throws IOException { }
  122. /**
  123. * Check if this renderer supports out of order rendering. If this renderer
  124. * supports out of order rendering then it means that the pages that are
  125. * not ready will be prepared and a future page will be rendered.
  126. *
  127. * @return True if the renderer supports out of order rendering
  128. * @see org.apache.fop.render.Renderer
  129. */
  130. public boolean supportsOutOfOrder() {
  131. return false;
  132. }
  133. /**
  134. * @see org.apache.fop.render.Renderer#processOffDocumentItem(OffDocumentItem)
  135. */
  136. public void processOffDocumentItem(OffDocumentItem oDI) { }
  137. /** @see org.apache.fop.render.Renderer#getGraphics2DAdapter() */
  138. public Graphics2DAdapter getGraphics2DAdapter() {
  139. return null;
  140. }
  141. /**
  142. * Prepare a page for rendering. This is called if the renderer supports
  143. * out of order rendering. The renderer should prepare the page so that a
  144. * page further on in the set of pages can be rendered. The body of the
  145. * page should not be rendered. The page will be rendered at a later time
  146. * by the call to render page.
  147. *
  148. * @see org.apache.fop.render.Renderer#preparePage(PageViewport)
  149. */
  150. public void preparePage(PageViewport page) { }
  151. /**
  152. * Utility method to convert a page sequence title to a string. Some
  153. * renderers may only be able to use a string title. A title is a sequence
  154. * of inline areas that this method attempts to convert to an equivalent
  155. * string.
  156. *
  157. * @param title The Title to convert
  158. * @return An expanded string representing the title
  159. */
  160. protected String convertTitleToString(LineArea title) {
  161. List children = title.getInlineAreas();
  162. String str = convertToString(children);
  163. return str.trim();
  164. }
  165. private String convertToString(List children) {
  166. StringBuffer sb = new StringBuffer();
  167. for (int count = 0; count < children.size(); count++) {
  168. InlineArea inline = (InlineArea) children.get(count);
  169. if (inline instanceof Character) {
  170. sb.append(((Character) inline).getChar());
  171. } else if (inline instanceof TextArea) {
  172. sb.append(((TextArea) inline).getText());
  173. } else if (inline instanceof InlineParent) {
  174. sb.append(convertToString(
  175. ((InlineParent) inline).getChildAreas()));
  176. } else {
  177. sb.append(" ");
  178. }
  179. }
  180. return sb.toString();
  181. }
  182. /** @see org.apache.fop.render.Renderer#startPageSequence(LineArea) */
  183. public void startPageSequence(LineArea seqTitle) {
  184. //do nothing
  185. }
  186. // normally this would be overriden to create a page in the
  187. // output
  188. /** @see org.apache.fop.render.Renderer#renderPage(PageViewport) */
  189. public void renderPage(PageViewport page)
  190. throws IOException, FOPException {
  191. Page p = page.getPage();
  192. renderPageAreas(p);
  193. }
  194. /**
  195. * Renders page areas.
  196. *
  197. * @param page The page whos page areas are to be rendered
  198. */
  199. protected void renderPageAreas(Page page) {
  200. /* Spec does not appear to specify whether fo:region-body should
  201. appear above or below side regions in cases of overlap. FOP
  202. decision is to have fo:region-body on top, hence it is rendered
  203. last here. */
  204. RegionViewport viewport;
  205. viewport = page.getRegionViewport(FO_REGION_BEFORE);
  206. renderRegionViewport(viewport);
  207. viewport = page.getRegionViewport(FO_REGION_START);
  208. renderRegionViewport(viewport);
  209. viewport = page.getRegionViewport(FO_REGION_END);
  210. renderRegionViewport(viewport);
  211. viewport = page.getRegionViewport(FO_REGION_AFTER);
  212. renderRegionViewport(viewport);
  213. viewport = page.getRegionViewport(FO_REGION_BODY);
  214. renderRegionViewport(viewport);
  215. }
  216. /**
  217. * Renders a region viewport. <p>
  218. *
  219. * The region may clip the area and it establishes a position from where
  220. * the region is placed.</p>
  221. *
  222. * @param port The region viewport to be rendered
  223. */
  224. protected void renderRegionViewport(RegionViewport port) {
  225. if (port != null) {
  226. Rectangle2D view = port.getViewArea();
  227. // The CTM will transform coordinates relative to
  228. // this region-reference area into page coords, so
  229. // set origin for the region to 0,0.
  230. currentBPPosition = 0;
  231. currentIPPosition = 0;
  232. RegionReference regionReference = port.getRegionReference();
  233. handleRegionTraits(port);
  234. // shouldn't the viewport have the CTM
  235. startVParea(regionReference.getCTM(), port.isClip() ? view : null);
  236. // do after starting viewport area
  237. if (regionReference.getRegionClass() == FO_REGION_BODY) {
  238. renderBodyRegion((BodyRegion) regionReference);
  239. } else {
  240. renderRegion(regionReference);
  241. }
  242. endVParea();
  243. }
  244. }
  245. /**
  246. * Establishes a new viewport area.
  247. *
  248. * @param ctm the coordinate transformation matrix to use
  249. * @param clippingRect the clipping rectangle if the viewport should be clipping,
  250. * null if no clipping is performed.
  251. */
  252. protected abstract void startVParea(CTM ctm, Rectangle2D clippingRect);
  253. /**
  254. * Signals exit from a viewport area. Subclasses can restore transformation matrices
  255. * valid before the viewport area was started.
  256. */
  257. protected abstract void endVParea();
  258. /**
  259. * Handle the traits for a region
  260. * This is used to draw the traits for the given page region.
  261. * (See Sect. 6.4.1.2 of XSL-FO spec.)
  262. * @param rv the RegionViewport whose region is to be drawn
  263. */
  264. protected void handleRegionTraits(RegionViewport rv) {
  265. // draw border and background
  266. }
  267. /**
  268. * Renders a region reference area.
  269. *
  270. * @param region The region reference area
  271. */
  272. protected void renderRegion(RegionReference region) {
  273. List blocks = region.getBlocks();
  274. renderBlocks(null, blocks);
  275. }
  276. /**
  277. * Renders a body region area.
  278. *
  279. * @param region The body region
  280. */
  281. protected void renderBodyRegion(BodyRegion region) {
  282. BeforeFloat bf = region.getBeforeFloat();
  283. if (bf != null) {
  284. renderBeforeFloat(bf);
  285. }
  286. MainReference mr = region.getMainReference();
  287. if (mr != null) {
  288. renderMainReference(mr);
  289. }
  290. Footnote foot = region.getFootnote();
  291. if (foot != null) {
  292. renderFootnote(foot);
  293. }
  294. }
  295. /**
  296. * Renders a before float area.
  297. *
  298. * @param bf The before float area
  299. */
  300. protected void renderBeforeFloat(BeforeFloat bf) {
  301. List blocks = bf.getChildAreas();
  302. if (blocks != null) {
  303. renderBlocks(null, blocks);
  304. Block sep = bf.getSeparator();
  305. if (sep != null) {
  306. renderBlock(sep);
  307. }
  308. }
  309. }
  310. /**
  311. * Renders a footnote
  312. *
  313. * @param footnote The footnote
  314. */
  315. protected void renderFootnote(Footnote footnote) {
  316. currentBPPosition += footnote.getTop();
  317. List blocks = footnote.getChildAreas();
  318. if (blocks != null) {
  319. Block sep = footnote.getSeparator();
  320. if (sep != null) {
  321. renderBlock(sep);
  322. }
  323. renderBlocks(null, blocks);
  324. }
  325. }
  326. /**
  327. * Renders the main reference area.
  328. * <p>
  329. * The main reference area contains a list of spans that are
  330. * stacked on the page.
  331. * The spans contain a list of normal flow reference areas
  332. * that are positioned into columns.
  333. * </p>
  334. *
  335. * @param mr The main reference area
  336. */
  337. protected void renderMainReference(MainReference mr) {
  338. int saveIPPos = currentIPPosition;
  339. Span span = null;
  340. List spans = mr.getSpans();
  341. int saveBPPos = currentBPPosition;
  342. int saveSpanBPPos = saveBPPos;
  343. for (int count = 0; count < spans.size(); count++) {
  344. span = (Span) spans.get(count);
  345. for (int c = 0; c < span.getColumnCount(); c++) {
  346. NormalFlow flow = (NormalFlow) span.getNormalFlow(c);
  347. if (flow != null) {
  348. currentBPPosition = saveSpanBPPos;
  349. renderFlow(flow);
  350. currentIPPosition += flow.getIPD();
  351. currentIPPosition += mr.getColumnGap();
  352. }
  353. }
  354. currentIPPosition = saveIPPos;
  355. currentBPPosition = saveSpanBPPos + span.getHeight();
  356. saveSpanBPPos = currentBPPosition;
  357. }
  358. currentBPPosition = saveBPPos;
  359. }
  360. /**
  361. * Renders a flow reference area.
  362. *
  363. * @param flow The flow reference area
  364. */
  365. protected void renderFlow(NormalFlow flow) {
  366. // the normal flow reference area contains stacked blocks
  367. List blocks = flow.getChildAreas();
  368. if (blocks != null) {
  369. renderBlocks(null, blocks);
  370. }
  371. }
  372. /**
  373. * Handle block traits.
  374. * This method is called when the correct ip and bp posiiton is
  375. * set. This should be overridden to draw border and background
  376. * traits for the block area.
  377. *
  378. * @param block the block area
  379. */
  380. protected void handleBlockTraits(Block block) {
  381. // draw border and background
  382. }
  383. /**
  384. * Renders a block viewport.
  385. *
  386. * @param bv The block viewport
  387. * @param children The children to render within the block viewport
  388. */
  389. protected void renderBlockViewport(BlockViewport bv, List children) {
  390. // clip and position viewport if necessary
  391. if (bv.getPositioning() == Block.ABSOLUTE) {
  392. // save positions
  393. int saveIP = currentIPPosition;
  394. int saveBP = currentBPPosition;
  395. Rectangle2D clippingRect = null;
  396. if (bv.getClip()) {
  397. clippingRect = new Rectangle(saveIP, saveBP, bv.getIPD(), bv.getIPD());
  398. }
  399. CTM ctm = bv.getCTM();
  400. currentIPPosition = 0;
  401. currentBPPosition = 0;
  402. startVParea(ctm, clippingRect);
  403. handleBlockTraits(bv);
  404. renderBlocks(bv, children);
  405. endVParea();
  406. // clip if necessary
  407. currentIPPosition = saveIP;
  408. currentBPPosition = saveBP;
  409. } else {
  410. // save position and offset
  411. int saveIP = currentIPPosition;
  412. int saveBP = currentBPPosition;
  413. handleBlockTraits(bv);
  414. renderBlocks(bv, children);
  415. currentIPPosition = saveIP;
  416. currentBPPosition = saveBP + bv.getAllocBPD();
  417. }
  418. }
  419. /**
  420. * Renders a list of block areas.
  421. *
  422. * @param parent the parent block if the parent is a block, otherwise
  423. * a null value.
  424. * @param blocks The block areas
  425. */
  426. protected void renderBlocks(Block parent, List blocks) {
  427. int saveIP = currentIPPosition;
  428. int saveBP = currentBPPosition;
  429. // Calculate the position of the content rectangle.
  430. if (parent != null && !Boolean.TRUE.equals(parent.getTrait(Trait.IS_VIEWPORT_AREA))) {
  431. currentBPPosition += parent.getBorderAndPaddingWidthBefore();
  432. /* This is unnecessary now as we're going to use the *-indent traits
  433. currentIPPosition += parent.getBorderAndPaddingWidthStart();
  434. Integer spaceStart = (Integer) parent.getTrait(Trait.SPACE_START);
  435. if (spaceStart != null) {
  436. currentIPPosition += spaceStart.intValue();
  437. }*/
  438. }
  439. // the position of the containing block is used for
  440. // absolutely positioned areas
  441. int contBP = currentBPPosition;
  442. int contIP = currentIPPosition;
  443. containingBPPosition = currentBPPosition;
  444. containingIPPosition = currentIPPosition;
  445. for (int count = 0; count < blocks.size(); count++) {
  446. Object obj = blocks.get(count);
  447. if (obj instanceof Block) {
  448. currentIPPosition = contIP;
  449. containingBPPosition = contBP;
  450. containingIPPosition = contIP;
  451. renderBlock((Block) obj);
  452. containingBPPosition = contBP;
  453. containingIPPosition = contIP;
  454. } else {
  455. // a line area is rendered from the top left position
  456. // of the line, each inline object is offset from there
  457. LineArea line = (LineArea) obj;
  458. currentIPPosition = contIP
  459. + parent.getStartIndent()
  460. + line.getStartIndent();
  461. renderLineArea(line);
  462. //InlineArea child = (InlineArea) line.getInlineAreas().get(0);
  463. currentBPPosition += line.getAllocBPD();
  464. }
  465. currentIPPosition = saveIP;
  466. }
  467. }
  468. /**
  469. * Renders a block area.
  470. *
  471. * @param block The block area
  472. */
  473. protected void renderBlock(Block block) {
  474. List children = block.getChildAreas();
  475. if (block instanceof BlockViewport) {
  476. if (children != null) {
  477. renderBlockViewport((BlockViewport) block, children);
  478. } else {
  479. handleBlockTraits(block);
  480. // simply move position
  481. currentBPPosition += block.getAllocBPD();
  482. }
  483. } else {
  484. // save position and offset
  485. int saveIP = currentIPPosition;
  486. int saveBP = currentBPPosition;
  487. if (block.getPositioning() == Block.ABSOLUTE) {
  488. currentIPPosition += block.getXOffset();
  489. currentBPPosition += block.getYOffset();
  490. currentBPPosition += block.getSpaceBefore();
  491. handleBlockTraits(block);
  492. if (children != null) {
  493. renderBlocks(block, children);
  494. }
  495. // absolute blocks do not effect the layout
  496. currentBPPosition = saveBP;
  497. } else {
  498. // relative blocks are offset
  499. currentIPPosition += block.getXOffset();
  500. currentBPPosition += block.getYOffset();
  501. currentBPPosition += block.getSpaceBefore();
  502. handleBlockTraits(block);
  503. if (children != null) {
  504. renderBlocks(block, children);
  505. }
  506. // stacked and relative blocks effect stacking
  507. currentIPPosition = saveIP;
  508. currentBPPosition = saveBP + block.getAllocBPD();
  509. }
  510. }
  511. }
  512. /**
  513. * Renders a line area. <p>
  514. *
  515. * A line area may have grouped styling for its children such as underline,
  516. * background.</p>
  517. *
  518. * @param line The line area
  519. */
  520. protected void renderLineArea(LineArea line) {
  521. List children = line.getInlineAreas();
  522. int saveBP = currentBPPosition;
  523. currentBPPosition += line.getSpaceBefore();
  524. for (int count = 0; count < children.size(); count++) {
  525. InlineArea inline = (InlineArea) children.get(count);
  526. renderInlineArea(inline);
  527. }
  528. currentBPPosition = saveBP;
  529. }
  530. /**
  531. * Render the given InlineArea.
  532. * @param inlineArea inline area text to render
  533. */
  534. protected void renderInlineArea(InlineArea inlineArea) {
  535. if (inlineArea instanceof TextArea) {
  536. renderText((TextArea) inlineArea);
  537. } else if (inlineArea instanceof Character) {
  538. renderCharacter((Character) inlineArea);
  539. } else if (inlineArea instanceof WordArea) {
  540. renderWord((WordArea) inlineArea);
  541. } else if (inlineArea instanceof SpaceArea) {
  542. renderSpace((SpaceArea) inlineArea);
  543. } else if (inlineArea instanceof InlineParent) {
  544. renderInlineParent((InlineParent) inlineArea);
  545. } else if (inlineArea instanceof InlineBlockParent) {
  546. renderInlineBlockParent((InlineBlockParent) inlineArea);
  547. } else if (inlineArea instanceof Space) {
  548. renderInlineSpace((Space) inlineArea);
  549. } else if (inlineArea instanceof Viewport) {
  550. renderViewport((Viewport) inlineArea);
  551. } else if (inlineArea instanceof Leader) {
  552. renderLeader((Leader) inlineArea);
  553. }
  554. }
  555. /**
  556. * Render the given Character.
  557. * @param ch the character to render
  558. */
  559. protected void renderCharacter(Character ch) {
  560. currentIPPosition += ch.getAllocIPD();
  561. }
  562. /**
  563. * Render the given Space.
  564. * @param space the space to render
  565. */
  566. protected void renderInlineSpace(Space space) {
  567. // an inline space moves the inline progression position
  568. // for the current block by the width or height of the space
  569. // it may also have styling (only on this object) that needs
  570. // handling
  571. currentIPPosition += space.getAllocIPD();
  572. }
  573. /**
  574. * Render the given Leader.
  575. * @param area the leader to render
  576. */
  577. protected void renderLeader(Leader area) {
  578. currentIPPosition += area.getAllocIPD();
  579. }
  580. /**
  581. * Render the given TextArea.
  582. * @param text the text to render
  583. */
  584. protected void renderText(TextArea text) {
  585. int saveIP = currentIPPosition;
  586. int saveBP = currentBPPosition;
  587. Iterator iter = text.getChildAreas().iterator();
  588. while (iter.hasNext()) {
  589. renderInlineArea((InlineArea) iter.next());
  590. }
  591. currentIPPosition = saveIP + text.getAllocIPD();
  592. }
  593. /**
  594. * Render the given WordArea.
  595. * @param word the word to render
  596. */
  597. protected void renderWord(WordArea word) {
  598. currentIPPosition += word.getAllocIPD();
  599. }
  600. /**
  601. * Render the given SpaceArea.
  602. * @param space the space to render
  603. */
  604. protected void renderSpace(SpaceArea space) {
  605. currentIPPosition += space.getAllocIPD();
  606. }
  607. /**
  608. * Render the given InlineParent.
  609. * @param ip the inline parent to render
  610. */
  611. protected void renderInlineParent(InlineParent ip) {
  612. int saveIP = currentIPPosition;
  613. int saveBP = currentBPPosition;
  614. currentIPPosition += ip.getBorderAndPaddingWidthStart();
  615. currentBPPosition += ip.getOffset();
  616. Iterator iter = ip.getChildAreas().iterator();
  617. while (iter.hasNext()) {
  618. renderInlineArea((InlineArea) iter.next());
  619. }
  620. currentIPPosition = saveIP + ip.getAllocIPD();
  621. currentBPPosition = saveBP;
  622. }
  623. /**
  624. * Render the given InlineBlockParent.
  625. * @param ibp the inline block parent to render
  626. */
  627. protected void renderInlineBlockParent(InlineBlockParent ibp) {
  628. currentIPPosition += ibp.getBorderAndPaddingWidthStart();
  629. // For inline content the BP position is updated by the enclosing line area
  630. int saveBP = currentBPPosition;
  631. currentBPPosition += ibp.getOffset();
  632. renderBlock(ibp.getChildArea());
  633. currentBPPosition = saveBP;
  634. }
  635. /**
  636. * Render the given Viewport.
  637. * @param viewport the viewport to render
  638. */
  639. protected void renderViewport(Viewport viewport) {
  640. Area content = viewport.getContent();
  641. int saveBP = currentBPPosition;
  642. currentBPPosition += viewport.getOffset();
  643. Rectangle2D contpos = viewport.getContentPosition();
  644. if (content instanceof Image) {
  645. renderImage((Image) content, contpos);
  646. } else if (content instanceof Container) {
  647. renderContainer((Container) content);
  648. } else if (content instanceof ForeignObject) {
  649. renderForeignObject((ForeignObject) content, contpos);
  650. }
  651. currentIPPosition += viewport.getAllocIPD();
  652. currentBPPosition = saveBP;
  653. }
  654. /**
  655. * Renders an image area.
  656. *
  657. * @param image The image
  658. * @param pos The target position of the image
  659. * (todo) Make renderImage() protected
  660. */
  661. public void renderImage(Image image, Rectangle2D pos) {
  662. // Default: do nothing.
  663. // Some renderers (ex. Text) don't support images.
  664. }
  665. /**
  666. * Tells the renderer to render an inline container.
  667. * @param cont The inline container area
  668. */
  669. protected void renderContainer(Container cont) {
  670. int saveIP = currentIPPosition;
  671. int saveBP = currentBPPosition;
  672. List blocks = cont.getBlocks();
  673. renderBlocks(null, blocks);
  674. currentIPPosition = saveIP;
  675. currentBPPosition = saveBP;
  676. }
  677. /**
  678. * Renders a foreign object area.
  679. *
  680. * @param fo The foreign object area
  681. * @param pos The target position of the foreign object
  682. * (todo) Make renderForeignObject() protected
  683. */
  684. public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
  685. // Default: do nothing.
  686. // Some renderers (ex. Text) don't support foreign objects.
  687. }
  688. /**
  689. * Returns the configuration subtree for a specific renderer.
  690. * @param cfg the renderer configuration
  691. * @param namespace the namespace (i.e. the XMLHandler) for which the configuration should
  692. * be returned
  693. * @return the requested configuration subtree, null if there's no configuration
  694. */
  695. public static Configuration getHandlerConfig(Configuration cfg, String namespace) {
  696. if (cfg == null || namespace == null) {
  697. return null;
  698. }
  699. Configuration handlerConfig = null;
  700. Configuration[] children = cfg.getChildren("xml-handler");
  701. for (int i = 0; i < children.length; ++i) {
  702. try {
  703. if (children[i].getAttribute("namespace").equals(namespace)) {
  704. handlerConfig = children[i];
  705. break;
  706. }
  707. } catch (ConfigurationException e) {
  708. // silently pass over configurations without namespace
  709. }
  710. }
  711. if (log.isDebugEnabled()) {
  712. log.debug((handlerConfig == null ? "No" : "")
  713. + "XML handler configuration found for namespace " + namespace);
  714. }
  715. return handlerConfig;
  716. }
  717. /**
  718. * Render the xml document with the given xml namespace.
  719. * The Render Context is by the handle to render into the current
  720. * rendering target.
  721. * @param ctx rendering context
  722. * @param doc DOM Document containing the source document
  723. * @param namespace Namespace URI of the document
  724. */
  725. public void renderXML(RendererContext ctx, Document doc,
  726. String namespace) {
  727. XMLHandler handler = userAgent.getXMLHandlerRegistry().getXMLHandler(
  728. this, namespace);
  729. if (handler != null) {
  730. try {
  731. //Optional XML handler configuration
  732. Configuration cfg = userAgent.getUserRendererConfig(getMimeType());
  733. if (cfg != null) {
  734. cfg = getHandlerConfig(cfg, namespace);
  735. if (cfg != null) {
  736. ctx.setProperty(RendererContextConstants.HANDLER_CONFIGURATION, cfg);
  737. }
  738. }
  739. handler.handleXML(ctx, doc, namespace);
  740. } catch (Throwable t) {
  741. // could not handle document
  742. log.error("Some XML content will be ignored. "
  743. + "Could not render XML", t);
  744. }
  745. } else {
  746. if (warnedXMLHandlers == null) {
  747. warnedXMLHandlers = new java.util.HashSet();
  748. }
  749. if (!warnedXMLHandlers.contains(namespace)) {
  750. // no handler found for document
  751. warnedXMLHandlers.add(namespace);
  752. log.warn("Some XML content will be ignored. "
  753. + "No handler defined for XML: " + namespace);
  754. }
  755. }
  756. }
  757. /**
  758. * Get the MIME type of the renderer.
  759. *
  760. * @return The MIME type of the renderer
  761. */
  762. public String getMimeType() {
  763. return null;
  764. }
  765. }