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

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