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.

PSRenderer.java 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  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$ */
  17. package org.apache.fop.render.ps;
  18. // Java
  19. import java.awt.geom.Rectangle2D;
  20. import java.io.IOException;
  21. import java.io.OutputStream;
  22. import java.util.List;
  23. // FOP
  24. import org.apache.avalon.framework.configuration.Configuration;
  25. import org.apache.avalon.framework.configuration.ConfigurationException;
  26. import org.apache.fop.area.Area;
  27. import org.apache.fop.area.RegionViewport;
  28. import org.apache.fop.apps.FOPException;
  29. import org.apache.fop.area.Block;
  30. import org.apache.fop.area.BlockViewport;
  31. import org.apache.fop.area.CTM;
  32. import org.apache.fop.area.PageViewport;
  33. import org.apache.fop.area.Trait;
  34. import org.apache.fop.area.inline.ForeignObject;
  35. import org.apache.fop.area.inline.TextArea;
  36. import org.apache.fop.datatypes.ColorType;
  37. import org.apache.fop.apps.FOUserAgent;
  38. import org.apache.fop.fonts.FontSetup;
  39. import org.apache.fop.fonts.Typeface;
  40. import org.apache.fop.render.PrintRenderer;
  41. import org.apache.fop.render.RendererContext;
  42. import org.apache.fop.image.FopImage;
  43. import org.apache.fop.image.ImageFactory;
  44. import org.apache.fop.traits.BorderProps;
  45. import org.w3c.dom.Document;
  46. /**
  47. * Renderer that renders to PostScript.
  48. * <br>
  49. * This class currently generates PostScript Level 2 code. The only exception
  50. * is the FlateEncode filter which is a Level 3 feature. The filters in use
  51. * are hardcoded at the moment.
  52. * <br>
  53. * This class follows the Document Structuring Conventions (DSC) version 3.0.
  54. * If anyone modifies this renderer please make
  55. * sure to also follow the DSC to make it simpler to programmatically modify
  56. * the generated Postscript files (ex. extract pages etc.).
  57. * <br>
  58. * The PS renderer operates in millipoints as the layout engine. Since PostScript
  59. * initially uses points, scaling is applied as needed.
  60. *
  61. * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
  62. * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
  63. * @version $Id: PSRenderer.java,v 1.31 2003/03/11 08:42:24 jeremias Exp $
  64. */
  65. public class PSRenderer extends PrintRenderer {
  66. /** The MIME type for PostScript */
  67. public static final String MIME_TYPE = "application/postscript";
  68. /** The application producing the PostScript */
  69. private int currentPageNumber = 0;
  70. private boolean enableComments = true;
  71. private boolean autoRotateLandscape = false;
  72. /** The PostScript generator used to output the PostScript */
  73. protected PSGenerator gen;
  74. private boolean ioTrouble = false;
  75. private String currentFontName;
  76. private int currentFontSize;
  77. private float currRed;
  78. private float currGreen;
  79. private float currBlue;
  80. /**
  81. * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
  82. */
  83. public void configure(Configuration cfg) throws ConfigurationException {
  84. super.configure(cfg);
  85. this.autoRotateLandscape = cfg.getChild("auto-rotate-landscape").getValueAsBoolean(false);
  86. //Font configuration
  87. List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg);
  88. if (this.fontList == null) {
  89. this.fontList = cfgFonts;
  90. } else {
  91. this.fontList.addAll(cfgFonts);
  92. }
  93. }
  94. /**
  95. * @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
  96. */
  97. public void setUserAgent(FOUserAgent agent) {
  98. super.setUserAgent(agent);
  99. PSXMLHandler xmlHandler = new PSXMLHandler();
  100. userAgent.getXMLHandlerRegistry().addXMLHandler(xmlHandler);
  101. }
  102. /**
  103. * Write out a command
  104. * @param cmd PostScript command
  105. */
  106. protected void writeln(String cmd) {
  107. try {
  108. gen.writeln(cmd);
  109. } catch (IOException ioe) {
  110. handleIOTrouble(ioe);
  111. }
  112. }
  113. /**
  114. * Central exception handler for I/O exceptions.
  115. * @param ioe IOException to handle
  116. */
  117. protected void handleIOTrouble(IOException ioe) {
  118. if (!ioTrouble) {
  119. getLogger().error("Error while writing to target file", ioe);
  120. ioTrouble = true;
  121. }
  122. }
  123. /**
  124. * Write out a comment
  125. * @param comment Comment to write
  126. */
  127. protected void comment(String comment) {
  128. if (this.enableComments) {
  129. writeln(comment);
  130. }
  131. }
  132. /**
  133. * Make sure the cursor is in the right place.
  134. */
  135. protected void movetoCurrPosition() {
  136. moveTo(this.currentIPPosition, this.currentBPPosition);
  137. }
  138. /**
  139. * Moves the cursor.
  140. * @param x X coordinate
  141. * @param y Y coordinate
  142. */
  143. protected void moveTo(int x, int y) {
  144. writeln(x + " " + y + " M");
  145. }
  146. /** Saves the graphics state of the rendering engine. */
  147. public void saveGraphicsState() {
  148. try {
  149. //delegate
  150. gen.saveGraphicsState();
  151. } catch (IOException ioe) {
  152. handleIOTrouble(ioe);
  153. }
  154. }
  155. /** Restores the last graphics state of the rendering engine. */
  156. public void restoreGraphicsState() {
  157. try {
  158. //delegate
  159. gen.restoreGraphicsState();
  160. } catch (IOException ioe) {
  161. handleIOTrouble(ioe);
  162. }
  163. }
  164. /** Indicates the beginning of a text object. */
  165. protected void beginTextObject() {
  166. writeln("BT");
  167. }
  168. /** Indicates the end of a text object. */
  169. protected void endTextObject() {
  170. writeln("ET");
  171. }
  172. /**
  173. * Concats the transformation matrix.
  174. * @param a A part
  175. * @param b B part
  176. * @param c C part
  177. * @param d D part
  178. * @param e E part
  179. * @param f F part
  180. */
  181. protected void concatMatrix(double a, double b,
  182. double c, double d,
  183. double e, double f) {
  184. try {
  185. gen.concatMatrix(a, b, c, d, e, f);
  186. } catch (IOException ioe) {
  187. handleIOTrouble(ioe);
  188. }
  189. }
  190. /**
  191. * Concats the transformations matrix.
  192. * @param matrix Matrix to use
  193. */
  194. protected void concatMatrix(double[] matrix) {
  195. try {
  196. gen.concatMatrix(matrix);
  197. } catch (IOException ioe) {
  198. handleIOTrouble(ioe);
  199. }
  200. }
  201. /**
  202. * Draws a filled rectangle.
  203. * @param x x-coordinate
  204. * @param y y-coordinate
  205. * @param w width
  206. * @param h height
  207. * @param col color to fill with
  208. */
  209. protected void fillRect(float x, float y, float w, float h,
  210. ColorType col) {
  211. useColor(col);
  212. writeln(gen.formatDouble(x)
  213. + " " + gen.formatDouble(y)
  214. + " " + gen.formatDouble(w)
  215. + " " + gen.formatDouble(h)
  216. + " rectfill");
  217. }
  218. /**
  219. * Draws a stroked rectangle with the current stroke settings.
  220. * @param x x-coordinate
  221. * @param y y-coordinate
  222. * @param w width
  223. * @param h height
  224. */
  225. protected void drawRect(float x, float y, float w, float h) {
  226. writeln(gen.formatDouble(x)
  227. + " " + gen.formatDouble(y)
  228. + " " + gen.formatDouble(w)
  229. + " " + gen.formatDouble(h)
  230. + " rectstroke");
  231. }
  232. /**
  233. * Clip an area.
  234. * Write a clipping operation given coordinates in the current
  235. * transform.
  236. * @param x the x coordinate
  237. * @param y the y coordinate
  238. * @param width the width of the area
  239. * @param height the height of the area
  240. */
  241. protected void clip(float x, float y, float width, float height) {
  242. writeln(x + " " + y + " " + width + " " + height + " rectclip");
  243. }
  244. /**
  245. * Changes the currently used font.
  246. * @param name name of the font
  247. * @param size font size
  248. */
  249. public void useFont(String name, int size) {
  250. if ((currentFontName != name) || (currentFontSize != size)) {
  251. writeln(name + " " + size + " F");
  252. currentFontName = name;
  253. currentFontSize = size;
  254. }
  255. }
  256. private void useColor(ColorType col) {
  257. useColor(col.getRed(), col.getGreen(), col.getBlue());
  258. }
  259. private void useColor(float red, float green, float blue) {
  260. if ((red != currRed) || (green != currGreen) || (blue != currBlue)) {
  261. writeln(gen.formatDouble(red)
  262. + " " + gen.formatDouble(green)
  263. + " " + gen.formatDouble(blue)
  264. + " setrgbcolor");
  265. currRed = red;
  266. currGreen = green;
  267. currBlue = blue;
  268. }
  269. }
  270. /**
  271. * @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
  272. */
  273. public void startRenderer(OutputStream outputStream)
  274. throws IOException {
  275. getLogger().debug("rendering areas to PostScript");
  276. //Setup for PostScript generation
  277. this.gen = new PSGenerator(outputStream);
  278. this.currentPageNumber = 0;
  279. //PostScript Header
  280. writeln(DSCConstants.PS_ADOBE_30);
  281. gen.writeDSCComment(DSCConstants.CREATOR, new String[] { userAgent.getProducer() });
  282. gen.writeDSCComment(DSCConstants.CREATION_DATE, new Object[] {new java.util.Date()});
  283. gen.writeDSCComment(DSCConstants.LANGUAGE_LEVEL, new Integer(gen.getPSLevel()));
  284. gen.writeDSCComment(DSCConstants.PAGES, new Object[] {PSGenerator.ATEND});
  285. gen.writeDSCComment(DSCConstants.END_COMMENTS);
  286. //Defaults
  287. gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS);
  288. gen.writeDSCComment(DSCConstants.END_DEFAULTS);
  289. //Prolog
  290. gen.writeDSCComment(DSCConstants.BEGIN_PROLOG);
  291. gen.writeDSCComment(DSCConstants.END_PROLOG);
  292. //Setup
  293. gen.writeDSCComment(DSCConstants.BEGIN_SETUP);
  294. PSProcSets.writeFOPStdProcSet(gen);
  295. PSProcSets.writeFOPEPSProcSet(gen);
  296. PSProcSets.writeFontDict(gen, fontInfo);
  297. gen.writeln("FOPFonts begin");
  298. gen.writeDSCComment(DSCConstants.END_SETUP);
  299. }
  300. /**
  301. * @see org.apache.fop.render.Renderer#stopRenderer()
  302. */
  303. public void stopRenderer() throws IOException {
  304. gen.writeDSCComment(DSCConstants.TRAILER);
  305. gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.currentPageNumber));
  306. gen.writeDSCComment(DSCConstants.EOF);
  307. gen.flush();
  308. }
  309. /**
  310. * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
  311. */
  312. public void renderPage(PageViewport page)
  313. throws IOException, FOPException {
  314. getLogger().debug("renderPage(): " + page);
  315. this.currentPageNumber++;
  316. gen.writeDSCComment(DSCConstants.PAGE, new Object[]
  317. {page.getPageNumberString(),
  318. new Integer(this.currentPageNumber)});
  319. final Integer zero = new Integer(0);
  320. final long pagewidth = Math.round(page.getViewArea().getWidth());
  321. final long pageheight = Math.round(page.getViewArea().getHeight());
  322. final double pspagewidth = pagewidth / 1000f;
  323. final double pspageheight = pageheight / 1000f;
  324. boolean rotate = false;
  325. if (this.autoRotateLandscape && (pageheight < pagewidth)) {
  326. rotate = true;
  327. gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[]
  328. {zero,
  329. zero,
  330. new Long(Math.round(pspageheight)),
  331. new Long(Math.round(pspagewidth))});
  332. gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[]
  333. {zero,
  334. zero,
  335. new Double(pspageheight),
  336. new Double(pspagewidth)});
  337. gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Landscape");
  338. } else {
  339. gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[]
  340. {zero,
  341. zero,
  342. new Long(Math.round(pspagewidth)),
  343. new Long(Math.round(pspageheight))});
  344. gen.writeDSCComment(DSCConstants.PAGE_HIRES_BBOX, new Object[]
  345. {zero,
  346. zero,
  347. new Double(pspagewidth),
  348. new Double(pspageheight)});
  349. if (this.autoRotateLandscape) {
  350. gen.writeDSCComment(DSCConstants.PAGE_ORIENTATION, "Portrait");
  351. }
  352. }
  353. gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP);
  354. if (rotate) {
  355. gen.writeln(Math.round(pspageheight) + " 0 translate");
  356. gen.writeln("90 rotate");
  357. }
  358. gen.writeln("0.001 0.001 scale");
  359. concatMatrix(1, 0, 0, -1, 0, pageheight);
  360. gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
  361. //Process page
  362. super.renderPage(page);
  363. writeln("showpage");
  364. gen.writeDSCComment(DSCConstants.PAGE_TRAILER);
  365. gen.writeDSCComment(DSCConstants.END_PAGE);
  366. }
  367. /**
  368. * Paints text.
  369. * @param rx X coordinate
  370. * @param bl Y coordinate
  371. * @param text Text to paint
  372. * @param font Font to use
  373. */
  374. protected void paintText(int rx, int bl, String text, Typeface font) {
  375. saveGraphicsState();
  376. writeln("1 0 0 -1 " + rx + " " + bl + " Tm");
  377. int initialSize = text.length();
  378. initialSize += initialSize / 2;
  379. StringBuffer sb = new StringBuffer(initialSize);
  380. sb.append("(");
  381. for (int i = 0; i < text.length(); i++) {
  382. final char c = text.charAt(i);
  383. final char mapped = font.mapChar(c);
  384. PSGenerator.escapeChar(mapped, sb);
  385. }
  386. sb.append(") t");
  387. writeln(sb.toString());
  388. restoreGraphicsState();
  389. }
  390. /**
  391. * @see org.apache.fop.render.Renderer#renderText(TextArea)
  392. */
  393. public void renderText(TextArea area) {
  394. String fontname = (String)area.getTrait(Trait.FONT_NAME);
  395. int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
  396. // This assumes that *all* CIDFonts use a /ToUnicode mapping
  397. Typeface f = (Typeface) fontInfo.getFonts().get(fontname);
  398. //Determine position
  399. int rx = currentIPPosition;
  400. int bl = currentBPPosition + area.getOffset();
  401. useFont(fontname, fontsize);
  402. ColorType ct = (ColorType)area.getTrait(Trait.COLOR);
  403. if (ct != null) {
  404. useColor(ct);
  405. }
  406. paintText(rx, bl, area.getTextArea(), f);
  407. /*
  408. String psString = null;
  409. if (area.getFontState().getLetterSpacing() > 0) {
  410. //float f = area.getFontState().getLetterSpacing()
  411. // * 1000 / this.currentFontSize;
  412. float f = area.getFontState().getLetterSpacing();
  413. psString = (new StringBuffer().append(f).append(" 0.0 (")
  414. .append(sb.toString()).append(") A")).toString();
  415. } else {
  416. psString = (new StringBuffer("(").append(sb.toString())
  417. .append(") t")).toString();
  418. }
  419. // System.out.println("["+s+"] --> ["+sb.toString()+"]");
  420. // comment("% --- InlineArea font-weight="+fontWeight+": " + sb.toString());
  421. useFont(fs.getFontName(), fs.getFontSize());
  422. useColor(area.getRed(), area.getGreen(), area.getBlue());
  423. if (area.getUnderlined() || area.getLineThrough()
  424. || area.getOverlined())
  425. write("ULS");
  426. write(psString);
  427. if (area.getUnderlined())
  428. write("ULE");
  429. if (area.getLineThrough())
  430. write("SOE");
  431. if (area.getOverlined())
  432. write("OLE");
  433. this.currentXPosition += area.getContentWidth();
  434. */
  435. super.renderText(area); //Updates IPD
  436. }
  437. /**
  438. * @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport, List)
  439. */
  440. protected void renderBlockViewport(BlockViewport bv, List children) {
  441. // clip and position viewport if necessary
  442. // save positions
  443. int saveIP = currentIPPosition;
  444. int saveBP = currentBPPosition;
  445. String saveFontName = currentFontName;
  446. CTM ctm = bv.getCTM();
  447. if (bv.getPositioning() == Block.ABSOLUTE) {
  448. currentIPPosition = 0;
  449. currentBPPosition = 0;
  450. //closeText();
  451. endTextObject();
  452. if (bv.getClip()) {
  453. saveGraphicsState();
  454. int x = bv.getXOffset() + containingIPPosition;
  455. int y = bv.getYOffset() + containingBPPosition;
  456. int width = bv.getIPD();
  457. int height = bv.getBPD();
  458. clip(x, y, width, height);
  459. }
  460. CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
  461. ctm = tempctm.multiply(ctm);
  462. startVParea(ctm);
  463. handleBlockTraits(bv);
  464. renderBlocks(bv, children);
  465. endVParea();
  466. if (bv.getClip()) {
  467. restoreGraphicsState();
  468. }
  469. beginTextObject();
  470. // clip if necessary
  471. currentIPPosition = saveIP;
  472. currentBPPosition = saveBP;
  473. } else {
  474. if (ctm != null) {
  475. currentIPPosition = 0;
  476. currentBPPosition = 0;
  477. //closeText();
  478. endTextObject();
  479. double[] vals = ctm.toArray();
  480. //boolean aclock = vals[2] == 1.0;
  481. if (vals[2] == 1.0) {
  482. ctm = ctm.translate(-saveBP - bv.getBPD(), -saveIP);
  483. } else if (vals[0] == -1.0) {
  484. ctm = ctm.translate(-saveIP - bv.getIPD(), -saveBP - bv.getBPD());
  485. } else {
  486. ctm = ctm.translate(saveBP, saveIP - bv.getIPD());
  487. }
  488. }
  489. // clip if necessary
  490. if (bv.getClip()) {
  491. if (ctm == null) {
  492. //closeText();
  493. endTextObject();
  494. }
  495. saveGraphicsState();
  496. int x = bv.getXOffset();
  497. int y = bv.getYOffset();
  498. int width = bv.getIPD();
  499. int height = bv.getBPD();
  500. clip(x, y, width, height);
  501. }
  502. if (ctm != null) {
  503. startVParea(ctm);
  504. }
  505. handleBlockTraits(bv);
  506. renderBlocks(bv, children);
  507. if (ctm != null) {
  508. endVParea();
  509. }
  510. if (bv.getClip()) {
  511. restoreGraphicsState();
  512. if (ctm == null) {
  513. beginTextObject();
  514. }
  515. }
  516. if (ctm != null) {
  517. beginTextObject();
  518. }
  519. currentIPPosition = saveIP;
  520. currentBPPosition = saveBP;
  521. currentBPPosition += (int)(bv.getAllocBPD());
  522. }
  523. currentFontName = saveFontName;
  524. }
  525. /**
  526. * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM)
  527. */
  528. protected void startVParea(CTM ctm) {
  529. // Set the given CTM in the graphics state
  530. //currentState.push();
  531. //currentState.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
  532. saveGraphicsState();
  533. // multiply with current CTM
  534. //writeln(CTMHelper.toPDFString(ctm) + " cm\n");
  535. final double[] matrix = ctm.toArray();
  536. concatMatrix(matrix);
  537. // Set clip?
  538. beginTextObject();
  539. }
  540. /**
  541. * @see org.apache.fop.render.AbstractRenderer#endVParea()
  542. */
  543. protected void endVParea() {
  544. endTextObject();
  545. restoreGraphicsState();
  546. //currentState.pop();
  547. }
  548. /**
  549. * Handle the traits for a region
  550. * This is used to draw the traits for the given page region.
  551. * (See Sect. 6.4.1.2 of XSL-FO spec.)
  552. * @param region the RegionViewport whose region is to be drawn
  553. */
  554. protected void handleRegionTraits(RegionViewport region) {
  555. currentFontName = "";
  556. float startx = 0;
  557. float starty = 0;
  558. Rectangle2D viewArea = region.getViewArea();
  559. float width = (float)(viewArea.getWidth());
  560. float height = (float)(viewArea.getHeight());
  561. /*
  562. Trait.Background back;
  563. back = (Trait.Background)region.getTrait(Trait.BACKGROUND);
  564. */
  565. drawBackAndBorders(region, startx, starty, width, height);
  566. }
  567. /**
  568. * Handle block traits.
  569. * The block could be any sort of block with any positioning
  570. * so this should render the traits such as border and background
  571. * in its position.
  572. *
  573. * @param block the block to render the traits
  574. */
  575. protected void handleBlockTraits(Block block) {
  576. float startx = currentIPPosition;
  577. float starty = currentBPPosition;
  578. drawBackAndBorders(block, startx, starty,
  579. block.getIPD(), block.getBPD());
  580. }
  581. /**
  582. * Draw the background and borders.
  583. * This draws the background and border traits for an area given
  584. * the position.
  585. *
  586. * @param block the area to get the traits from
  587. * @param startx the start x position
  588. * @param starty the start y position
  589. * @param width the width of the area
  590. * @param height the height of the area
  591. */
  592. protected void drawBackAndBorders(Area block,
  593. float startx, float starty,
  594. float width, float height) {
  595. // draw background then border
  596. boolean started = false;
  597. Trait.Background back;
  598. back = (Trait.Background)block.getTrait(Trait.BACKGROUND);
  599. if (back != null) {
  600. started = true;
  601. // closeText();
  602. endTextObject();
  603. //saveGraphicsState();
  604. if (back.getColor() != null) {
  605. fillRect(startx, starty, width, height, back.getColor());
  606. }
  607. if (back.getURL() != null) {
  608. ImageFactory fact = ImageFactory.getInstance();
  609. FopImage fopimage = fact.getImage(back.getURL(), userAgent);
  610. if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
  611. if (back.getRepeat() == EN_REPEAT) {
  612. // create a pattern for the image
  613. } else {
  614. // place once
  615. Rectangle2D pos;
  616. pos = new Rectangle2D.Float((startx + back.getHoriz()) * 1000,
  617. (starty + back.getVertical()) * 1000,
  618. fopimage.getWidth() * 1000,
  619. fopimage.getHeight() * 1000);
  620. // putImage(back.url, pos);
  621. }
  622. }
  623. }
  624. }
  625. BorderProps bps = (BorderProps)block.getTrait(Trait.BORDER_BEFORE);
  626. if (bps != null) {
  627. float endx = startx + width;
  628. if (!started) {
  629. started = true;
  630. // closeText();
  631. endTextObject();
  632. //saveGraphicsState();
  633. }
  634. float bwidth = bps.width;
  635. useColor(bps.color);
  636. writeln(bwidth + " setlinewidth");
  637. drawLine(startx, starty + bwidth / 2, endx, starty + bwidth / 2);
  638. }
  639. bps = (BorderProps)block.getTrait(Trait.BORDER_START);
  640. if (bps != null) {
  641. float endy = starty + height;
  642. if (!started) {
  643. started = true;
  644. // closeText();
  645. endTextObject();
  646. //saveGraphicsState();
  647. }
  648. float bwidth = bps.width;
  649. useColor(bps.color);
  650. writeln(bwidth + " setlinewidth");
  651. drawLine(startx + bwidth / 2, starty, startx + bwidth / 2, endy);
  652. }
  653. bps = (BorderProps)block.getTrait(Trait.BORDER_AFTER);
  654. if (bps != null) {
  655. float sy = starty + height;
  656. float endx = startx + width;
  657. if (!started) {
  658. started = true;
  659. // closeText();
  660. endTextObject();
  661. //saveGraphicsState();
  662. }
  663. float bwidth = bps.width;
  664. useColor(bps.color);
  665. writeln(bwidth + " setlinewidth");
  666. drawLine(startx, sy - bwidth / 2, endx, sy - bwidth / 2);
  667. }
  668. bps = (BorderProps)block.getTrait(Trait.BORDER_END);
  669. if (bps != null) {
  670. float sx = startx + width;
  671. float endy = starty + height;
  672. if (!started) {
  673. started = true;
  674. // closeText();
  675. endTextObject();
  676. //saveGraphicsState();
  677. }
  678. float bwidth = bps.width;
  679. useColor(bps.color);
  680. writeln(bwidth + " setlinewidth");
  681. drawLine(sx - bwidth / 2, starty, sx - bwidth / 2, endy);
  682. }
  683. if (started) {
  684. //restoreGraphicsState();
  685. beginTextObject();
  686. // font last set out of scope in text section
  687. currentFontName = "";
  688. }
  689. }
  690. /**
  691. * Draw a line.
  692. *
  693. * @param startx the start x position
  694. * @param starty the start y position
  695. * @param endx the x end position
  696. * @param endy the y end position
  697. */
  698. private void drawLine(float startx, float starty, float endx, float endy) {
  699. writeln(startx + " " + starty + " M ");
  700. writeln(endx + " " + endy + " lineto");
  701. }
  702. /**
  703. * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D)
  704. */
  705. public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
  706. Document doc = fo.getDocument();
  707. String ns = fo.getNameSpace();
  708. renderDocument(doc, ns, pos);
  709. }
  710. /**
  711. * Renders an XML document (SVG for example).
  712. * @param doc DOM Document containing the XML document to be rendered
  713. * @param ns Namespace for the XML document
  714. * @param pos Position for the generated graphic/image
  715. */
  716. public void renderDocument(Document doc, String ns, Rectangle2D pos) {
  717. RendererContext context;
  718. context = new RendererContext(this, MIME_TYPE);
  719. context.setUserAgent(userAgent);
  720. context.setProperty(PSXMLHandler.PS_GENERATOR, this.gen);
  721. context.setProperty(PSXMLHandler.PS_FONT_INFO, fontInfo);
  722. context.setProperty(PSXMLHandler.PS_WIDTH,
  723. new Integer((int) pos.getWidth()));
  724. context.setProperty(PSXMLHandler.PS_HEIGHT,
  725. new Integer((int) pos.getHeight()));
  726. context.setProperty(PSXMLHandler.PS_XPOS,
  727. new Integer(currentIPPosition + (int) pos.getX()));
  728. context.setProperty(PSXMLHandler.PS_YPOS,
  729. new Integer(currentBPPosition + (int) pos.getY()));
  730. //context.setProperty("strokeSVGText", options.get("strokeSVGText"));
  731. renderXML(context, doc, ns);
  732. }
  733. /** @see org.apache.fop.render.AbstractRenderer */
  734. public String getMimeType() {
  735. return MIME_TYPE;
  736. }
  737. }