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.

TXTRenderer.java 50KB

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