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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. package org.apache.fop.render.awt;
  2. /*
  3. originally contributed by
  4. Juergen Verwohlt: Juergen.Verwohlt@af-software.de,
  5. Rainer Steinkuhle: Rainer.Steinkuhle@af-software.de,
  6. Stanislav Gorkhover: Stanislav.Gorkhover@af-software.de
  7. */
  8. import org.apache.fop.layout.*;
  9. import org.apache.fop.messaging.MessageHandler;
  10. import org.apache.fop.datatypes.*;
  11. import org.apache.fop.image.*;
  12. import org.apache.fop.svg.*;
  13. import org.apache.fop.render.pdf.*;
  14. import org.apache.fop.viewer.*;
  15. import org.apache.fop.apps.*;
  16. import org.apache.fop.render.Renderer;
  17. import java.awt.*;
  18. import java.awt.image.*;
  19. import java.awt.geom.*;
  20. import java.awt.font.*;
  21. import java.util.*;
  22. import java.io.*;
  23. import java.beans.*;
  24. import javax.swing.*;
  25. import java.awt.print.*;
  26. import java.awt.image.BufferedImage;
  27. public class AWTRenderer implements Renderer, Printable, Pageable {
  28. protected int pageWidth = 0;
  29. protected int pageHeight = 0;
  30. protected double scaleFactor = 100.0;
  31. protected int pageNumber = 0;
  32. protected AreaTree tree;
  33. protected ProgressListener progressListener = null;
  34. protected Translator res = null;
  35. protected Hashtable fontNames = new Hashtable();
  36. protected Hashtable fontStyles = new Hashtable();
  37. protected Color saveColor;
  38. // Key - Font name, Value - java Font name.
  39. protected static Hashtable JAVA_FONT_NAMES;
  40. /**
  41. * Image Object and Graphics Object. The Graphics Object is the Graphics
  42. * object that is contained withing the Image Object.
  43. */
  44. private BufferedImage pageImage = null;
  45. private Graphics2D graphics = null;
  46. /**
  47. * The current (internal) font name
  48. */
  49. protected String currentFontName;
  50. /**
  51. * The current font size in millipoints
  52. */
  53. protected int currentFontSize;
  54. /**
  55. * The current colour's red, green and blue component
  56. */
  57. protected float currentRed = 0;
  58. protected float currentGreen = 0;
  59. protected float currentBlue = 0;
  60. /**
  61. * The current vertical position in millipoints from bottom
  62. */
  63. protected int currentYPosition = 0;
  64. /**
  65. * The current horizontal position in millipoints from left
  66. */
  67. protected int currentXPosition = 0;
  68. /**
  69. * The horizontal position of the current area container
  70. */
  71. private int currentAreaContainerXPosition = 0;
  72. static {
  73. JAVA_FONT_NAMES = new Hashtable();
  74. JAVA_FONT_NAMES.put("Times", "serif");
  75. JAVA_FONT_NAMES.put("Times-Roman", "serif");
  76. JAVA_FONT_NAMES.put("Courier", "monospaced");
  77. JAVA_FONT_NAMES.put("Helvetica", "sansserif");
  78. // JAVA_FONT_NAMES.put("Serif", "sansserif");
  79. }
  80. public AWTRenderer(Translator aRes) {
  81. res = aRes;
  82. }
  83. public int getPageNumber() {
  84. return pageNumber;
  85. }
  86. public void setPageNumber(int aValue) {
  87. pageNumber = aValue;
  88. }
  89. public void setScaleFactor(double newScaleFactor) {
  90. scaleFactor = newScaleFactor;
  91. }
  92. public double getScaleFactor() {
  93. return scaleFactor;
  94. }
  95. public BufferedImage getLastRenderedPage() {
  96. return pageImage;
  97. }
  98. /**
  99. * add a line to the current stream
  100. *
  101. * @param x1 the start x location in millipoints
  102. * @param y1 the start y location in millipoints
  103. * @param x2 the end x location in millipoints
  104. * @param y2 the end y location in millipoints
  105. * @param th the thickness in millipoints
  106. * @param r the red component
  107. * @param g the green component
  108. * @param b the blue component
  109. */
  110. protected void addLine(int x1, int y1, int x2, int y2, int th,
  111. float r, float g, float b) {
  112. graphics.setColor(new Color (r,g,b));
  113. graphics.drawLine((int)(x1/1000f), pageHeight - (int)(y1/1000f),
  114. (int)(x2/1000f), pageHeight - (int)(y2/1000f));
  115. }
  116. /**
  117. * draw a filled rectangle
  118. *
  119. * @param x the x position of left edge in millipoints
  120. * @param y the y position of top edge in millipoints
  121. * @param w the width in millipoints
  122. * @param h the height in millipoints
  123. * @param r the red component
  124. * @param g the green component
  125. * @param b the blue component
  126. */
  127. protected void addRect(int x, int y, int w, int h,
  128. float r, float g, float b) {
  129. graphics.setColor(new Color (r,g,b));
  130. graphics.fill3DRect((int) (x/1000f), pageHeight - (int) (y/1000f),
  131. (int) (w/1000f), -(int) (h/1000f),false);
  132. }
  133. /**
  134. * draw a filled rectangle
  135. *
  136. * @param x the x position of left edge in millipoints
  137. * @param y the y position of top edge in millipoints
  138. * @param w the width in millipoints
  139. * @param h the height in millipoints
  140. * @param r the red component of edges
  141. * @param g the green component of edges
  142. * @param b the blue component of edges
  143. * @param fr the red component of the fill
  144. * @param fg the green component of the fill
  145. * @param fb the blue component of the fill
  146. */
  147. protected void addRect(int x, int y, int w, int h,
  148. float r, float g, float b,
  149. float fr, float fg, float fb) {
  150. graphics.setColor(new Color (r,g,b));
  151. graphics.fill3DRect((int) (x/1000f), pageHeight - (int) (y/1000f),
  152. (int) (w/1000f), -(int) (h/1000f),true);
  153. }
  154. /**
  155. * Vor dem Druck einzustellen:
  156. *
  157. * Seite/Seiten wählen
  158. * Zoomfaktor
  159. * Seitenformat / Quer- oder Hoch
  160. **/
  161. public void transform(Graphics2D g2d, double zoomPercent, double angle) {
  162. AffineTransform at = g2d.getTransform();
  163. at.rotate(angle);
  164. at.scale(zoomPercent/100.0, zoomPercent/100.0);
  165. g2d.setTransform(at);
  166. }
  167. protected void drawFrame() {
  168. int width = pageWidth;
  169. int height = pageHeight;
  170. graphics.setColor(Color.white);
  171. graphics.fillRect(0, 0, width, height);
  172. graphics.setColor(Color.black);
  173. graphics.drawRect(-1, -1, width+2, height+2);
  174. graphics.drawLine(width+2, 0, width+2, height+2);
  175. graphics.drawLine(width+3, 1, width+3, height+3);
  176. graphics.drawLine(0, height+2, width+2, height+2);
  177. graphics.drawLine(1, height+3, width+3, height+3);
  178. }
  179. /**
  180. * Retrieve the number of pages in this document.
  181. *
  182. * @return the number of pages
  183. */
  184. public int getPageCount()
  185. {
  186. if (tree == null) {
  187. return 0;
  188. }
  189. return tree.getPages().size();
  190. }
  191. public void render(int aPageNumber) {
  192. if (tree != null) {
  193. try {
  194. render(tree, aPageNumber);
  195. } catch (IOException e) {
  196. // This exception can't occur because we are not dealing with
  197. // any files.
  198. }
  199. }
  200. }
  201. public void render(AreaTree areaTree, PrintWriter writer)
  202. throws IOException {
  203. tree = areaTree;
  204. render(areaTree,0);
  205. }
  206. public void render(AreaTree areaTree, int aPageNumber)
  207. throws IOException {
  208. tree = areaTree;
  209. Page page = (Page)areaTree.getPages().elementAt(aPageNumber);
  210. pageWidth = (int)((float)page.getWidth() / 1000f);
  211. pageHeight = (int)((float)page.getHeight() / 1000f);
  212. pageImage = new BufferedImage((int)((pageWidth * (int)scaleFactor)/100),
  213. (int)((pageHeight * (int)scaleFactor)/100),
  214. BufferedImage.TYPE_INT_RGB);
  215. graphics = pageImage.createGraphics();
  216. transform(graphics, scaleFactor, 0);
  217. drawFrame();
  218. renderPage(page);
  219. }
  220. public void renderPage(Page page) {
  221. AreaContainer body, before, after;
  222. body = page.getBody();
  223. before = page.getBefore();
  224. after = page.getAfter();
  225. this.currentFontName = "";
  226. this.currentFontSize = 0;
  227. renderAreaContainer(body);
  228. if (before != null) {
  229. renderAreaContainer(before);
  230. }
  231. if (after != null) {
  232. renderAreaContainer(after);
  233. }
  234. }
  235. public void renderAreaContainer(AreaContainer area) {
  236. int saveY = this.currentYPosition;
  237. int saveX = this.currentAreaContainerXPosition;
  238. if (area.getPosition() ==
  239. org.apache.fop.fo.properties.Position.ABSOLUTE) {
  240. // Y position is computed assuming positive Y axis, adjust
  241. //for negative postscript one
  242. this.currentYPosition = area.getYPosition() -
  243. 2 * area.getPaddingTop() -
  244. 2 * area.borderWidthTop;
  245. this.currentAreaContainerXPosition = area.getXPosition();
  246. } else if (area.getPosition() ==
  247. org.apache.fop.fo.properties.Position.RELATIVE) {
  248. this.currentYPosition -= area.getYPosition();
  249. this.currentAreaContainerXPosition += area.getXPosition();
  250. } else if (area.getPosition() ==
  251. org.apache.fop.fo.properties.Position.STATIC) {
  252. this.currentYPosition -= area.getPaddingTop() + area.borderWidthTop;
  253. this.currentAreaContainerXPosition += area.getPaddingLeft() +
  254. area.borderWidthLeft;
  255. }
  256. doFrame(area);
  257. Enumeration e = area.getChildren().elements();
  258. while (e.hasMoreElements()) {
  259. org.apache.fop.layout.Box b =
  260. (org.apache.fop.layout.Box) e.nextElement();
  261. b.render(this);
  262. }
  263. if (area.getPosition() !=
  264. org.apache.fop.fo.properties.Position.STATIC) {
  265. this.currentYPosition = saveY;
  266. this.currentAreaContainerXPosition = saveX;
  267. } else {
  268. this.currentYPosition -= area.getHeight();
  269. }
  270. }
  271. private void doFrame(org.apache.fop.layout.Area area) {
  272. int w, h;
  273. int rx = this.currentAreaContainerXPosition;
  274. w = area.getContentWidth();
  275. if (area instanceof BlockArea) {
  276. rx += ((BlockArea)area).getStartIndent();
  277. }
  278. h = area.getContentHeight();
  279. int ry = this.currentYPosition;
  280. ColorType bg = area.getBackgroundColor();
  281. rx = rx - area.getPaddingLeft();
  282. ry = ry + area.getPaddingTop();
  283. w = w + area.getPaddingLeft() + area.getPaddingRight();
  284. h = h + area.getPaddingTop() + area.getPaddingBottom();
  285. // I'm not sure I should have to check for bg being null
  286. // but I do
  287. if ((bg != null) && (bg.alpha() == 0)) {
  288. this.addRect(rx, ry, w, -h,
  289. bg.red(), bg.green(), bg.blue(),
  290. bg.red(), bg.green(), bg.blue());
  291. }
  292. rx = rx - area.borderWidthLeft;
  293. ry = ry + area.borderWidthTop;
  294. w = w + area.borderWidthLeft + area.borderWidthRight;
  295. h = h + area.borderWidthTop + area.borderWidthBottom;
  296. if (area.borderWidthTop != 0) {
  297. addLine(rx, ry, rx + w, ry,
  298. area.borderWidthTop,
  299. area.borderColorTop.red(), area.borderColorTop.green(),
  300. area.borderColorTop.blue());
  301. }
  302. if (area.borderWidthLeft != 0) {
  303. addLine(rx, ry, rx, ry - h,
  304. area.borderWidthLeft,
  305. area.borderColorLeft.red(), area.borderColorLeft.green(),
  306. area.borderColorLeft.blue());
  307. }
  308. if (area.borderWidthRight != 0) {
  309. addLine(rx + w, ry, rx + w, ry - h,
  310. area.borderWidthRight,
  311. area.borderColorRight.red(), area.borderColorRight.green(),
  312. area.borderColorRight.blue());
  313. }
  314. if (area.borderWidthBottom != 0) {
  315. addLine(rx, ry - h, rx + w, ry - h,
  316. area.borderWidthBottom,
  317. area.borderColorBottom.red(), area.borderColorBottom.green(),
  318. area.borderColorBottom.blue());
  319. }
  320. }
  321. protected Rectangle2D getBounds(org.apache.fop.layout.Area a) {
  322. return new Rectangle2D.Double(currentAreaContainerXPosition,
  323. currentYPosition,
  324. a.getAllocationWidth(),
  325. a.getHeight());
  326. }
  327. public void renderBlockArea(BlockArea area) {
  328. doFrame(area);
  329. Enumeration e = area.getChildren().elements();
  330. while (e.hasMoreElements()) {
  331. org.apache.fop.layout.Box b =
  332. (org.apache.fop.layout.Box) e.nextElement();
  333. b.render(this);
  334. }
  335. }
  336. public void setupFontInfo(FontInfo fontInfo) {
  337. FontSetup.setup(fontInfo);
  338. Hashtable hash = fontInfo.getFonts();
  339. org.apache.fop.render.pdf.Font f;
  340. String name;
  341. Object key;
  342. int fontStyle;
  343. for (Enumeration e = hash.keys(); e.hasMoreElements();) {
  344. fontStyle = java.awt.Font.PLAIN;
  345. key = e.nextElement();
  346. f = (org.apache.fop.render.pdf.Font)hash.get(key);
  347. name = f.fontName();
  348. if (name.toUpperCase().indexOf("BOLD") > 0) {
  349. fontStyle += java.awt.Font.BOLD;
  350. }
  351. if (name.toUpperCase().indexOf("ITALIC") > 0 ||
  352. name.toUpperCase().indexOf("OBLIQUE") > 0) {
  353. fontStyle += java.awt.Font.ITALIC;
  354. }
  355. int hyphenIndex = name.indexOf("-");
  356. hyphenIndex = (hyphenIndex < 0) ? name.length() : hyphenIndex;
  357. fontNames.put(key, name.substring(0, hyphenIndex));
  358. fontStyles.put(key, new Integer(fontStyle));
  359. }
  360. }
  361. public void renderDisplaySpace(DisplaySpace space) {
  362. int d = space.getSize();
  363. this.currentYPosition -= d;
  364. }
  365. public void renderImageArea(ImageArea area) {
  366. int x = this.currentAreaContainerXPosition +
  367. area.getXOffset();
  368. int y = this.currentYPosition;
  369. int w = area.getContentWidth();
  370. int h = area.getHeight();
  371. FopImage img = area.getImage();
  372. if (img == null) {
  373. MessageHandler.logln("area.getImage() is null");
  374. }
  375. try {
  376. byte[] map = img.getBitmaps();
  377. String path = img.getURL();
  378. ImageIcon icon = new ImageIcon(path);
  379. Image imgage = icon.getImage();
  380. graphics.drawImage(imgage, currentXPosition / 1000,
  381. pageHeight - y / 1000,
  382. img.getWidth() / 1000,
  383. img.getHeight() / 1000,
  384. null);
  385. currentYPosition -= h;
  386. } catch (FopImageException imgex) {
  387. // ?
  388. MessageHandler.logln("Error while loading image : " + imgex.getMessage());
  389. }
  390. }
  391. public void renderInlineArea(InlineArea area) {
  392. char ch;
  393. StringBuffer pdf = new StringBuffer();
  394. String name = area.getFontState().getFontName();
  395. int size = area.getFontState().getFontSize();
  396. float red = area.getRed();
  397. float green = area.getGreen();
  398. float blue = area.getBlue();
  399. if ((!name.equals(this.currentFontName))
  400. || (size != this.currentFontSize)) {
  401. this.currentFontName = name;
  402. this.currentFontSize = size;
  403. }
  404. if ((red != this.currentRed)
  405. || (green != this.currentGreen)
  406. || (blue != this.currentBlue)) {
  407. this.currentRed = red;
  408. this.currentGreen = green;
  409. this.currentBlue = blue;
  410. }
  411. int rx = this.currentXPosition;
  412. int bl = this.currentYPosition;
  413. String s = area.getText();
  414. Color oldColor = graphics.getColor();
  415. java.awt.Font oldFont = graphics.getFont();
  416. String aFontName = fontNames.get(name).toString();
  417. aFontName = getJavaFontName(aFontName);
  418. java.awt.Font f =
  419. new java.awt.Font(aFontName,
  420. ((Integer)fontStyles.get(name)).intValue(),
  421. (int)(size / 1000f));
  422. graphics.setColor(new Color(red, green, blue));
  423. /*
  424. Die KLasse TextLayout nimmt für die Ausgabe eigenen Schriftsatz,
  425. der i.R. breiter ist. Deshalb wird bis diese Tatsache sich geklärt/
  426. geregelt hat weniger schöne Ausgabe über Graphics benutzt.
  427. */
  428. // Fonts in bold still have trouble displaying!
  429. FontRenderContext newContext = new FontRenderContext(null, true, true);
  430. TextLayout layout = new TextLayout(s, f, newContext);
  431. graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
  432. RenderingHints.VALUE_RENDER_QUALITY);
  433. layout.draw(graphics, rx / 1000f, (int)(pageHeight - bl / 1000f));
  434. graphics.setColor(oldColor);
  435. this.currentXPosition += area.getContentWidth();
  436. }
  437. public void renderInlineSpace(InlineSpace space) {
  438. this.currentXPosition += space.getSize();
  439. }
  440. public void renderLineArea(LineArea area) {
  441. int rx = this.currentAreaContainerXPosition
  442. + area.getStartIndent();
  443. int ry = this.currentYPosition;
  444. int w = area.getContentWidth();
  445. int h = area.getHeight();
  446. this.currentYPosition -= area.getPlacementOffset();
  447. this.currentXPosition = rx;
  448. int bl = this.currentYPosition;
  449. Enumeration e = area.getChildren().elements();
  450. while (e.hasMoreElements()) {
  451. org.apache.fop.layout.Box b =
  452. (org.apache.fop.layout.Box) e.nextElement();
  453. b.render(this);
  454. }
  455. this.currentYPosition = ry-h;
  456. }
  457. /**
  458. * render rule area into PDF
  459. *
  460. * @param area area to render
  461. */
  462. public void renderRuleArea(RuleArea area) {
  463. int rx = this.currentAreaContainerXPosition
  464. + area.getStartIndent();
  465. int ry = this.currentYPosition;
  466. int w = area.getContentWidth();
  467. int h = area.getHeight();
  468. int th = area.getRuleThickness();
  469. float r = area.getRed();
  470. float g = area.getGreen();
  471. float b = area.getBlue();
  472. Color oldColor = graphics.getColor();
  473. graphics.setColor(new Color(r, g, b));
  474. graphics.fillRect((int)(rx / 1000f), (int)(pageHeight - ry / 1000f),
  475. (int)(w / 1000f), (int)(th / 1000f));
  476. graphics.setColor(oldColor);
  477. }
  478. public void renderSVGArea(SVGArea area) {
  479. int x = this.currentAreaContainerXPosition;
  480. int y = this.currentYPosition;
  481. int w = area.getContentWidth();
  482. int h = area.getHeight();
  483. this.currentYPosition -= h;
  484. // Enumeration e = area.getChildren().elements();
  485. // while (e.hasMoreElements()) {
  486. // Object o = e.nextElement();
  487. // if (o instanceof RectGraphic) {
  488. // int rx = ((RectGraphic)o).x;
  489. // int ry = ((RectGraphic)o).y;
  490. // int rw = ((RectGraphic)o).width;
  491. // int rh = ((RectGraphic)o).height;
  492. // addRect(x+rx,y-ry,rw,-rh,0,0,0);
  493. // } else if (o instanceof LineGraphic) {
  494. // int x1 = ((LineGraphic)o).x1;
  495. // int y1 = ((LineGraphic)o).y1;
  496. // int x2 = ((LineGraphic)o).x2;
  497. // int y2 = ((LineGraphic)o).y2;
  498. // addLine(x+x1,y-y1,x+x2,y-y2,0,0,0,0);
  499. // } else if (o instanceof TextGraphic) {
  500. // int tx = ((TextGraphic)o).x;
  501. // int ty = ((TextGraphic)o).y;
  502. // String s = ((TextGraphic)o).s;
  503. // currentStream.add("1 0 0 1 "
  504. // + ((x+tx)/1000f) + " "
  505. // + ((y-ty)/1000f) + " Tm "
  506. // + "(" + s + ") Tj\n");
  507. // }
  508. // }
  509. }
  510. protected String getJavaFontName(String aName) {
  511. if (aName == null)
  512. return null;
  513. Object o = JAVA_FONT_NAMES.get(aName);
  514. return (o == null) ? aName : o.toString();
  515. }
  516. public void setProducer(String producer) {
  517. // defined in Renderer Interface
  518. }
  519. public int print(Graphics g, PageFormat pageFormat, int pageIndex)
  520. throws PrinterException {
  521. if (pageIndex >= tree.getPages().size())
  522. return NO_SUCH_PAGE;
  523. Graphics2D oldGraphics = graphics;
  524. int oldPageNumber = pageNumber;
  525. graphics = (Graphics2D)g;
  526. Page aPage = (Page)tree.getPages().elementAt(pageIndex);
  527. renderPage(aPage);
  528. graphics = oldGraphics;
  529. return PAGE_EXISTS;
  530. }
  531. public int getNumberOfPages() {
  532. return tree.getPages().size();
  533. }
  534. public PageFormat getPageFormat(int pageIndex)
  535. throws IndexOutOfBoundsException {
  536. if (pageIndex >= tree.getPages().size())
  537. return null;
  538. Page page = (Page)tree.getPages().elementAt(pageIndex);
  539. PageFormat pageFormat = new PageFormat();
  540. Paper paper = new Paper();
  541. paper.setImageableArea(0, 0,
  542. page.getWidth() / 1000d, page.getHeight() / 1000d);
  543. paper.setSize(page.getWidth() / 1000d, page.getHeight() / 1000d);
  544. pageFormat.setPaper(paper);
  545. return pageFormat;
  546. }
  547. public Printable getPrintable(int pageIndex)
  548. throws IndexOutOfBoundsException {
  549. return this;
  550. }
  551. public void setProgressListener(ProgressListener l) {
  552. progressListener = l;
  553. }
  554. public static Color colorType2Color(ColorType ct) {
  555. if (ct == null) {
  556. return null;
  557. }
  558. return new Color(ct.red(), ct.green(), ct.blue());
  559. }
  560. }