您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

TXTRenderer.java 58KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. // package com.eastpoint.chrysalis;
  8. package org.apache.fop.render.txt;
  9. // FOP
  10. import org.apache.fop.render.PrintRenderer;
  11. import org.apache.fop.render.pcl.*;
  12. import org.apache.fop.apps.FOPException;
  13. import org.apache.fop.fo.properties.*;
  14. import org.apache.fop.layout.*;
  15. import org.apache.fop.layout.inline.*;
  16. import org.apache.fop.datatypes.*;
  17. import org.apache.fop.pdf.PDFPathPaint;
  18. import org.apache.fop.pdf.PDFColor;
  19. import org.apache.fop.image.*;
  20. import org.apache.fop.svg.SVGArea;
  21. import org.w3c.dom.svg.SVGSVGElement;
  22. import org.w3c.dom.svg.SVGDocument;
  23. // Java
  24. import java.io.IOException;
  25. import java.io.OutputStream;
  26. import java.util.Enumeration;
  27. import java.util.Vector;
  28. import java.util.Hashtable;
  29. /**
  30. * Renderer that renders areas to plain text
  31. *
  32. * Modified by Mark Lillywhite mark-fop@inomial.com to use the new
  33. * Renderer interface.
  34. */
  35. public class TXTRenderer extends PrintRenderer {
  36. /**
  37. * the current stream to add Text commands to
  38. */
  39. PCLStream currentStream;
  40. private int pageHeight = 7920;
  41. // These variables control the virtual paggination functionality.
  42. public int curdiv = 0;
  43. private int divisions = -1;
  44. private int paperheight = -1; // Paper height in decipoints?
  45. public int orientation =
  46. -1; // -1=default/unknown, 0=portrait, 1=landscape.
  47. public int topmargin = -1; // Top margin in decipoints?
  48. public int leftmargin = -1; // Left margin in decipoints?
  49. private int fullmargin = 0;
  50. final boolean debug = false;
  51. // Variables for rendering text.
  52. StringBuffer charData[];
  53. StringBuffer decoData[];
  54. public float textCPI = 16.67f;
  55. public float textLPI = 8;
  56. int maxX = (int)(8.5f * textCPI + 1);
  57. int maxY = (int)(11f * textLPI + 1);
  58. float xFactor;
  59. float yFactor;
  60. public String lineEnding =
  61. "\r\n"; // Every line except the last line on a page (which will end with pageEnding) will be terminated with this string.
  62. public String pageEnding =
  63. "\f"; // Every page except the last one will end with this string.
  64. public boolean suppressGraphics =
  65. false; // If true then graphics/decorations will not be rendered - text only.
  66. boolean firstPage = false;
  67. /**
  68. * options
  69. */
  70. protected Hashtable options;
  71. public TXTRenderer() {}
  72. /**
  73. * set up renderer options
  74. */
  75. public void setOptions(Hashtable options) {
  76. this.options = options;
  77. }
  78. /**
  79. * set the TXT document's producer
  80. *
  81. * @param producer string indicating application producing PDF
  82. */
  83. public void setProducer(String producer) {}
  84. void addStr(int row, int col, String str, boolean ischar) {
  85. if (debug)
  86. System.out.println("TXTRenderer.addStr(" + row + ", " + col
  87. + ", \"" + str + "\", " + ischar + ")");
  88. if (suppressGraphics &&!ischar)
  89. return;
  90. StringBuffer sb;
  91. if (row < 0)
  92. row = 0;
  93. if (ischar)
  94. sb = charData[row];
  95. else
  96. sb = decoData[row];
  97. if (sb == null)
  98. sb = new StringBuffer();
  99. if ((col + str.length()) > maxX)
  100. col = maxX - str.length();
  101. if (col < 0) {
  102. col = 0;
  103. if (str.length() > maxX)
  104. str = str.substring(0, maxX);
  105. }
  106. // Pad to col
  107. for (int countr = sb.length(); countr < col; countr++)
  108. sb.append(' ');
  109. if (debug)
  110. System.out.println("TXTRenderer.addStr() sb.length()="
  111. + sb.length());
  112. for (int countr = col; countr < (col + str.length()); countr++) {
  113. if (countr >= sb.length())
  114. sb.append(str.charAt(countr - col));
  115. else {
  116. if (debug)
  117. System.out.println("TXTRenderer.addStr() sb.length()="
  118. + sb.length() + " countr=" + countr);
  119. sb.setCharAt(countr, str.charAt(countr - col));
  120. }
  121. }
  122. if (ischar)
  123. charData[row] = sb;
  124. else
  125. decoData[row] = sb;
  126. }
  127. /**
  128. * add a line to the current stream
  129. *
  130. * @param x1 the start x location in millipoints
  131. * @param y1 the start y location in millipoints
  132. * @param x2 the end x location in millipoints
  133. * @param y2 the end y location in millipoints
  134. * @param th the thickness in millipoints
  135. * @param stroke the line color
  136. */
  137. protected void addLine(int x1, int y1, int x2, int y2, int th,
  138. PDFPathPaint stroke) {
  139. if (x1 == x2) {
  140. addRect(x1, y1, th, y2 - y1 + 1, stroke, stroke);
  141. } else if (y1 == y2) {
  142. addRect(x1, y1, x2 - x1 + 1, th, stroke, stroke);
  143. }
  144. }
  145. /**
  146. * add a line to the current stream
  147. *
  148. * @param x1 the start x location in millipoints
  149. * @param y1 the start y location in millipoints
  150. * @param x2 the end x location in millipoints
  151. * @param y2 the end y location in millipoints
  152. * @param th the thickness in millipoints
  153. * @param rs the rule style
  154. * @param stroke the line color
  155. */
  156. protected void addLine(int x1, int y1, int x2, int y2, int th, int rs,
  157. PDFPathPaint stroke) {
  158. PDFColor lstroke = null;
  159. if (rs == org.apache.fop.fo.properties.RuleStyle.DOTTED)
  160. lstroke = new PDFColor(0.7f, 0.7f, 0.7f);
  161. else
  162. lstroke = (PDFColor)stroke;
  163. if (x1 == x2) {
  164. addRect(x1, y1, th, y2 - y1 + 1, lstroke, lstroke);
  165. } else if (y1 == y2) {
  166. addRect(x1, y1, x2 - x1 + 1, th, lstroke, lstroke);
  167. }
  168. }
  169. protected void addLine(float x1, float y1, float x2, float y2,
  170. PDFColor sc, float sw) {
  171. /*
  172. * SVG - Not yet implemented
  173. * if ( debug )
  174. * System.out.println("TXTRenderer.addLine(" + x1 + ", " + y1 + ", " + x2 + ", " + y2 + ", " + sc + ", " + sw + ")");
  175. * if ( x1 == x2 )
  176. * {
  177. * addRect(x1 - sw/2, y1, sw, y2 - y1 + 1, 0, 0, sc, null, 0);
  178. * }
  179. * else if ( y1 == y2 || (Math.abs(y1 - y2) <= 0.24) ) // 72/300=0.24
  180. * {
  181. * addRect(x1, y1 - sw/2, x2 - x1 + 1, sw, 0, 0, sc, null, 0);
  182. * }
  183. * else if ( sc != null )
  184. * {
  185. * // Convert dimensions to characters.
  186. * //float cfact = 300f / 72f; // 300 dpi, 1pt=1/72in
  187. * int ix1 = (int)(x1 * xFactor);
  188. * int iy1 = (int)(y1 * yFactor);
  189. * int ix2 = (int)(x2 * xFactor);
  190. * int iy2 = (int)(y2 * yFactor);
  191. * int isw = (int)(sw * xFactor);
  192. * int origix;
  193. * // Normalize
  194. * if ( iy1 > iy2 )
  195. * {
  196. * int tmp = ix1;
  197. * ix1 = ix2;
  198. * ix2 = tmp;
  199. * tmp = iy1;
  200. * iy1 = iy2;
  201. * iy2 = tmp;
  202. * }
  203. * if ( ix1 > ix2 )
  204. * {
  205. * origix = ix2;
  206. * ix1 -=ix2;
  207. * ix2 = 0;
  208. * }
  209. * else
  210. * {
  211. * origix = ix1;
  212. * ix2 -= ix1;
  213. * ix1 = 0;
  214. * }
  215. * // Convert line width to a pixel run length.
  216. * //System.out.println("TXTRenderer.addLine(" + ix1 + ", " + iy1 + ", " + ix2 + ", " + iy2 + ", " + isw + ")");
  217. * int runlen = (int)Math.sqrt(Math.pow(isw, 2) * (1 + Math.pow((ix1 - ix2) / (iy1 - iy2), 2)));
  218. * if ( runlen < 1 )
  219. * runlen = 1;
  220. * StringBuffer rlbuff = new StringBuffer();
  221. * for ( int countr = 0 ; countr < runlen ; countr++ )
  222. * rlbuff.append('*');
  223. * String rlstr = rlbuff.toString();
  224. * //System.out.println("TXTRenderer.addLine: runlen = " + runlen);
  225. * // Draw the line.
  226. * int d, dx, dy;
  227. * int Aincr, Bincr;
  228. * int xincr = 1;
  229. * int x, y;
  230. * dx = Math.abs(ix2 - ix1);
  231. * dy = iy2 - iy1;
  232. * if ( dx > dy )
  233. * {
  234. * xincr = dx / dy;
  235. * // Move to starting position.
  236. * //currentStream.add("\033*p" + origix + "x" + iy1 + "Y");
  237. * x = ix1 - runlen / 2;
  238. * iy2 += (isw / 2);
  239. * // Start raster graphics
  240. * //currentStream.add("\033*t300R\033*r" + dx + "s1A\033*b1M");
  241. * }
  242. * else
  243. * {
  244. * // Move to starting position.
  245. * //currentStream.add("\033*p" + (origix - runlen / 2) + "x" + iy1 + "Y");
  246. * x = ix1;
  247. * // Start raster graphics
  248. * //currentStream.add("\033*t300R\033*r1A\033*b1M");
  249. * }
  250. * if ( ix1 > ix2 )
  251. * xincr *= -1;
  252. * d = 2 * dx - dy;
  253. * Aincr = 2 * (dx - dy);
  254. * Bincr = 2 * dx;
  255. * y = iy1;
  256. * xferLineBytes(x, runlen, null, -1);
  257. *
  258. * for ( y = iy1 + 1 ; y <= iy2 ; y++ )
  259. * {
  260. * if ( d >= 0 )
  261. * {
  262. * x += xincr;
  263. * d += Aincr;
  264. * }
  265. * else
  266. * d += Bincr;
  267. * xferLineBytes(x, runlen, null, -1);
  268. * }
  269. * // End raster graphics
  270. * //currentStream.add("\033*rB");
  271. * // Return to regular print mode.
  272. * //currentStream.add("\033*v0t0n0O");
  273. * }
  274. */
  275. }
  276. private void xferLineBytes(int startpos, int bitcount, Vector save,
  277. int start2) {
  278. /*
  279. * Not yet implemented
  280. * //System.out.println("TXTRenderer.xferLineBytes(" + startpos + ", " + bitcount + ")");
  281. * int curbitpos = 0;
  282. * if ( start2 > 0 && start2 <= (startpos + bitcount) )
  283. * {
  284. * bitcount += (start2 - startpos);
  285. * start2 = 0;
  286. * }
  287. * char bytes[] = new char[((start2>startpos?start2:startpos) + bitcount) / 4 + 2];
  288. * int dlen = 0;
  289. * byte dbyte = 0;
  290. * int bytepos = 0;
  291. * do
  292. * {
  293. * int bits2set;
  294. * if ( startpos < 0 )
  295. * {
  296. * bits2set = bitcount + startpos;
  297. * startpos = 0;
  298. * }
  299. * else
  300. * bits2set = bitcount;
  301. * byte bittype = 0;
  302. * do
  303. * {
  304. * if ( bytepos > 0 )
  305. * {
  306. * int inc = startpos - curbitpos;
  307. * if ( (inc) >= (8 - bytepos) )
  308. * {
  309. * curbitpos += (8 - bytepos);
  310. * bytepos = 0;
  311. * bytes[dlen++] = (char)0;
  312. * bytes[dlen++] = (char)dbyte;
  313. * dbyte = 0;
  314. * }
  315. * else
  316. * {
  317. * bytepos += inc;
  318. * dbyte = (byte)(dbyte ^ (byte)(Math.pow(2, 8 - bytepos) - 1));
  319. * curbitpos += inc;
  320. * }
  321. * }
  322. * // Set runs of whole bytes.
  323. * int setbytes = (startpos - curbitpos) / 8;
  324. * if ( setbytes > 0 )
  325. * {
  326. * curbitpos += setbytes * 8;
  327. * while ( setbytes > 0 )
  328. * {
  329. * if ( setbytes > 256 )
  330. * {
  331. * bytes[dlen++] = 0xFF;
  332. * setbytes -= 256;
  333. * }
  334. * else
  335. * {
  336. * bytes[dlen++] = (char)((setbytes - 1) & 0xFF);
  337. * setbytes = 0;
  338. * }
  339. * bytes[dlen++] = (char)bittype;
  340. * }
  341. * }
  342. * // move to position in the first byte.
  343. * if ( curbitpos < startpos )
  344. * {
  345. * if ( bytepos == 0 )
  346. * dbyte = bittype;
  347. * bytepos += startpos - curbitpos;
  348. * dbyte = (byte)(dbyte ^ (byte)(Math.pow(2, 8 - bytepos) - 1));
  349. * curbitpos += bytepos;
  350. * startpos += bits2set;
  351. * }
  352. * else
  353. * {
  354. * startpos += bits2set;
  355. * }
  356. * if ( bittype == 0 )
  357. * bittype = (byte)0xFF;
  358. * else
  359. * bittype = 7;
  360. * } while ( bittype != 7 );
  361. * if ( start2 > 0 )
  362. * {
  363. * startpos = start2;
  364. * start2 = -1;
  365. * }
  366. * else
  367. * startpos = -1;
  368. * } while ( startpos >= 0 );
  369. * if ( bytepos > 0 )
  370. * {
  371. * bytes[dlen++] = (char)0;
  372. * bytes[dlen++] = (char)dbyte;
  373. * }
  374. * if ( save == null )
  375. * {
  376. * //currentStream.add("\033*b" + dlen + "W");
  377. * //currentStream.add(new String(bytes, 0, dlen));
  378. * }
  379. * else
  380. * {
  381. * String line = "\033*b" + dlen + "W" + new String(bytes, 0, dlen);
  382. * //currentStream.add(line);
  383. * save.addElement(line);
  384. * }
  385. */
  386. }
  387. /**
  388. * add a rectangle to the current stream
  389. *
  390. * @param x the x position of left edge in millipoints
  391. * @param y the y position of top edge in millipoints
  392. * @param w the width in millipoints
  393. * @param h the height in millipoints
  394. * @param stroke the stroke color/gradient
  395. */
  396. protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke) {
  397. if (h < 0)
  398. h *= -1;
  399. if (h < 720 || w < 720) {
  400. if (w < 720)
  401. w = 720;
  402. if (h < 720)
  403. h = 720;
  404. addRect(x, y, w, h, stroke, stroke);
  405. } else {
  406. addRect(x, y, w, 720, stroke, stroke);
  407. addRect(x, y, 720, h, stroke, stroke);
  408. addRect(x + w - 720, y, 720, h, stroke, stroke);
  409. addRect(x, y - h + 720, w, 720, stroke, stroke);
  410. }
  411. }
  412. /**
  413. * add a filled rectangle to the current stream
  414. *
  415. * @param x the x position of left edge in millipoints
  416. * @param y the y position of top edge in millipoints
  417. * @param w the width in millipoints
  418. * @param h the height in millipoints
  419. * @param fill the fill color/gradient
  420. * @param stroke the stroke color/gradient
  421. */
  422. protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke,
  423. PDFPathPaint fill) {
  424. // System.out.println("TXTRenderer.addRect(" + x + ", " + y + ", " + w + ", " + h + ", " + r + ", " + g + ", " + b + ", " + fr + ", " + fg + ", " + fb + ")");
  425. if ((w == 0) || (h == 0))
  426. return;
  427. if (h < 0)
  428. h *= -1;
  429. int row = (int)((pageHeight - (y / 100)) * 100 * yFactor);
  430. int col = (int)(x * xFactor);
  431. PDFColor sc = (PDFColor)stroke;
  432. PDFColor fc = (PDFColor)fill;
  433. sc.setColorSpace(ColorSpace.DEVICE_RGB);
  434. fc.setColorSpace(ColorSpace.DEVICE_RGB);
  435. int lineshade =
  436. (int)(100
  437. - ((0.3f * sc.red() + 0.59f * sc.green() + 0.11f * sc.blue())
  438. * 100f));
  439. int fillshade =
  440. (int)(100
  441. - ((0.3f * fc.red() + 0.59f * fc.green() + 0.11f * fc.blue())
  442. * 100f));
  443. if (debug)
  444. System.out.println("TXTRenderer.addRect(" + x + ", " + y + ", "
  445. + w + ", " + h + ", " + stroke + ", " + fill
  446. + ") fillshade=" + fillshade);
  447. char fillchar = ' ';
  448. if (fillshade >= 75)
  449. fillchar = '#';
  450. else if (fillshade >= 50)
  451. fillchar = '*';
  452. else if (fillshade >= 25)
  453. fillchar = ':';
  454. if (fillchar != ' ') {
  455. StringBuffer linefill = new StringBuffer();
  456. int sw = (int)(w * xFactor);
  457. int sh = (int)(h * yFactor);
  458. if (sw == 0 || sh == 0) {
  459. if (fillshade >= 50) {
  460. if (h > w)
  461. fillchar = '|';
  462. else
  463. fillchar = '-';
  464. } else {
  465. if (h > w)
  466. fillchar = ':';
  467. else
  468. fillchar = '.';
  469. }
  470. }
  471. if (sw == 0)
  472. linefill.append(fillchar);
  473. else
  474. for (int countr = 0; countr < sw; countr++)
  475. linefill.append(fillchar);
  476. if (sh == 0)
  477. addStr(row, col, linefill.toString(), false);
  478. else
  479. for (int countr = 0; countr < sh; countr++)
  480. addStr(row + countr, col, linefill.toString(), false);
  481. }
  482. if (lineshade >= 25) {
  483. char vlinechar = '|';
  484. char hlinechar = '-';
  485. if (lineshade < 50) {
  486. vlinechar = ':';
  487. hlinechar = '.';
  488. }
  489. StringBuffer linefill = new StringBuffer();
  490. int sw = (int)(w * xFactor);
  491. for (int countr = 0; countr < sw; countr++)
  492. linefill.append(hlinechar);
  493. int sh = (int)(h * yFactor);
  494. if (w > h) {
  495. for (int countr = 1; countr < (sh - 1); countr++) {
  496. addStr(row + countr, col, String.valueOf(vlinechar),
  497. false);
  498. addStr(row + countr, col + sw, String.valueOf(vlinechar),
  499. false);
  500. }
  501. addStr(row, col, linefill.toString(), false);
  502. addStr(row + sh, col, linefill.toString(), false);
  503. } else {
  504. addStr(row, col, linefill.toString(), false);
  505. addStr(row + sh, col, linefill.toString(), false);
  506. for (int countr = 1; countr < (sh - 1); countr++) {
  507. addStr(row + countr, col, String.valueOf(vlinechar),
  508. false);
  509. addStr(row + countr, col + sw, String.valueOf(vlinechar),
  510. false);
  511. }
  512. }
  513. }
  514. }
  515. /**
  516. * add a filled rectangle to the current stream
  517. *
  518. * @param x the x position of left edge in millipoints
  519. * @param y the y position of top edge in millipoints
  520. * @param w the width in millipoints
  521. * @param h the height in millipoints
  522. * @param r the red component of edges
  523. * @param g the green component of edges
  524. * @param b the blue component of edges
  525. * @param fr the red component of the fill
  526. * @param fg the green component of the fill
  527. * @param fb the blue component of the fill
  528. */
  529. protected void addRect(float x, float y, float w, float h, float rx,
  530. float ry, PDFColor fc, PDFColor sc, float sw) {
  531. /*
  532. * SVG - Not yet implemented
  533. * if ( debug )
  534. * System.out.println("TXTRenderer.addRect(" + x + ", " + y + ", " + w + ", " + h + ", " + rx + ", " + ry + ", " + fc + ", " + sc + ", " + sw + ")");
  535. * float sr = 1;
  536. * float sg = 1;
  537. * float sb = 1;
  538. * float fr = 1;
  539. * float fg = 1;
  540. * float fb = 1;
  541. * if ( sc != null && sw > 0 )
  542. * {
  543. * sr = (float)sc.red();
  544. * sg = (float)sc.green();
  545. * sb = (float)sc.blue();
  546. * }
  547. * if ( fc != null )
  548. * {
  549. * fr = (float)fc.red();
  550. * fg = (float)fc.green();
  551. * fb = (float)fc.blue();
  552. * }
  553. * addRect((int)(x * 1000), (int)(pageHeight * 100 - y * 1000), (int)(w * 1000), (int)(h * 1000), sr, sg, sb, fr, fg, fb);
  554. * fc = null;
  555. * sc = null;
  556. * if ( rx == 0 || ry == 0 )
  557. * {
  558. * if ( fc != null )
  559. * {
  560. * int fillshade = (int)(100 - ((0.3f * fc.red() + 0.59f * fc.green() + 0.11f * fc.blue()) * 100f));
  561. * currentStream.add("\033*v0n1O\033&a" + (x * 10) + "h" + ((y * 10)) + "V"
  562. * + "\033*c" + (w * 10) + "h" + (h * 10) + "v" + fillshade + "g2P\033*v0n0O");
  563. * }
  564. * if ( sc != null && sw > 0 )
  565. * {
  566. * String lend = "v" + String.valueOf((int)(100 - ((0.3f * sc.red() + 0.59f * sc.green() + 0.11f * sc.blue()) * 100f))) + "g2P";
  567. * currentStream.add("\033*v0n1O");
  568. * currentStream.add("\033&a" + ((x - sw/2) * 10) + "h" + (((y - sw/2)) * 10) + "V"
  569. * + "\033*c" + ((w + sw) * 10) + "h" + ((sw) * 10) + lend);
  570. * currentStream.add("\033&a" + ((x - sw/2) * 10) + "h" + (((y - sw/2)) * 10) + "V"
  571. * + "\033*c" + ((sw) * 10) + "h" + ((h + sw) * 10) + lend);
  572. * currentStream.add("\033&a" + ((x + w - sw/2) * 10) + "h" + (((y - sw/2)) * 10) + "V"
  573. * + "\033*c" + ((sw) * 10) + "h" + ((h + sw) * 10) + lend);
  574. * currentStream.add("\033&a" + ((x - sw/2) * 10) + "h" + (((y + h - sw/2)) * 10) + "V"
  575. * + "\033*c" + ((w + sw) * 10) + "h" + ((sw) * 10) + lend);
  576. * currentStream.add("\033*v0n0O");
  577. * }
  578. * }
  579. * else
  580. * {
  581. * // Convert dimensions to pixels.
  582. * float cfact = 300f / 72f; // 300 dpi, 1pt=1/72in
  583. * int ix = (int)(x * cfact);
  584. * int iy = (int)(y * cfact);
  585. * int iw = (int)(w * cfact);
  586. * int ih = (int)(h * cfact);
  587. * int irx = (int)(rx * cfact);
  588. * int iry = (int)(ry * cfact);
  589. * int isw = (int)(sw * cfact);
  590. * int longwidth = 0;
  591. * int pass = 0;
  592. * PDFColor thecolor = null;
  593. * do
  594. * {
  595. * if ( pass == 0 && fc != null )
  596. * {
  597. * thecolor = fc;
  598. * }
  599. * else if ( pass == 1 && sc != null )
  600. * {
  601. * int iswdiv2 = isw / 2;
  602. * thecolor = sc;
  603. * ix -= iswdiv2;
  604. * iy -= iswdiv2;
  605. * irx += iswdiv2;
  606. * iry += iswdiv2;
  607. * iw += isw;
  608. * ih += isw;
  609. * longwidth = (int)(isw * 1.414);
  610. * }
  611. * else
  612. * thecolor = null;
  613. * if ( thecolor != null )
  614. * {
  615. * int tx = 0;
  616. * int ty = iry;
  617. * long a = irx;
  618. * long b = iry;
  619. * long Asquared = (long)Math.pow(a, 2);
  620. * long TwoAsquared = 2 * Asquared;
  621. * long Bsquared = (long)Math.pow(b, 2);
  622. * long TwoBsquared = 2 * Bsquared;
  623. * long d = Bsquared - Asquared * b + Asquared / 4;
  624. * long dx = 0;
  625. * long dy = TwoAsquared * b;
  626. * int rectlen = iw - 2 * irx;
  627. * Vector bottomlines = new Vector();
  628. * int x0 = tx;
  629. * // Set Transparency modes and select shading.
  630. * currentStream.add("\033*v0n1O\033*c" + (int)(100 - ((0.3f * thecolor.red() + 0.59f * thecolor.green() + 0.11f * thecolor.blue()) * 100f)) + "G\033*v2T");
  631. * // Move to starting position.
  632. * currentStream.add("\033*p" + ix + "x" + iy + "Y");
  633. * // Start raster graphics
  634. * currentStream.add("\033*t300R\033*r" + iw + "s1A\033*b1M");
  635. * while ( dx < dy )
  636. * {
  637. * if ( d > 0 )
  638. * {
  639. * if ( pass == 0 || ty > (iry - isw) )
  640. * xferLineBytes(irx - x0, rectlen + 2 * x0, bottomlines, -1);
  641. * else
  642. * xferLineBytes(irx - x0, longwidth, bottomlines, iw - irx + x0 - longwidth);
  643. * x0 = tx + 1;
  644. * ty--;
  645. * dy -= TwoAsquared;
  646. * d -= dy;
  647. * }
  648. * tx++;
  649. * dx += TwoBsquared;
  650. * d += Bsquared + dx;
  651. * }
  652. * d += (3 * (Asquared - Bsquared) / 2 - (dx + dy)) / 2;
  653. * while ( ty > 0 )
  654. * {
  655. * if ( pass == 0 || ty >= (iry - isw) )
  656. * xferLineBytes(irx - tx, rectlen + 2 * tx, bottomlines, -1);
  657. * else
  658. * xferLineBytes(irx - tx, isw, bottomlines, iw - irx + tx - isw);
  659. *
  660. * if ( d < 0 )
  661. * {
  662. * tx++;
  663. * dx += TwoBsquared;
  664. * d += dx;
  665. * }
  666. * ty--;
  667. * dy -= TwoAsquared;
  668. * d += Asquared - dy;
  669. * }
  670. * // Draw the middle part of the rectangle
  671. * int midlen = ih - 2 * iry;
  672. * if ( midlen > 0 )
  673. * {
  674. * if ( pass == 0 )
  675. * xferLineBytes(0, iw, null, -1);
  676. * else
  677. * xferLineBytes(0, isw, null, iw - isw);
  678. * currentStream.add("\033*b3M");
  679. * for ( int countr = midlen - 1 ; countr > 0 ; countr-- )
  680. * currentStream.add("\033*b0W");
  681. * currentStream.add("\033*b1M");
  682. * }
  683. * // Draw the bottom.
  684. * for ( int countr = bottomlines.size() - 1 ; countr >= 0 ; countr-- )
  685. * currentStream.add((String)bottomlines.elementAt(countr));
  686. * // End raster graphics
  687. * currentStream.add("\033*rB");
  688. * // Return to regular print mode.
  689. * currentStream.add("\033*v0t0n0O");
  690. * }
  691. * pass++;
  692. * } while ( pass < 2 );
  693. * }
  694. */
  695. }
  696. // Add a polyline or polygon. Does not support fills yet!!!
  697. protected void addPolyline(Vector points, int posx, int posy,
  698. PDFColor fc, PDFColor sc, float sw,
  699. boolean close) {}
  700. boolean printBMP(FopImage img, int x, int y, int w,
  701. int h) throws FopImageException {
  702. if (debug)
  703. System.out.println("TXTRenderer.printBMP(" + img + ", " + x
  704. + ", " + y + ", " + w + ", " + h + ")");
  705. addRect(x, y, w, h, new PDFColor(1f, 1f, 1f),
  706. new PDFColor(0f, 0f, 0f));
  707. int nameh = (int)(h * yFactor / 2);
  708. if (nameh > 0) {
  709. int namew = (int)(w * xFactor);
  710. if (namew > 4) {
  711. String iname = img.getURL();
  712. if (iname.length() >= namew)
  713. addStr((int)((pageHeight - (y / 100)) * 100 * yFactor)
  714. + nameh, (int)(x * xFactor),
  715. iname.substring(iname.length() - namew),
  716. true);
  717. else
  718. addStr((int)((pageHeight - (y / 100)) * 100 * yFactor)
  719. + nameh, (int)(x * xFactor
  720. + (namew - iname.length())
  721. / 2), iname, true);
  722. }
  723. }
  724. return (true);
  725. }
  726. /**
  727. * render image area to PCL
  728. *
  729. * @param area the image area to render
  730. */
  731. public void renderImageArea(ImageArea area) {
  732. int x = this.currentAreaContainerXPosition + area.getXOffset();
  733. int y = this.currentYPosition;
  734. int w = area.getContentWidth();
  735. int h = area.getHeight();
  736. this.currentYPosition -= h;
  737. FopImage img = area.getImage();
  738. try {
  739. printBMP(img, x, y, w, h);
  740. } catch (FopImageException e) {
  741. // e.printStackTrace(System.out);
  742. log.error("TXTRenderer.renderImageArea() printing BMP ("
  743. + e.toString() + ").", e);
  744. }
  745. }
  746. public void renderImage(FontState fontState, String href, float x,
  747. float y, float width, float height) {
  748. try {
  749. if (href.indexOf(":") == -1)
  750. href = "file:" + href;
  751. FopImage img = FopImageFactory.Make(href);
  752. if (img != null) {
  753. if (img instanceof SVGImage) {
  754. SVGSVGElement svg =
  755. ((SVGImage)img).getSVGDocument().getRootElement();
  756. renderSVG(fontState, svg, (int)x * 1000, (int)y * 1000);
  757. } else {
  758. printBMP(img, (int)x, (int)y, (int)width, (int)height);
  759. }
  760. }
  761. } catch (Exception e) {
  762. log.error("could not add image to SVG: " + href, e);
  763. }
  764. }
  765. /**
  766. * render a foreign object area
  767. */
  768. public void renderForeignObjectArea(ForeignObjectArea area) {
  769. // if necessary need to scale and align the content
  770. this.currentXPosition = this.currentXPosition + area.getXOffset();
  771. this.currentYPosition = this.currentYPosition;
  772. switch (area.getAlign()) {
  773. case TextAlign.START:
  774. break;
  775. case TextAlign.END:
  776. break;
  777. case TextAlign.CENTER:
  778. case TextAlign.JUSTIFY:
  779. break;
  780. }
  781. switch (area.getVerticalAlign()) {
  782. case VerticalAlign.BASELINE:
  783. break;
  784. case VerticalAlign.MIDDLE:
  785. break;
  786. case VerticalAlign.SUB:
  787. break;
  788. case VerticalAlign.SUPER:
  789. break;
  790. case VerticalAlign.TEXT_TOP:
  791. break;
  792. case VerticalAlign.TEXT_BOTTOM:
  793. break;
  794. case VerticalAlign.TOP:
  795. break;
  796. case VerticalAlign.BOTTOM:
  797. break;
  798. }
  799. // in general the content will not be text
  800. // align and scale
  801. switch (area.scalingMethod()) {
  802. case Scaling.UNIFORM:
  803. break;
  804. case Scaling.NON_UNIFORM:
  805. break;
  806. }
  807. // if the overflow is auto (default), scroll or visible
  808. // then the contents should not be clipped, since this
  809. // is considered a printing medium.
  810. switch (area.getOverflow()) {
  811. case Overflow.VISIBLE:
  812. case Overflow.SCROLL:
  813. case Overflow.AUTO:
  814. break;
  815. case Overflow.HIDDEN:
  816. break;
  817. }
  818. area.getObject().render(this);
  819. this.currentXPosition += area.getEffectiveWidth();
  820. // this.currentYPosition -= area.getEffectiveHeight();
  821. }
  822. void renderSVG(FontState fontState, SVGSVGElement svg, int x, int y) {
  823. /*
  824. * SVG - Not yet implemented
  825. * NodeList nl = svg.getChildNodes();
  826. * for(int count = 0; count < nl.getLength(); count++) {
  827. * Node n = nl.item(count);
  828. * if(n instanceof SVGElement) {
  829. * renderElement(fontState, (SVGElement)n, x, y);
  830. * }
  831. * }
  832. */
  833. }
  834. /**
  835. * render SVG area to Text
  836. *
  837. * @param area the SVG area to render
  838. */
  839. public void renderSVGArea(SVGArea area) {
  840. if (debug)
  841. System.out.println("TXTRenderer.renderSVGArea(" + area + ")");
  842. int x = this.currentAreaContainerXPosition;
  843. int y = this.currentYPosition;
  844. SVGSVGElement svg =
  845. ((SVGDocument)area.getSVGDocument()).getRootElement();
  846. int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000);
  847. int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000);
  848. // currentStream.add("ET\n");
  849. /*
  850. * Clip to the svg area.
  851. * Note: To have the svg overlay (under) a text area then use
  852. * an fo:block-container
  853. */
  854. // currentStream.add("q\n");
  855. // currentStream.add(x / 1000f + " " + y / 1000f + " m\n");
  856. // currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n");
  857. // currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f + " l\n");
  858. // currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n");
  859. // currentStream.add("h\n");
  860. // currentStream.add("W\n");
  861. // currentStream.add("n\n");
  862. // transform so that the coordinates (0,0) is from the top left
  863. // and positive is down and to the right
  864. // currentStream.add(1 + " " + 0 + " " + 0 + " " + (-1) + " " + x / 1000f + " " + y / 1000f + " cm\n");
  865. // TODO - translate and clip to viewbox
  866. renderSVG(area.getFontState(), svg, x, y);
  867. // Enumeration e = area.getChildren().elements();
  868. // while (e.hasMoreElements()) {
  869. // Object o = e.nextElement();
  870. // if(o instanceof GraphicImpl) {
  871. // renderElement(area, (GraphicImpl)o, x, y);
  872. // }
  873. // }
  874. // currentStream.add("Q\n");
  875. // currentStream.add("BT\n");
  876. // this.currentYPosition -= h;
  877. }
  878. /*
  879. * SVG - Not yet implemented
  880. * public void renderElement(FontState fontState, SVGElement area, int posx, int posy)
  881. * {
  882. * if ( debug )
  883. * System.out.println("TXTRenderer.renderElement(" + fontState + ", " + area + ", " + posx + ", " + posy + ")");
  884. * int x = posx;
  885. * int y = posy;
  886. * CSSStyleDeclaration style = null;
  887. * if ( area instanceof SVGStylable )
  888. * style = ((SVGStylable)area).getStyle();
  889. * PDFColor fillColour = null;
  890. * PDFColor strokeColour = null;
  891. * float strokeWidth = 0;
  892. * //currentStream.add("q\n");
  893. * //if( area instanceof SVGTransformable )
  894. * //{
  895. * // SVGTransformable tf = (SVGTransformable)area;
  896. * // SVGAnimatedTransformList trans = tf.getTransform();
  897. * // SVGRect bbox = tf.getBBox();
  898. * // if(trans != null) {
  899. * // applyTransform(trans, bbox);
  900. * // }
  901. * //}
  902. * if(style != null)
  903. * {
  904. * CSSValue sp = style.getPropertyCSSValue("fill");
  905. * if(sp != null)
  906. * {
  907. * if( sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
  908. * {
  909. * if( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_RGBCOLOR )
  910. * {
  911. * RGBColor col = ((CSSPrimitiveValue)sp).getRGBColorValue();
  912. * CSSPrimitiveValue val;
  913. * val = col.getRed();
  914. * float red = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
  915. * val = col.getGreen();
  916. * float green = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
  917. * val = col.getBlue();
  918. * float blue = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
  919. * fillColour = new PDFColor(red, green, blue);
  920. * }
  921. * }
  922. * //if(sp instanceof ColorType)
  923. * //{
  924. * // ColorType ct = (ColorType)sp;
  925. * // fillColour = new PDFColor(ct.red(), ct.green(), ct.blue());
  926. * //}
  927. * }
  928. * else
  929. * fillColour = new PDFColor(0, 0, 0);
  930. * sp = style.getPropertyCSSValue("stroke");
  931. * if(sp != null)
  932. * {
  933. * if( sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
  934. * {
  935. * if( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_RGBCOLOR )
  936. * {
  937. * RGBColor col = ((CSSPrimitiveValue)sp).getRGBColorValue();
  938. * CSSPrimitiveValue val;
  939. * val = col.getRed();
  940. * float red = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
  941. * val = col.getGreen();
  942. * float green = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
  943. * val = col.getBlue();
  944. * float blue = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
  945. * strokeColour = new PDFColor(red, green, blue);
  946. * }
  947. * }
  948. * //if(sp instanceof ColorType)
  949. * //{
  950. * // ColorType ct = (ColorType)sp;
  951. * // strokeColour = new PDFColor(ct.red(), ct.green(), ct.blue());
  952. * //}
  953. * }
  954. * sp = style.getPropertyCSSValue("stroke-width");
  955. * if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE)
  956. * {
  957. * strokeWidth = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
  958. * //PDFNumber pdfNumber = new PDFNumber();
  959. * //currentStream.add(pdfNumber.doubleOut(width) + " w\n");
  960. * //strokeWidth = ((SVGLengthImpl)sp).getValue();
  961. * }
  962. * else
  963. * strokeWidth = 1;
  964. * }
  965. * if (area instanceof SVGRectElement)
  966. * {
  967. * SVGRectElement rg = (SVGRectElement)area;
  968. * float rectx = rg.getX().getBaseVal().getValue() + posx / 1000;
  969. * float recty = ((pageHeight / 10) - posy/1000) + rg.getY().getBaseVal().getValue();
  970. * float rx = rg.getRx().getBaseVal().getValue();
  971. * float ry = rg.getRy().getBaseVal().getValue();
  972. * float rw = rg.getWidth().getBaseVal().getValue();
  973. * float rh = rg.getHeight().getBaseVal().getValue();
  974. * addRect(rectx, recty, rw, rh, rx, ry, fillColour, strokeColour, strokeWidth);
  975. * }
  976. * else if (area instanceof SVGLineElement)
  977. * {
  978. * SVGLineElement lg = (SVGLineElement)area;
  979. * float x1 = lg.getX1().getBaseVal().getValue() + posx / 1000;
  980. * float y1 = ((pageHeight / 10) - posy/1000) + lg.getY1().getBaseVal().getValue();
  981. * float x2 = lg.getX2().getBaseVal().getValue() + posx / 1000;
  982. * float y2 = ((pageHeight / 10) - posy/1000) + lg.getY2().getBaseVal().getValue();
  983. * addLine(x1,y1,x2,y2, strokeColour, strokeWidth);
  984. * }
  985. * else if (area instanceof SVGTextElementImpl)
  986. * {
  987. * //currentStream.add("BT\n");
  988. * renderText(fontState, (SVGTextElementImpl)area, posx / 1000f, ((float)(pageHeight / 10) - posy/1000f));
  989. * //currentStream.add("ET\n");
  990. * }
  991. * else if (area instanceof SVGCircleElement)
  992. * {
  993. * SVGCircleElement cg = (SVGCircleElement)area;
  994. * float cx = cg.getCx().getBaseVal().getValue() + posx / 1000;
  995. * float cy = ((pageHeight / 10) - posy/1000) + cg.getCy().getBaseVal().getValue();
  996. * float r = cg.getR().getBaseVal().getValue();
  997. * //addCircle(cx,cy,r, di);
  998. * addRect(cx - r, cy - r, 2 * r, 2 * r, r, r, fillColour, strokeColour, strokeWidth);
  999. * }
  1000. * else if (area instanceof SVGEllipseElement)
  1001. * {
  1002. * SVGEllipseElement cg = (SVGEllipseElement)area;
  1003. * float cx = cg.getCx().getBaseVal().getValue() + posx / 1000;
  1004. * float cy = ((pageHeight / 10) - posy/1000) + cg.getCy().getBaseVal().getValue();
  1005. * float rx = cg.getRx().getBaseVal().getValue();
  1006. * float ry = cg.getRy().getBaseVal().getValue();
  1007. * //addEllipse(cx,cy,rx,ry, di);
  1008. * addRect(cx - rx, cy - ry, 2 * rx, 2 * ry, rx, ry, fillColour, strokeColour, strokeWidth);
  1009. * }
  1010. * else if (area instanceof SVGPathElementImpl)
  1011. * {
  1012. * //addPath(((SVGPathElementImpl)area).pathElements, posx, posy, di);
  1013. * }
  1014. * else if (area instanceof SVGPolylineElementImpl)
  1015. * {
  1016. * addPolyline(((SVGPolylineElementImpl)area).points, posx, posy, fillColour, strokeColour, strokeWidth, false);
  1017. * }
  1018. * else if (area instanceof SVGPolygonElementImpl)
  1019. * {
  1020. * addPolyline(((SVGPolylineElementImpl)area).points, posx, posy, fillColour, strokeColour, strokeWidth, true);
  1021. * }
  1022. * else if (area instanceof SVGGElementImpl)
  1023. * {
  1024. * renderGArea(fontState, (SVGGElementImpl)area, x, y);
  1025. * }
  1026. * else if(area instanceof SVGUseElementImpl)
  1027. * {
  1028. * SVGUseElementImpl ug = (SVGUseElementImpl)area;
  1029. * String ref = ug.link;
  1030. * ref = ref.substring(1, ref.length());
  1031. * SVGElement graph = null;
  1032. * //GraphicImpl graph = null;
  1033. * //graph = area.locateDef(ref);
  1034. * if(graph != null) {
  1035. * // probably not the best way to do this, should be able
  1036. * // to render without the style being set.
  1037. * //GraphicImpl parent = graph.getGraphicParent();
  1038. * //graph.setParent(area);
  1039. * // need to clip (if necessary) to the use area
  1040. * // the style of the linked element is as if is was
  1041. * // a direct descendant of the use element.
  1042. * renderElement(fontState, graph, posx, posy);
  1043. * //graph.setParent(parent);
  1044. * }
  1045. * }
  1046. * else if (area instanceof SVGImageElementImpl)
  1047. * {
  1048. * SVGImageElementImpl ig = (SVGImageElementImpl)area;
  1049. * renderImage(fontState, ig.link, ig.x, ig.y, ig.width, ig.height);
  1050. * }
  1051. * else if (area instanceof SVGSVGElement)
  1052. * {
  1053. * // the x and y pos will be wrong!
  1054. * renderSVG(fontState, (SVGSVGElement)area, x, y);
  1055. * }
  1056. * else if (area instanceof SVGAElement)
  1057. * {
  1058. * SVGAElement ael = (SVGAElement)area;
  1059. * org.w3c.dom.NodeList nl = ael.getChildNodes();
  1060. * for ( int count = 0 ; count < nl.getLength() ; count++ )
  1061. * {
  1062. * org.w3c.dom.Node n = nl.item(count);
  1063. * if ( n instanceof SVGElement )
  1064. * {
  1065. * if ( n instanceof GraphicElement )
  1066. * {
  1067. * SVGRect rect = ((GraphicElement)n).getBBox();
  1068. * if ( rect != null )
  1069. * {
  1070. * // currentAnnotList = this.pdfDoc.makeAnnotList();
  1071. * // currentPage.setAnnotList(currentAnnotList);
  1072. * // String dest = linkSet.getDest();
  1073. * // int linkType = linkSet.getLinkType();
  1074. * // currentAnnotList.addLink(
  1075. * // this.pdfDoc.makeLink(lrect.getRectangle(), dest, linkType));
  1076. * // currentAnnotList = null;
  1077. * // }
  1078. * }
  1079. * renderElement(fontState, (SVGElement)n, posx, posy);
  1080. * }
  1081. * }
  1082. * }
  1083. * else if ( area instanceof SVGSwitchElement )
  1084. * {
  1085. * handleSwitchElement(fontState, posx, posy, (SVGSwitchElement)area);
  1086. * }
  1087. * // should be done with some cleanup code, so only
  1088. * // required values are reset.
  1089. * //currentStream.add("Q\n");
  1090. * }
  1091. */
  1092. private void setFont(String name, float size) {
  1093. return;
  1094. }
  1095. /*
  1096. * SVG - Not implemented yet.
  1097. * public void renderText(FontState fontState, SVGTextElementImpl tg, float x, float y)
  1098. * {
  1099. * PDFNumber pdfNumber = new PDFNumber();
  1100. * CSSStyleDeclaration styles;
  1101. * styles = tg.getStyle();
  1102. * //applyStyle(tg, styles);
  1103. * // apply transform
  1104. * // text has a Tm and need to handle each element
  1105. * SVGTransformList trans = tg.getTransform().getBaseVal();
  1106. * SVGMatrix matrix = trans.consolidate().getMatrix();
  1107. * String transstr = (pdfNumber.doubleOut(matrix.getA())
  1108. * + " " + pdfNumber.doubleOut(matrix.getB())
  1109. * + " " + pdfNumber.doubleOut(matrix.getC())
  1110. * + " " + pdfNumber.doubleOut(-matrix.getD()) + " ");
  1111. * String fontFamily = null;
  1112. * CSSValue sp = styles.getPropertyCSSValue("font-family");
  1113. * if ( sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
  1114. * {
  1115. * if ( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING )
  1116. * fontFamily = sp.getCssText();
  1117. * }
  1118. * if ( fontFamily == null )
  1119. * fontFamily = fontState.getFontFamily();
  1120. * String fontStyle = null;
  1121. * sp = styles.getPropertyCSSValue("font-style");
  1122. * if ( sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
  1123. * {
  1124. * if ( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING )
  1125. * fontStyle = sp.getCssText();
  1126. * }
  1127. * if ( fontStyle == null )
  1128. * fontStyle = fontState.getFontStyle();
  1129. * String fontWeight = null;
  1130. * sp = styles.getPropertyCSSValue("font-weight");
  1131. * if( sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
  1132. * {
  1133. * if ( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING )
  1134. * fontWeight = sp.getCssText();
  1135. * }
  1136. * if( fontWeight == null )
  1137. * fontWeight = fontState.getFontWeight();
  1138. * float fontSize;
  1139. * sp = styles.getPropertyCSSValue("font-size");
  1140. * if( sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
  1141. * {
  1142. * // if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_NUMBER) {
  1143. * fontSize = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
  1144. * // }
  1145. * }
  1146. * else
  1147. * {
  1148. * fontSize = fontState.getFontSize() / 1000f;
  1149. * }
  1150. * FontState fs = fontState;
  1151. * try
  1152. * {
  1153. * fs = new FontState(fontState.getFontInfo(), fontFamily, fontStyle,
  1154. * fontWeight, (int)(fontSize * 1000));
  1155. * }
  1156. * catch( Exception fope )
  1157. * {
  1158. * // fope.printStackTrace();
  1159. * }
  1160. * //currentStream.add("/" + fs.getFontName() + " " + fontSize + " Tf\n");
  1161. * setFont(fs.getFontName(), fontSize * 1000);
  1162. * float tx = tg.x;
  1163. * float ty = tg.y;
  1164. * float currentX = x + tx;
  1165. * float currentY = y + ty;
  1166. * Vector list = tg.textList;
  1167. * for ( Enumeration e = list.elements() ; e.hasMoreElements() ; )
  1168. * {
  1169. * Object o = e.nextElement();
  1170. * styles = tg.getStyle();
  1171. * //applyStyle(tg, styles);
  1172. * if( o instanceof String )
  1173. * {
  1174. * String str = (String)o;
  1175. * //currentStream.add(transstr
  1176. * // + (currentX + matrix.getE()) + " "
  1177. * // + (y+ty + matrix.getF()) + " Tm "
  1178. * // + "(");
  1179. * boolean spacing = "preserve".equals(tg.getXMLspace());
  1180. * //currentX = addSVGStr(fs, currentX, str, spacing);
  1181. * //currentStream.add(") Tj\n");
  1182. * // for(int count = 0; count < str.length(); count++) {
  1183. * // }
  1184. * // currentX += fs.width(' ') / 1000f;
  1185. * currentStream.add("\033&a" + (currentX + matrix.getE())*10 + "h" + (y+ty + matrix.getF())*10 + "V" + str);
  1186. * for ( int count = 0; count < str.length(); count++ )
  1187. * {
  1188. * currentX += fs.width(str.charAt(count)) / 1000f;
  1189. * }
  1190. * currentX += fs.width(' ') / 1000f;
  1191. * } else if(o instanceof SVGTextPathElementImpl) {
  1192. * SVGTextPathElementImpl tpg = (SVGTextPathElementImpl)o;
  1193. * String ref = tpg.str;
  1194. * SVGElement graph = null;
  1195. * // graph = tpg.locateDef(ref);
  1196. * if(graph != null && graph instanceof SVGPathElementImpl) {
  1197. * // probably not the best way to do this, should be able
  1198. * // to render without the style being set.
  1199. * // GraphicImpl parent = graph.getGraphicParent();
  1200. * // graph.setParent(tpg);
  1201. * // set text path??
  1202. * // how should this work
  1203. * // graph.setParent(parent);
  1204. * }
  1205. * } else if(o instanceof SVGTRefElementImpl) {
  1206. * SVGTRefElementImpl trg = (SVGTRefElementImpl)o;
  1207. * String ref = trg.ref;
  1208. * ref = ref.substring(1, ref.length());
  1209. * SVGElement graph = null;
  1210. * // graph = trg.locateDef(ref);
  1211. * if(graph != null && graph instanceof SVGTextElementImpl) {
  1212. * // GraphicImpl parent = graph.getGraphicParent();
  1213. * // graph.setParent(trg);
  1214. * SVGTextElementImpl te = (SVGTextElementImpl)graph;
  1215. * renderText(fs, te, (int)(x + tx), (int)(y + ty));
  1216. * // graph.setParent(parent);
  1217. * }
  1218. * } else if(o instanceof SVGTSpanElementImpl) {
  1219. * SVGTSpanElementImpl tsg = (SVGTSpanElementImpl)o;
  1220. * styles = tsg.getStyle();
  1221. * //applyStyle(tsg, styles);
  1222. * boolean changed = false;
  1223. * String newprop = null;
  1224. * sp = styles.getPropertyCSSValue("font-family");
  1225. * if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
  1226. * if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
  1227. * newprop = sp.getCssText();
  1228. * }
  1229. * }
  1230. * if(newprop != null && !newprop.equals(fontFamily)) {
  1231. * fontFamily = newprop;
  1232. * changed = true;
  1233. * }
  1234. * sp = styles.getPropertyCSSValue("font-style");
  1235. * if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
  1236. * if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
  1237. * newprop = sp.getCssText();
  1238. * }
  1239. * }
  1240. * if(newprop != null && !newprop.equals(fontStyle)) {
  1241. * fontStyle = newprop;
  1242. * changed = true;
  1243. * }
  1244. * sp = styles.getPropertyCSSValue("font-weight");
  1245. * if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
  1246. * if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
  1247. * newprop = sp.getCssText();
  1248. * }
  1249. * }
  1250. * if(newprop != null && !newprop.equals(fontWeight)) {
  1251. * fontWeight = newprop;
  1252. * changed = true;
  1253. * }
  1254. * float newSize = fontSize;
  1255. * sp = styles.getPropertyCSSValue("font-size");
  1256. * if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
  1257. * // if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_NUMBER) {
  1258. * newSize = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
  1259. * // }
  1260. * }
  1261. * if ( fontSize != newSize )
  1262. * {
  1263. * fontSize = newSize;
  1264. * changed = true;
  1265. * }
  1266. * FontState oldfs = null;
  1267. * if ( changed )
  1268. * {
  1269. * oldfs = fs;
  1270. * try
  1271. * {
  1272. * fs = new FontState(fontState.getFontInfo(), fontFamily, fontStyle,
  1273. * fontWeight, (int)(fontSize * 1000));
  1274. * }
  1275. * catch(Exception fope)
  1276. * {
  1277. * }
  1278. * setFont(fs.getFontName(), fontSize * 1000);
  1279. * //currentStream.add("/" + fs.getFontName() + " " + fontSize + " Tf\n");
  1280. * }
  1281. * float baseX;
  1282. * float baseY;
  1283. * StringBuffer pdf = new StringBuffer();
  1284. * boolean spacing = "preserve".equals(tsg.getXMLspace());
  1285. * boolean inbetween = false;
  1286. * boolean addedspace = false;
  1287. * int charPos = 0;
  1288. * float xpos = currentX;
  1289. * float ypos = currentY;
  1290. * for ( int i=0 ; i < tsg.str.length() ; i++ )
  1291. * {
  1292. * char ch = tsg.str.charAt(i);
  1293. * xpos = currentX;
  1294. * ypos = currentY;
  1295. * if ( tsg.ylist.size() > charPos )
  1296. * ypos = y + ty + ((Float)tsg.ylist.elementAt(charPos)).floatValue();
  1297. * if ( tsg.dylist.size() > charPos )
  1298. * ypos = ypos + ((Float)tsg.dylist.elementAt(charPos)).floatValue();
  1299. * if ( tsg.xlist.size() > charPos )
  1300. * xpos = x + tx + ((Float)tsg.xlist.elementAt(charPos)).floatValue();
  1301. * if ( tsg.dxlist.size() > charPos )
  1302. * xpos = xpos + ((Float)tsg.dxlist.elementAt(charPos)).floatValue();
  1303. * switch (ch)
  1304. * {
  1305. * case ' ':
  1306. * case ' ':
  1307. * if ( spacing )
  1308. * {
  1309. * currentX = xpos + fs.width(' ') / 1000f;
  1310. * currentY = ypos;
  1311. * charPos++;
  1312. * }
  1313. * else
  1314. * {
  1315. * if ( inbetween && !addedspace)
  1316. * {
  1317. * addedspace = true;
  1318. * currentX = xpos + fs.width(' ') / 1000f;
  1319. * currentY = ypos;
  1320. * charPos++;
  1321. * }
  1322. * }
  1323. * break;
  1324. * case '\n':
  1325. * case '\r':
  1326. * if ( spacing )
  1327. * {
  1328. * currentX = xpos + fs.width(' ') / 1000f;
  1329. * currentY = ypos;
  1330. * charPos++;
  1331. * }
  1332. * break;
  1333. * default:
  1334. * addedspace = false;
  1335. * pdf = pdf.append(transstr
  1336. * + (xpos + matrix.getE()) + " "
  1337. * + (ypos + matrix.getF()) + " Tm "
  1338. * + "(" + ch + ") Tj\n");
  1339. * pdf = pdf.append("\033&a" + (xpos + matrix.getE())*10 + "h" + (ypos + matrix.getF())*10 + "V" + ch);
  1340. * currentX = xpos + fs.width(ch) / 1000f;
  1341. * currentY = ypos;
  1342. * charPos++;
  1343. * inbetween = true;
  1344. * break;
  1345. * }
  1346. * //currentStream.add(pdf.toString());
  1347. * }
  1348. * // currentX += fs.width(' ') / 1000f;
  1349. * if ( changed )
  1350. * {
  1351. * fs = oldfs;
  1352. * setFont(fs.getFontName(), fs.getFontSize() * 1000);
  1353. * //currentStream.add("/" + fs.getFontName() + " " + fs.getFontSize() / 1000f + " Tf\n");
  1354. * }
  1355. * }
  1356. * else
  1357. * {
  1358. * System.err.println("Error: unknown text element " + o);
  1359. * }
  1360. * }
  1361. * }
  1362. */
  1363. /*
  1364. * SVG - Not yet implemented
  1365. * public void renderGArea(FontState fontState, SVGGElement area, int posx, int posy)
  1366. * {
  1367. * NodeList nl = area.getChildNodes();
  1368. * for ( int count = 0 ; count < nl.getLength() ; count++ )
  1369. * {
  1370. * Node n = nl.item(count);
  1371. * if ( n instanceof SVGElement )
  1372. * renderElement(fontState, (SVGElement)n, posx, posy);
  1373. * }
  1374. * }
  1375. */
  1376. /*
  1377. * SVG - Not yet implemented
  1378. * void handleSwitchElement(FontState fontState, int posx, int posy, SVGSwitchElement ael)
  1379. * {
  1380. * SVGList relist = ael.getRequiredExtensions();
  1381. * SVGList rflist = ael.getRequiredFeatures();
  1382. * SVGList sllist = ael.getSystemLanguage();
  1383. * org.w3c.dom.NodeList nl = ael.getChildNodes();
  1384. * for(int count = 0; count < nl.getLength(); count++) {
  1385. * org.w3c.dom.Node n = nl.item(count);
  1386. * // only render the first child that has a valid
  1387. * // test data
  1388. * if(n instanceof GraphicElement) {
  1389. * GraphicElement graphic = (GraphicElement)n;
  1390. * SVGList grelist = graphic.getRequiredExtensions();
  1391. * // if null it evaluates to true
  1392. * if(grelist != null) {
  1393. * for(int i = 0; i < grelist.getNumberOfItems(); i++) {
  1394. * String str = (String)grelist.getItem(i);
  1395. * if(relist == null) {
  1396. * // use default extension set
  1397. * // currently no extensions are supported
  1398. * // if(!(str.equals("http:// ??"))) {
  1399. * continue;
  1400. * // }
  1401. * } else {
  1402. * }
  1403. * }
  1404. * }
  1405. * SVGList grflist = graphic.getRequiredFeatures();
  1406. * if(grflist != null) {
  1407. * for(int i = 0; i < grflist.getNumberOfItems(); i++) {
  1408. * String str = (String)grflist.getItem(i);
  1409. * if(rflist == null) {
  1410. * // use default feature set
  1411. * if(!(str.equals("org.w3c.svg.static")
  1412. * || str.equals("org.w3c.dom.svg.all"))) {
  1413. * continue;
  1414. * }
  1415. * } else {
  1416. * boolean found = false;
  1417. * for(int j = 0; j < rflist.getNumberOfItems(); j++) {
  1418. * if(rflist.getItem(j).equals(str)) {
  1419. * found = true;
  1420. * break;
  1421. * }
  1422. * }
  1423. * if(!found)
  1424. * continue;
  1425. * }
  1426. * }
  1427. * }
  1428. * SVGList gsllist = graphic.getSystemLanguage();
  1429. * if(gsllist != null) {
  1430. * for(int i = 0; i < gsllist.getNumberOfItems(); i++) {
  1431. * String str = (String)gsllist.getItem(i);
  1432. * if(sllist == null) {
  1433. * // use default feature set
  1434. * if(!(str.equals("en"))) {
  1435. * continue;
  1436. * }
  1437. * } else {
  1438. * boolean found = false;
  1439. * for(int j = 0; j < sllist.getNumberOfItems(); j++) {
  1440. * if(sllist.getItem(j).equals(str)) {
  1441. * found = true;
  1442. * break;
  1443. * }
  1444. * }
  1445. * if(!found)
  1446. * continue;
  1447. * }
  1448. * }
  1449. * }
  1450. * renderElement(fontState, (SVGElement)n, posx, posy);
  1451. * // only render the first valid one
  1452. * break;
  1453. * }
  1454. * }
  1455. * }
  1456. */
  1457. /**
  1458. * render inline area to Text
  1459. *
  1460. * @param area inline area to render
  1461. */
  1462. public void renderWordArea(WordArea area) {
  1463. // System.out.println("TXTRenderer.renderInlineArea: currentXPosition=" + this.currentXPosition + " currentYPosition=" + this.currentYPosition + " text=" + area.getText());
  1464. int rx = this.currentXPosition;
  1465. int bl = this.currentYPosition;
  1466. String s;
  1467. if (area.getPageNumberID() != null) {
  1468. // this text is a page number, so resolve it
  1469. s = idReferences.getPageNumber(area.getPageNumberID());
  1470. if (s == null)
  1471. s = "";
  1472. } else {
  1473. s = area.getText();
  1474. }
  1475. if (debug)
  1476. System.out.println("TXTRenderer.renderInlineArea: rx=" + rx
  1477. + " bl=" + bl + " pageHeight=" + pageHeight);
  1478. addStr((int)((pageHeight - (bl / 100)) * 100 * yFactor) - 1,
  1479. (int)(rx * xFactor), s, true);
  1480. this.currentXPosition += area.getContentWidth();
  1481. }
  1482. /**
  1483. * render inline space to Text
  1484. *
  1485. * @param space space to render
  1486. */
  1487. public void renderInlineSpace(InlineSpace space) {
  1488. this.currentXPosition += space.getSize();
  1489. }
  1490. /**
  1491. * render page into Text
  1492. *
  1493. * @param page page to render
  1494. */
  1495. public void renderPage(Page page) {
  1496. if (debug)
  1497. System.out.println("TXTRenderer.renderPage() page.getHeight() = "
  1498. + page.getHeight());
  1499. BodyAreaContainer body;
  1500. AreaContainer before, after, start, end;
  1501. maxX = (int)(textCPI * page.getWidth() / 72000 + 1);
  1502. maxY = (int)(textLPI * page.getHeight() / 72000 + 1);
  1503. xFactor = (float)(maxX - 1) / (float)page.getWidth();
  1504. yFactor = (float)(maxY - 1) / (float)page.getHeight();
  1505. charData = new StringBuffer[maxY + 1];
  1506. decoData = new StringBuffer[maxY + 1];
  1507. if (paperheight > 0)
  1508. pageHeight = paperheight;
  1509. else
  1510. pageHeight = page.getHeight() / 100;
  1511. if (debug)
  1512. System.out.println("TXTRenderer.renderPage() maxX=" + maxX
  1513. + " maxY=" + maxY + " xFactor=" + xFactor
  1514. + " yFactor=" + yFactor + " paperHeight="
  1515. + pageHeight);
  1516. body = page.getBody();
  1517. before = page.getBefore();
  1518. after = page.getAfter();
  1519. start = page.getStart();
  1520. end = page.getEnd();
  1521. this.currentFontName = "";
  1522. this.currentFontSize = 0;
  1523. // currentStream.add("BT\n");
  1524. renderBodyAreaContainer(body);
  1525. if (before != null)
  1526. renderAreaContainer(before);
  1527. if (after != null)
  1528. renderAreaContainer(after);
  1529. if (start != null)
  1530. renderAreaContainer(start);
  1531. if (end != null)
  1532. renderAreaContainer(end);
  1533. // Write out the buffers.
  1534. for (int row = 0; row <= maxY; row++) {
  1535. StringBuffer cr = charData[row];
  1536. StringBuffer dr = decoData[row];
  1537. StringBuffer outr = null;
  1538. if (cr != null && dr == null)
  1539. outr = cr;
  1540. else if (dr != null && cr == null)
  1541. outr = dr;
  1542. else if (cr != null && dr != null) {
  1543. int len = dr.length();
  1544. if (cr.length() > len)
  1545. len = cr.length();
  1546. outr = new StringBuffer();
  1547. for (int countr = 0; countr < len; countr++) {
  1548. if (countr < cr.length() && cr.charAt(countr) != ' ')
  1549. outr.append(cr.charAt(countr));
  1550. else if (countr < dr.length())
  1551. outr.append(dr.charAt(countr));
  1552. else
  1553. outr.append(' ');
  1554. }
  1555. }
  1556. if (outr != null)
  1557. currentStream.add(outr.toString());
  1558. if (row < maxY)
  1559. currentStream.add(lineEnding);
  1560. }
  1561. // End page.
  1562. // if ( ++curdiv == divisions || divisions == -1 )
  1563. // {
  1564. // curdiv = 0;
  1565. // currentStream.add("\f");
  1566. // }
  1567. // Links, etc not implemented...
  1568. /*
  1569. * currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
  1570. * page.getWidth()/1000,
  1571. * page.getHeight()/1000, page);
  1572. * if (page.hasLinks()) {
  1573. * currentAnnotList = this.pdfDoc.makeAnnotList();
  1574. * currentPage.setAnnotList(currentAnnotList);
  1575. * Enumeration e = page.getLinkSets().elements();
  1576. * while (e.hasMoreElements()) {
  1577. * LinkSet linkSet = (LinkSet) e.nextElement();
  1578. * linkSet.align();
  1579. * String dest = linkSet.getDest();
  1580. * int linkType = linkSet.getLinkType();
  1581. * Enumeration f = linkSet.getRects().elements();
  1582. * while (f.hasMoreElements()) {
  1583. * LinkedRectangle lrect = (LinkedRectangle) f.nextElement();
  1584. * currentAnnotList.addLink(
  1585. * this.pdfDoc.makeLink(lrect.getRectangle(), dest, linkType));
  1586. * }
  1587. * }
  1588. * } else {
  1589. * // just to be on the safe side
  1590. * currentAnnotList = null;
  1591. * }
  1592. */
  1593. }
  1594. public void startRenderer(OutputStream outputStream)
  1595. throws IOException {
  1596. log.info("rendering areas to TEXT");
  1597. currentStream = new PCLStream(outputStream);
  1598. firstPage=true;
  1599. }
  1600. /**
  1601. * In Mark's patch, this is endRenderer
  1602. * However, I couldn't see how it builds that way, so
  1603. * i changed it. - Steve gears@apache.org
  1604. */
  1605. public void stopRenderer(OutputStream outputStream)
  1606. throws IOException {
  1607. log.info("writing out TEXT");
  1608. outputStream.flush();
  1609. }
  1610. public void render(Page page, OutputStream outputStream) {
  1611. idReferences = page.getIDReferences();
  1612. if ( firstPage )
  1613. firstPage = false;
  1614. else
  1615. currentStream.add(pageEnding);
  1616. this.renderPage(page);
  1617. currentStream.add(lineEnding);
  1618. }
  1619. }