]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
New files for text rendering
authorarved <arved@unknown>
Sat, 10 Mar 2001 18:59:45 +0000 (18:59 +0000)
committerarved <arved@unknown>
Sat, 10 Mar 2001 18:59:45 +0000 (18:59 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194147 13f79535-47bb-0310-9956-ffa450edef68

src/org/apache/fop/render/txt/TXTRenderer.java [new file with mode: 0755]

diff --git a/src/org/apache/fop/render/txt/TXTRenderer.java b/src/org/apache/fop/render/txt/TXTRenderer.java
new file mode 100755 (executable)
index 0000000..e8ba1c0
--- /dev/null
@@ -0,0 +1,1766 @@
+//package com.eastpoint.chrysalis;
+package org.apache.fop.render.txt;
+
+// FOP
+import org.apache.fop.render.PrintRenderer;
+import org.apache.fop.render.pcl.*;
+import org.apache.fop.messaging.MessageHandler;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.properties.*;
+import org.apache.fop.layout.*;
+import org.apache.fop.layout.inline.*;
+import org.apache.fop.datatypes.*;
+import org.apache.fop.svg.PathPoint;
+import org.apache.fop.pdf.PDFPathPaint;
+import org.apache.fop.pdf.PDFColor;
+import org.apache.fop.image.*;
+
+import org.apache.fop.dom.svg.SVGArea;
+import org.w3c.dom.svg.SVGSVGElement;
+
+// Java
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * Renderer that renders areas to plain text
+ */
+public class TXTRenderer extends PrintRenderer
+{
+    /** the current stream to add Text commands to */
+    PCLStream currentStream;
+
+       private int pageHeight = 7920;
+
+       // These variables control the virtual paggination functionality.
+       public int      curdiv = 0;
+       private int     divisions = -1;
+       private int     paperheight = -1;       // Paper height in decipoints?
+       public int      orientation = -1;       // -1=default/unknown, 0=portrait, 1=landscape.
+       public int      topmargin = -1; // Top margin in decipoints?
+       public int      leftmargin = -1;        // Left margin in decipoints?
+       private int fullmargin = 0;
+       final boolean debug = false;
+
+       // Variables for rendering text.
+       StringBuffer    charData[];
+       StringBuffer    decoData[];
+       public float    textCPI = 16.67f;
+       public float    textLPI = 8;
+       int     maxX = (int)(8.5f * textCPI + 1);
+       int     maxY = (int)(11f * textLPI + 1);
+       float   xFactor;
+       float   yFactor;
+
+    /**
+     * create the TXT renderer
+     */
+    public TXTRenderer()
+    {
+    }
+
+    /**
+     * set the TXT document's producer
+     *
+     * @param producer string indicating application producing PDF
+     */
+    public void setProducer(String producer)
+    {
+    }
+
+    /**
+     * render the areas into text
+     *
+     * @param areaTree the laid-out area tree
+     * @param writer the PrintWriter to write the PDF with
+     */
+    public void render(AreaTree areaTree, OutputStream stream) throws IOException, FOPException
+    {
+               MessageHandler.logln("rendering areas to TEXT");
+               idReferences=areaTree.getIDReferences();
+               Enumeration e = areaTree.getPages().elements();
+               currentStream = new PCLStream(stream);
+
+               boolean first = true;
+
+               while (e.hasMoreElements())
+               {
+                       if ( first )
+                               first = false;
+                       else
+                               currentStream.add("/f");
+                   this.renderPage((Page) e.nextElement());
+               }
+        if ( !idReferences.isEveryIdValid() )
+        {
+            //throw new FOPException("The following id's were referenced but not found: "+idReferences.getInvalidIds()+"\n");
+            MessageHandler.errorln("Warning: The following id's were referenced but not found: "+idReferences.getInvalidIds()+"\n");
+        }
+
+        MessageHandler.logln("writing out TEXT");
+               stream.flush();
+    }
+
+       void addStr(int row, int col, String str, boolean ischar)
+       {
+if ( debug )
+System.out.println("TXTRenderer.addStr(" + row + ", " + col + ", \"" + str + "\", " + ischar + ")");
+               StringBuffer sb;
+               if ( row < 0 )
+                       row = 0;
+               if ( ischar )
+                       sb = charData[row];
+               else
+                       sb = decoData[row];
+               if ( sb == null )
+                       sb = new StringBuffer();
+               if ( (col + str.length()) > maxX )
+                       col = maxX - str.length();
+               if ( col < 0 )
+               {
+                       col = 0;
+                       if ( str.length() > maxX )
+                               str = str.substring(0, maxX);
+               }
+               // Pad to col
+               for ( int countr = sb.length() ; countr < col ; countr++ )
+                       sb.append(' ');
+if ( debug )
+System.out.println("TXTRenderer.addStr() sb.length()=" + sb.length());
+               for ( int countr = col ; countr < (col + str.length()) ; countr++ )
+               {
+                       if ( countr >= sb.length() )
+                               sb.append(str.charAt(countr - col));
+                       else
+                       {
+if ( debug )
+System.out.println("TXTRenderer.addStr() sb.length()=" + sb.length() + " countr=" + countr);
+                               sb.setCharAt(countr, str.charAt(countr - col));
+                       }
+               }
+
+               if ( ischar )
+                       charData[row] = sb;
+               else
+                       decoData[row] = sb;
+       }
+
+    /**
+     * add a line to the current stream
+     *
+     * @param x1 the start x location in millipoints
+     * @param y1 the start y location in millipoints
+     * @param x2 the end x location in millipoints
+     * @param y2 the end y location in millipoints
+     * @param th the thickness in millipoints
+     * @param stroke the line color
+     */
+    protected void addLine(int x1, int y1, int x2, int y2, int th, PDFPathPaint stroke)
+       {
+               if ( x1 == x2 )
+               {
+                       addRect(x1, y1, th, y2 - y1 + 1, stroke, stroke);
+               }
+               else if ( y1 == y2 )
+               {
+                       addRect(x1, y1, x2 - x1 + 1, th, stroke, stroke);
+               }
+    }
+
+    /**
+     * add a line to the current stream
+     *
+     * @param x1 the start x location in millipoints
+     * @param y1 the start y location in millipoints
+     * @param x2 the end x location in millipoints
+     * @param y2 the end y location in millipoints
+     * @param th the thickness in millipoints
+     * @param rs the rule style
+     * @param stroke the line color
+     */
+    protected void addLine(int x1, int y1, int x2, int y2, int th, int rs, PDFPathPaint stroke)
+       {
+               PDFColor lstroke = null;
+               if ( rs == org.apache.fop.fo.properties.RuleStyle.DOTTED )
+                       lstroke = new PDFColor(0.7f, 0.7f, 0.7f);
+               else
+                       lstroke = (PDFColor)stroke;
+               if ( x1 == x2 )
+               {
+                       addRect(x1, y1, th, y2 - y1 + 1, lstroke, lstroke);
+               }
+               else if ( y1 == y2 )
+               {
+                       addRect(x1, y1, x2 - x1 + 1, th, lstroke, lstroke);
+               }
+    }
+
+    protected void addLine(float x1, float y1, float x2, float y2, PDFColor sc, float sw)
+       {
+/* SVG - Not yet implemented
+if ( debug )
+System.out.println("TXTRenderer.addLine(" + x1 + ", " + y1 + ", " + x2 + ", " + y2 + ", " + sc + ", " + sw + ")");
+               if ( x1 == x2 )
+               {
+                       addRect(x1 - sw/2, y1, sw, y2 - y1 + 1, 0, 0, sc, null, 0);
+               }
+               else if ( y1 == y2 || (Math.abs(y1 - y2) <= 0.24) )     // 72/300=0.24
+               {
+                       addRect(x1, y1 - sw/2, x2 - x1 + 1, sw, 0, 0, sc, null, 0);
+               }
+               else if ( sc != null )
+               {
+                       // Convert dimensions to characters.
+                       //float cfact = 300f / 72f;     // 300 dpi, 1pt=1/72in
+                       int     ix1 = (int)(x1 * xFactor);
+                       int     iy1 = (int)(y1 * yFactor);
+                       int     ix2 = (int)(x2 * xFactor);
+                       int     iy2 = (int)(y2 * yFactor);
+                       int     isw = (int)(sw * xFactor);
+                       int origix;
+
+                       // Normalize
+                       if ( iy1 > iy2 )
+                       {
+                               int tmp = ix1;
+                               ix1 = ix2;
+                               ix2 = tmp;
+                               tmp = iy1;
+                               iy1 = iy2;
+                               iy2 = tmp;
+                       }
+                       if ( ix1 > ix2 )
+                       {
+                               origix = ix2;
+                               ix1 -=ix2;
+                               ix2 = 0;
+                       }
+                       else
+                       {
+                               origix = ix1;
+                               ix2 -= ix1;
+                               ix1 = 0;
+                       }
+
+                       // Convert line width to a pixel run length.
+//System.out.println("TXTRenderer.addLine(" + ix1 + ", " + iy1 + ", " + ix2 + ", " + iy2 + ", " + isw + ")");
+                       int     runlen = (int)Math.sqrt(Math.pow(isw, 2) * (1 + Math.pow((ix1 - ix2) / (iy1 - iy2), 2)));
+                       if ( runlen < 1 )
+                               runlen = 1;
+                       StringBuffer rlbuff = new StringBuffer();
+                       for ( int countr = 0 ; countr < runlen ; countr++ )
+                               rlbuff.append('*');
+                       String rlstr = rlbuff.toString();
+//System.out.println("TXTRenderer.addLine: runlen = " + runlen);
+
+                       // Draw the line.
+                       int     d, dx, dy;
+                       int     Aincr, Bincr;
+                       int     xincr = 1;
+                       int     x, y;
+
+
+                       dx = Math.abs(ix2 - ix1);
+                       dy = iy2 - iy1;
+
+                       if ( dx > dy )
+                       {
+                               xincr = dx / dy;
+
+                               // Move to starting position.
+                               //currentStream.add("\033*p" + origix + "x" + iy1 + "Y");
+                               x = ix1 - runlen / 2;
+                               iy2 += (isw / 2);
+                               // Start raster graphics
+                               //currentStream.add("\033*t300R\033*r" + dx + "s1A\033*b1M");
+                       }
+                       else
+                       {
+                               // Move to starting position.
+                               //currentStream.add("\033*p" + (origix - runlen / 2) + "x" + iy1 + "Y");
+                               x = ix1;
+                               // Start raster graphics
+                               //currentStream.add("\033*t300R\033*r1A\033*b1M");
+                       }
+
+                       if ( ix1 > ix2 )
+                               xincr *= -1;
+                       d = 2 * dx - dy;
+                       Aincr = 2 * (dx - dy);
+                       Bincr = 2 * dx;
+
+                       y = iy1;
+
+                       xferLineBytes(x, runlen, null, -1);
+                       
+                       for ( y = iy1 + 1 ; y <= iy2 ; y++ )
+                       {
+                               if ( d >= 0 )
+                               {
+                                       x += xincr;
+                                       d += Aincr;
+                               }
+                               else
+                                       d += Bincr;
+                               xferLineBytes(x, runlen, null, -1);
+                       }
+
+                       // End raster graphics
+                       //currentStream.add("\033*rB");
+                       // Return to regular print mode.
+                       //currentStream.add("\033*v0t0n0O");
+               }
+*/
+    }
+
+       private void xferLineBytes(int  startpos, int bitcount, Vector save, int start2)
+       {
+/* Not yet implemented
+//System.out.println("TXTRenderer.xferLineBytes(" + startpos + ", " + bitcount + ")");
+               int     curbitpos = 0;
+               if ( start2 > 0 && start2 <= (startpos + bitcount) )
+               {
+                       bitcount += (start2 - startpos);
+                       start2 = 0;
+               }
+
+               char bytes[] = new char[((start2>startpos?start2:startpos) + bitcount) / 4 + 2];
+               int     dlen = 0;
+               byte dbyte = 0;
+               int     bytepos = 0;
+
+               do
+               {
+                       int bits2set;
+                       if ( startpos < 0 )
+                       {
+                               bits2set = bitcount + startpos;
+                               startpos = 0;
+                       }
+                       else
+                               bits2set = bitcount;
+
+                       byte bittype = 0;
+                       do
+                       {
+                               if ( bytepos > 0 )
+                               {
+                                       int inc = startpos - curbitpos;
+                                       if ( (inc) >=  (8 - bytepos) )
+                                       {
+                                               curbitpos += (8 - bytepos);
+                                               bytepos = 0;
+                                               bytes[dlen++] = (char)0;
+                                               bytes[dlen++] = (char)dbyte;
+                                               dbyte = 0;
+                                       }
+                                       else
+                                       {
+                                               bytepos += inc;
+                                               dbyte = (byte)(dbyte ^ (byte)(Math.pow(2, 8 - bytepos) - 1));
+                                               curbitpos += inc;
+                                       }
+                               }
+
+                               // Set runs of whole bytes.
+                               int     setbytes = (startpos - curbitpos) / 8;
+                               if ( setbytes > 0 )
+                               {
+                                       curbitpos += setbytes * 8;
+                                       while ( setbytes > 0 )
+                                       {
+                                               if ( setbytes > 256 )
+                                               {
+                                                       bytes[dlen++] = 0xFF;
+                                                       setbytes -= 256;
+                                               }
+                                               else
+                                               {
+                                                       bytes[dlen++] = (char)((setbytes - 1) & 0xFF);
+                                                       setbytes = 0;
+                                               }
+                                               bytes[dlen++] = (char)bittype;
+                                       }
+                               }
+                               // move to position in the first byte.
+                               if ( curbitpos < startpos )
+                               {
+                                       if ( bytepos == 0 )
+                                               dbyte = bittype;
+                                       bytepos += startpos - curbitpos;
+                                       dbyte = (byte)(dbyte ^ (byte)(Math.pow(2, 8 - bytepos) - 1));
+                                       curbitpos += bytepos;
+                                       startpos += bits2set;
+                               }
+                               else
+                               {
+                                       startpos += bits2set;
+                               }
+
+                               if ( bittype == 0 )
+                                       bittype = (byte)0xFF;
+                               else
+                                       bittype = 7;
+                       } while ( bittype != 7 );
+
+                       if ( start2 > 0 )
+                       {
+                               startpos = start2;
+                               start2 = -1;
+                       }
+                       else
+                               startpos = -1;
+               } while ( startpos >= 0 );
+               if ( bytepos > 0 )
+               {
+                       bytes[dlen++] = (char)0;
+                       bytes[dlen++] = (char)dbyte;
+               }
+               if ( save == null )
+               {
+                       //currentStream.add("\033*b" + dlen + "W");
+                       //currentStream.add(new String(bytes, 0, dlen));
+               }
+               else
+               {
+                       String line = "\033*b" + dlen + "W" + new String(bytes, 0, dlen);
+                       //currentStream.add(line);
+                       save.addElement(line);
+               }
+*/
+       }
+
+    /**
+     * add a rectangle to the current stream
+     *
+     * @param x the x position of left edge in millipoints
+     * @param y the y position of top edge in millipoints
+     * @param w the width in millipoints
+     * @param h the height in millipoints
+     * @param stroke the stroke color/gradient
+     */
+    protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke)
+    {
+               if ( h < 0 )
+                       h *= -1;
+
+               if (h < 720 || w < 720)
+               {
+                       if ( w < 720 )
+                               w = 720;
+                       if ( h < 720 )
+                               h = 720;
+                   addRect(x, y, w, h, stroke, stroke);
+               }
+               else
+               {
+                   addRect(x, y, w, 720, stroke, stroke);
+                   addRect(x, y, 720, h, stroke, stroke);
+                   addRect(x + w - 720, y, 720, h, stroke, stroke);
+                   addRect(x, y - h + 720, w, 720, stroke, stroke);
+               }
+    }
+
+    /**
+     * add a filled rectangle to the current stream
+     *
+     * @param x the x position of left edge in millipoints
+     * @param y the y position of top edge in millipoints
+     * @param w the width in millipoints
+     * @param h the height in millipoints
+     * @param fill the fill color/gradient
+     * @param stroke the stroke color/gradient
+     */
+    protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke, PDFPathPaint fill)
+       {
+//System.out.println("TXTRenderer.addRect(" + x + ", " + y + ", " + w + ", " + h + ", " + r + ", " + g + ", " + b + ", " + fr + ", " + fg + ", " + fb + ")");
+               if ((w == 0) || (h == 0))
+               return;
+               if ( h < 0 )
+                       h *= -1;
+
+               int     row = (int)((pageHeight - (y / 100))* 100 * yFactor);
+               int     col = (int)(x * xFactor);
+
+               PDFColor sc = (PDFColor)stroke;
+               PDFColor fc = (PDFColor)fill;
+
+               sc.setColorSpace(ColorSpace.DEVICE_RGB);
+               fc.setColorSpace(ColorSpace.DEVICE_RGB);
+
+               int     lineshade = (int)(100 - ((0.3f * sc.red() + 0.59f * sc.green() + 0.11f * sc.blue()) * 100f));
+               int     fillshade = (int)(100 - ((0.3f * fc.red() + 0.59f * fc.green() + 0.11f * fc.blue()) * 100f));
+if ( debug )
+System.out.println("TXTRenderer.addRect(" + x + ", " + y + ", " + w + ", " + h + ", " + stroke + ", " + fill + ") fillshade=" + fillshade);
+               char    fillchar = ' ';
+               if ( fillshade >= 75 )
+                       fillchar = '#';
+               else if ( fillshade >= 50 )
+                       fillchar = '*';
+               else if ( fillshade >= 25 )
+                       fillchar = ':';
+
+
+               if ( fillchar != ' ' )
+               {
+                       StringBuffer linefill = new StringBuffer();
+                       int     sw = (int)(w * xFactor);
+                       int sh = (int)(h * yFactor);
+                       if ( sw == 0 || sh == 0 )
+                       {
+                               if ( fillshade >= 50 )
+                               {
+                                       if ( h > w )
+                                               fillchar = '|';
+                                       else
+                                               fillchar = '-';
+                               }
+                               else
+                               {
+                                       if ( h > w )
+                                               fillchar = ':';
+                                       else
+                                               fillchar = '.';
+                               }
+                       }
+                       if ( sw == 0 )
+                               linefill.append(fillchar);
+                       else
+                               for ( int countr = 0 ; countr < sw ; countr++ )
+                                       linefill.append(fillchar);
+                       if ( sh == 0 )
+                               addStr(row, col, linefill.toString(), false);
+                       else
+                               for ( int countr = 0 ; countr < sh ; countr++ )
+                                       addStr(row + countr, col, linefill.toString(), false);
+               }
+
+               if ( lineshade >= 25 )
+               {
+                       char vlinechar = '|';
+                       char hlinechar = '-';
+                       if ( lineshade < 50 )
+                       {
+                               vlinechar = ':';
+                               hlinechar = '.';
+                       }
+                       StringBuffer linefill = new StringBuffer();
+                       int     sw = (int)(w * xFactor);
+                       for ( int countr = 0 ; countr < sw ; countr++ )
+                               linefill.append(hlinechar);
+                       int sh = (int)(h * yFactor);
+
+                       if ( w > h )
+                       {
+                               for ( int countr = 1 ; countr < (sh - 1); countr++ )
+                               {
+                                       addStr(row + countr, col, String.valueOf(vlinechar), false);
+                                       addStr(row + countr, col + sw, String.valueOf(vlinechar), false);
+                               }
+                               addStr(row, col, linefill.toString(), false);
+                               addStr(row + sh, col, linefill.toString(), false);
+
+                       }
+                       else
+                       {
+                               addStr(row, col, linefill.toString(), false);
+                               addStr(row + sh, col, linefill.toString(), false);
+                               for ( int countr = 1 ; countr < (sh - 1); countr++ )
+                               {
+                                       addStr(row + countr, col, String.valueOf(vlinechar), false);
+                                       addStr(row + countr, col + sw, String.valueOf(vlinechar), false);
+                               }
+
+                       }
+               }
+    }
+
+
+    /**
+     * add a filled rectangle to the current stream
+     *
+     * @param x the x position of left edge in millipoints
+     * @param y the y position of top edge in millipoints
+     * @param w the width in millipoints
+     * @param h the height in millipoints
+     * @param r the red component of edges
+     * @param g the green component of edges
+     * @param b the blue component of edges
+     * @param fr the red component of the fill
+     * @param fg the green component of the fill
+     * @param fb the blue component of the fill
+     */
+    protected void addRect(float x, float y, float w, float h, float rx, float ry,
+                          PDFColor fc, PDFColor sc, float sw)
+       {
+/* SVG - Not yet implemented
+if ( debug )
+System.out.println("TXTRenderer.addRect(" + x + ", " + y + ", " + w + ", " + h + ", " + rx + ", " + ry + ", " + fc + ", " + sc + ", " + sw + ")");
+
+               float sr = 1;
+               float sg = 1;
+               float sb = 1;
+               float fr = 1;
+               float fg = 1;
+               float fb = 1;
+               if ( sc != null && sw > 0 )
+               {
+                       sr = (float)sc.red();
+                       sg = (float)sc.green();
+                       sb = (float)sc.blue();
+               }
+               if ( fc != null )
+               {
+                       fr = (float)fc.red();
+                       fg = (float)fc.green();
+                       fb = (float)fc.blue();
+               }
+               addRect((int)(x * 1000), (int)(pageHeight * 100 - y * 1000), (int)(w * 1000), (int)(h * 1000), sr, sg, sb, fr, fg, fb);
+
+               fc = null;
+               sc = null;
+
+               if ( rx == 0 || ry == 0 )
+               {
+                       if ( fc != null )
+                       {
+                               int fillshade = (int)(100 - ((0.3f * fc.red() + 0.59f * fc.green() + 0.11f * fc.blue()) * 100f));
+                               currentStream.add("\033*v0n1O\033&a" + (x * 10) + "h" + ((y * 10)) + "V"
+                                                                       + "\033*c" + (w * 10) + "h" + (h * 10) + "v" + fillshade + "g2P\033*v0n0O");
+                       }
+                       if ( sc != null && sw > 0 )
+                       {
+                               String lend = "v" + String.valueOf((int)(100 - ((0.3f * sc.red() + 0.59f * sc.green() + 0.11f * sc.blue()) * 100f))) + "g2P";
+                               currentStream.add("\033*v0n1O");
+                               currentStream.add("\033&a" + ((x - sw/2) * 10) + "h" + (((y - sw/2)) * 10) + "V"
+                                                                       + "\033*c" + ((w + sw) * 10) + "h" + ((sw) * 10) + lend);
+                               currentStream.add("\033&a" + ((x - sw/2) * 10) + "h" + (((y - sw/2)) * 10) + "V"
+                                                                       + "\033*c" + ((sw) * 10) + "h" + ((h + sw) * 10) + lend);
+                               currentStream.add("\033&a" + ((x + w - sw/2) * 10) + "h" + (((y - sw/2)) * 10) + "V"
+                                                                       + "\033*c" + ((sw) * 10) + "h" + ((h + sw) * 10) + lend);
+                               currentStream.add("\033&a" + ((x - sw/2) * 10) + "h" + (((y + h - sw/2)) * 10) + "V"
+                                                                       + "\033*c" + ((w + sw) * 10) + "h" + ((sw) * 10) + lend);
+                               currentStream.add("\033*v0n0O");
+                       }
+               }
+               else
+               {
+                       // Convert dimensions to pixels.
+                       float cfact = 300f / 72f;       // 300 dpi, 1pt=1/72in
+                       int     ix = (int)(x * cfact);
+                       int     iy = (int)(y * cfact);
+                       int     iw = (int)(w * cfact);
+                       int     ih = (int)(h * cfact);
+                       int     irx = (int)(rx * cfact);
+                       int     iry = (int)(ry * cfact);
+                       int     isw = (int)(sw * cfact);
+                       int     longwidth = 0;
+                       int     pass = 0;
+                       PDFColor thecolor = null;
+
+                       do
+                       {
+                               if ( pass == 0 && fc != null )
+                               {
+                                       thecolor = fc;
+                               }
+                               else if ( pass == 1 && sc != null )
+                               {
+                                       int     iswdiv2 = isw / 2;
+                                       thecolor = sc;
+                                       ix -= iswdiv2;
+                                       iy -= iswdiv2;
+                                       irx += iswdiv2;
+                                       iry += iswdiv2;
+                                       iw += isw;
+                                       ih += isw;
+                                       longwidth = (int)(isw * 1.414);
+                               }
+                               else
+                                       thecolor = null;
+
+
+                               if ( thecolor != null )
+                               {
+                                       int             tx = 0;
+                                       int             ty = iry;
+                                       long    a = irx;
+                                       long    b = iry;
+                                       long    Asquared = (long)Math.pow(a, 2);
+                                       long    TwoAsquared = 2 * Asquared;
+                                       long    Bsquared = (long)Math.pow(b, 2);
+                                       long    TwoBsquared = 2 * Bsquared;
+                                       long    d = Bsquared - Asquared * b + Asquared / 4;
+                                       long    dx = 0;
+                                       long    dy = TwoAsquared * b;
+                                       int             rectlen = iw - 2 * irx;
+                                       Vector  bottomlines = new Vector();
+
+                                       int x0 = tx;
+
+                                       // Set Transparency modes and select shading.
+                                       currentStream.add("\033*v0n1O\033*c" + (int)(100 - ((0.3f * thecolor.red() + 0.59f * thecolor.green() + 0.11f * thecolor.blue()) * 100f)) + "G\033*v2T");
+                                       // Move to starting position.
+                                       currentStream.add("\033*p" + ix + "x" + iy + "Y");
+                                       // Start raster graphics
+                                       currentStream.add("\033*t300R\033*r" + iw + "s1A\033*b1M");
+
+                                       while ( dx < dy )
+                                       {
+                                               if ( d > 0 )
+                                               {
+                                                       if ( pass == 0 || ty > (iry - isw) )
+                                                               xferLineBytes(irx - x0, rectlen + 2 * x0, bottomlines, -1);
+                                                       else
+                                                               xferLineBytes(irx - x0, longwidth, bottomlines, iw - irx + x0 - longwidth);
+                                                       x0 = tx + 1;
+                                                       ty--;
+                                                       dy -= TwoAsquared;
+                                                       d -= dy;
+                                               }
+                                               tx++;
+                                               dx += TwoBsquared;
+                                               d += Bsquared + dx;
+                                       }
+
+                                       d += (3 * (Asquared - Bsquared) / 2 - (dx + dy)) / 2;
+
+                                       while ( ty > 0 )
+                                       {
+                                               if ( pass == 0 || ty >= (iry - isw) )
+                                                       xferLineBytes(irx - tx, rectlen + 2 * tx, bottomlines, -1);
+                                               else
+                                                       xferLineBytes(irx - tx, isw, bottomlines, iw - irx + tx - isw);
+                                               
+                                               if ( d < 0 )
+                                               {
+                                                       tx++;
+                                                       dx += TwoBsquared;
+                                                       d += dx;
+                                               }
+                                               ty--;
+                                               dy -= TwoAsquared;
+                                               d += Asquared - dy;
+                                       }
+
+                                       // Draw the middle part of the rectangle
+                                       int     midlen = ih - 2 * iry;
+                                       if ( midlen > 0 )
+                                       {
+                                               if ( pass == 0 )
+                                                       xferLineBytes(0, iw, null, -1);
+                                               else
+                                                       xferLineBytes(0, isw, null, iw - isw);
+                                               currentStream.add("\033*b3M");
+                                               for ( int countr = midlen - 1 ; countr > 0 ; countr-- )
+                                                       currentStream.add("\033*b0W");
+                                               currentStream.add("\033*b1M");
+                                       }
+
+                                       // Draw the bottom.
+                                       for ( int countr = bottomlines.size() - 1 ; countr >= 0 ; countr-- )
+                                               currentStream.add((String)bottomlines.elementAt(countr));
+
+                                       // End raster graphics
+                                       currentStream.add("\033*rB");
+                                       // Return to regular print mode.
+                                       currentStream.add("\033*v0t0n0O");
+                               }
+                               pass++;
+                       } while ( pass < 2 );
+               }
+*/
+    }
+
+       // Add a polyline or polygon. Does not support fills yet!!!
+    protected void addPolyline(Vector points, int posx, int posy, PDFColor fc, PDFColor sc, float sw, boolean close)
+    {
+               PathPoint pc;
+       float lastx = 0;
+       float lasty = 0;
+       float curx = 0;
+       float cury = 0;
+       float startx = 0;
+       float starty = 0;
+       Enumeration e = points.elements();
+       if(e.hasMoreElements())
+       {
+               pc = (PathPoint)e.nextElement();
+                       lastx = pc.x + posx / 1000;
+                       lasty = ((pageHeight / 10) - posy/1000) + pc.y;
+                       startx = lastx;
+                       starty = lasty;
+       }
+       while(e.hasMoreElements())
+       {
+               pc = (PathPoint)e.nextElement();
+                       curx = pc.x + posx / 1000;
+                       cury = ((pageHeight / 10) - posy/1000) + pc.y;
+               addLine(lastx, lasty, curx, cury, sc, sw);
+                       lastx = curx;
+                       lasty = cury;
+       }
+       if(close)
+               {
+               addLine(lastx, lasty, startx, starty, sc, sw);
+               }
+    }
+
+       boolean printBMP(FopImage img, int x, int y, int w, int h) throws FopImageException
+       {
+               addRect(x, y, w, h, new PDFColor(1f, 1f, 1f), new PDFColor(0f, 0f, 0f));
+               int     nameh = (int)(h * yFactor / 2);
+               if ( nameh > 0 )
+               {
+                       int     namew = (int)(w * xFactor);
+
+                       if ( namew > 10 )
+                       {
+                               String iname = img.getURL();
+                               if ( iname.length() >= namew )
+                                       addStr((int)((pageHeight - (y / 100))* 100 * yFactor) + nameh, (int)(x * xFactor), iname.substring(namew - iname.length(), namew), true);
+                               else
+                                       addStr((int)((pageHeight - (y / 100))* 100 * yFactor) + nameh, (int)(x * xFactor + (namew - iname.length()) / 2), iname, true);
+
+                       }
+               }
+               return(true);
+       }
+
+    /**
+     * render image area to PCL
+     *
+     * @param area the image area to render
+     */
+    public void renderImageArea(ImageArea area)
+    {
+               int x = this.currentAreaContainerXPosition + area.getXOffset();
+               int y = this.currentYPosition;
+               int w = area.getContentWidth();
+               int h = area.getHeight();
+
+               this.currentYPosition -= h;
+
+               FopImage img = area.getImage();
+
+               try
+               {
+                       printBMP(img, x, y, w, h);
+               }
+               catch ( FopImageException e )
+               {
+                       //e.printStackTrace(System.out);
+                       MessageHandler.errorln("TXTRenderer.renderImageArea() Error printing BMP (" + e.toString() + ").");
+               }
+    }
+
+       public void renderImage(FontState fontState, String href, float x, float y, float width, float height)
+       {
+               try
+               {
+                       if ( href.indexOf(":") == -1 )
+                               href = "file:" + href;
+                       FopImage img = FopImageFactory.Make(href);
+                       if(img != null)
+                       {
+                               if ( img instanceof SVGImage )
+                               {
+                                       SVGSVGElement svg = ((SVGImage)img).getSVGDocument().getRootElement();
+                                       renderSVG(fontState, svg, (int)x * 1000, (int)y * 1000);
+                               }
+                               else
+                               {
+                                       printBMP(img, (int)x, (int)y, (int)width, (int)height);
+                               }
+                       }
+               }
+               catch(Exception e)
+               {
+                       MessageHandler.errorln("could not add image to SVG: " + href);
+               }
+       }
+
+    /** render a foreign object area */
+    public void renderForeignObjectArea(ForeignObjectArea area)
+    {
+        // if necessary need to scale and align the content
+        this.currentXPosition = this.currentXPosition + area.getXOffset();
+        this.currentYPosition = this.currentYPosition;
+        switch (area.getAlign())
+        {
+            case TextAlign.START:
+                break;
+            case TextAlign.END:
+                break;
+            case TextAlign.CENTER:
+            case TextAlign.JUSTIFY:
+                break;
+        }
+        switch (area.getVerticalAlign())
+        {
+            case VerticalAlign.BASELINE:
+                break;
+            case VerticalAlign.MIDDLE:
+                break;
+            case VerticalAlign.SUB:
+                break;
+            case VerticalAlign.SUPER:
+                break;
+            case VerticalAlign.TEXT_TOP:
+                break;
+            case VerticalAlign.TEXT_BOTTOM:
+                break;
+            case VerticalAlign.TOP:
+                break;
+            case VerticalAlign.BOTTOM:
+                break;
+        }
+        // in general the content will not be text
+
+        // align and scale
+
+        switch (area.scalingMethod())
+        {
+            case Scaling.UNIFORM:
+                break;
+            case Scaling.NON_UNIFORM:
+                break;
+        }
+        // if the overflow is auto (default), scroll or visible
+        // then the contents should not be clipped, since this
+        // is considered a printing medium.
+        switch (area.getOverflow())
+        {
+            case Overflow.VISIBLE:
+            case Overflow.SCROLL:
+            case Overflow.AUTO:
+                break;
+            case Overflow.HIDDEN:
+                break;
+        }
+        area.getObject().render(this);
+
+        this.currentXPosition += area.getEffectiveWidth();
+    //    this.currentYPosition -= area.getEffectiveHeight();
+    }
+
+       void renderSVG(FontState fontState, SVGSVGElement svg, int x, int y)
+       {
+/* SVG - Not yet implemented
+               NodeList nl = svg.getChildNodes();
+               for(int count = 0; count < nl.getLength(); count++) {
+                       Node n = nl.item(count);
+                       if(n instanceof SVGElement) {
+                               renderElement(fontState, (SVGElement)n, x, y);
+                       }
+               }
+*/
+       }
+
+    /**
+     * render SVG area to Text
+     *
+     * @param area the SVG area to render
+     */
+       public void renderSVGArea(SVGArea area)
+       {
+if ( debug )
+System.out.println("TXTRenderer.renderSVGArea(" + area + ")");
+               int x = this.currentAreaContainerXPosition;
+               int y = this.currentYPosition;
+               SVGSVGElement svg = area.getSVGDocument().getRootElement();
+               int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000);
+               int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000);
+
+               //currentStream.add("ET\n");
+               /*
+                * Clip to the svg area.
+                * Note: To have the svg overlay (under) a text area then use
+                * an fo:block-container
+                */
+               //currentStream.add("q\n");
+               //currentStream.add(x / 1000f + " " + y / 1000f + " m\n");
+               //currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n");
+               //currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f + " l\n");
+               //currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n");
+               //currentStream.add("h\n");
+               //currentStream.add("W\n");
+               //currentStream.add("n\n");
+               // transform so that the coordinates (0,0) is from the top left
+               // and positive is down and to the right
+               //currentStream.add(1 + " " + 0 + " " + 0 + " " + (-1) + " " + x / 1000f + " " + y / 1000f + " cm\n");
+
+               // TODO - translate and clip to viewbox
+
+               renderSVG(area.getFontState(), svg, x, y);
+
+               //Enumeration e = area.getChildren().elements();
+               //while (e.hasMoreElements()) {
+               //      Object o = e.nextElement();
+               //      if(o instanceof GraphicImpl) {
+               //              renderElement(area, (GraphicImpl)o, x, y);
+               //      }
+               //}
+
+               //currentStream.add("Q\n");
+               //currentStream.add("BT\n");
+               //this.currentYPosition -= h;
+       }
+
+/* SVG - Not yet implemented
+       public void renderElement(FontState fontState, SVGElement area, int posx, int posy)
+       {
+if ( debug )
+System.out.println("TXTRenderer.renderElement(" + fontState + ", " + area + ", " + posx + ", " + posy + ")");
+               int x = posx;
+               int y = posy;
+               CSSStyleDeclaration style = null;
+               if ( area instanceof SVGStylable )
+                       style = ((SVGStylable)area).getStyle();
+               PDFColor fillColour = null;
+               PDFColor strokeColour = null;
+               float strokeWidth = 0;
+
+               //currentStream.add("q\n");
+               //if( area instanceof SVGTransformable )
+               //{
+               //      SVGTransformable tf = (SVGTransformable)area;
+               //      SVGAnimatedTransformList trans = tf.getTransform();
+               //      SVGRect bbox = tf.getBBox();
+               //      if(trans != null) {
+               //              applyTransform(trans, bbox);
+               //      }
+               //}
+
+               if(style != null)
+               {
+                       CSSValue sp = style.getPropertyCSSValue("fill");
+                       if(sp != null)
+                       {
+                               if( sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
+                               {
+                                       if( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_RGBCOLOR )
+                                       {
+                                               RGBColor col = ((CSSPrimitiveValue)sp).getRGBColorValue();
+                                               CSSPrimitiveValue val;
+                                               val = col.getRed();
+                                               float red = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+                                               val = col.getGreen();
+                                               float green = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+                                               val = col.getBlue();
+                                               float blue = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+                                               fillColour = new PDFColor(red, green, blue);
+                                       }
+                               }
+                               //if(sp instanceof ColorType)
+                               //{
+                               //      ColorType ct = (ColorType)sp;
+                               //      fillColour = new PDFColor(ct.red(), ct.green(), ct.blue());
+                               //}
+                       }
+                       else
+                               fillColour = new PDFColor(0, 0, 0);
+                       sp = style.getPropertyCSSValue("stroke");
+                       if(sp != null)
+                       {
+                               if( sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
+                               {
+                                       if( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_RGBCOLOR )
+                                       {
+                                               RGBColor col = ((CSSPrimitiveValue)sp).getRGBColorValue();
+                                               CSSPrimitiveValue val;
+                                               val = col.getRed();
+                                               float red = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+                                               val = col.getGreen();
+                                               float green = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+                                               val = col.getBlue();
+                                               float blue = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+                                               strokeColour = new PDFColor(red, green, blue);
+                                       }
+                               }
+                               //if(sp instanceof ColorType)
+                               //{
+                               //      ColorType ct = (ColorType)sp;
+                               //      strokeColour = new PDFColor(ct.red(), ct.green(), ct.blue());
+                               //}
+                       }
+                       sp = style.getPropertyCSSValue("stroke-width");
+                       if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE)
+                       {
+                       strokeWidth = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
+                               //PDFNumber pdfNumber = new PDFNumber();
+                               //currentStream.add(pdfNumber.doubleOut(width) + " w\n");
+                               //strokeWidth = ((SVGLengthImpl)sp).getValue();
+                       }
+                       else
+                               strokeWidth = 1;
+               }
+
+               if (area instanceof SVGRectElement)
+               {
+                       SVGRectElement rg = (SVGRectElement)area;
+                       float rectx = rg.getX().getBaseVal().getValue() + posx / 1000;
+                       float recty = ((pageHeight / 10) - posy/1000) + rg.getY().getBaseVal().getValue();
+                       float rx = rg.getRx().getBaseVal().getValue();
+                       float ry = rg.getRy().getBaseVal().getValue();
+                       float rw = rg.getWidth().getBaseVal().getValue();
+                       float rh = rg.getHeight().getBaseVal().getValue();
+                       addRect(rectx, recty, rw, rh, rx, ry, fillColour, strokeColour, strokeWidth);
+               }
+               else if (area instanceof SVGLineElement)
+               {
+                       SVGLineElement lg = (SVGLineElement)area;
+                       float x1 = lg.getX1().getBaseVal().getValue() + posx / 1000;
+                       float y1 = ((pageHeight / 10) - posy/1000) + lg.getY1().getBaseVal().getValue();
+                       float x2 = lg.getX2().getBaseVal().getValue() + posx / 1000;
+                       float y2 = ((pageHeight / 10) - posy/1000) + lg.getY2().getBaseVal().getValue();
+                       addLine(x1,y1,x2,y2, strokeColour, strokeWidth);
+               }
+               else if (area instanceof SVGTextElementImpl)
+               {
+                       //currentStream.add("BT\n");
+                       renderText(fontState, (SVGTextElementImpl)area, posx / 1000f, ((float)(pageHeight / 10) - posy/1000f));
+                       //currentStream.add("ET\n");
+               }
+               else if (area instanceof SVGCircleElement)
+               {
+                       SVGCircleElement cg = (SVGCircleElement)area;
+                       float cx = cg.getCx().getBaseVal().getValue() + posx / 1000;
+                       float cy = ((pageHeight / 10) - posy/1000) + cg.getCy().getBaseVal().getValue();
+                       float r = cg.getR().getBaseVal().getValue();
+                       //addCircle(cx,cy,r, di);
+                       addRect(cx - r, cy - r, 2 * r, 2 * r, r, r, fillColour, strokeColour, strokeWidth);
+               }
+               else if (area instanceof SVGEllipseElement)
+               {
+                       SVGEllipseElement cg = (SVGEllipseElement)area;
+                       float cx = cg.getCx().getBaseVal().getValue() + posx / 1000;
+                       float cy = ((pageHeight / 10) - posy/1000) + cg.getCy().getBaseVal().getValue();
+                       float rx = cg.getRx().getBaseVal().getValue();
+                       float ry = cg.getRy().getBaseVal().getValue();
+                       //addEllipse(cx,cy,rx,ry, di);
+                       addRect(cx - rx, cy - ry, 2 * rx, 2 * ry, rx, ry, fillColour, strokeColour, strokeWidth);
+               }
+               else if (area instanceof SVGPathElementImpl)
+               {
+                       //addPath(((SVGPathElementImpl)area).pathElements, posx, posy, di);
+               }
+               else if (area instanceof SVGPolylineElementImpl)
+               {
+                       addPolyline(((SVGPolylineElementImpl)area).points, posx, posy, fillColour, strokeColour, strokeWidth, false);
+               }
+               else if (area instanceof SVGPolygonElementImpl)
+               {
+                       addPolyline(((SVGPolylineElementImpl)area).points, posx, posy, fillColour, strokeColour, strokeWidth, true);
+               }
+               else if (area instanceof SVGGElementImpl)
+               {
+                       renderGArea(fontState, (SVGGElementImpl)area, x, y);
+               }
+               else if(area instanceof SVGUseElementImpl)
+               {
+                       SVGUseElementImpl ug = (SVGUseElementImpl)area;
+                       String ref = ug.link;
+                       ref = ref.substring(1, ref.length());
+                       SVGElement graph = null;
+                       //GraphicImpl graph = null;
+                       //graph = area.locateDef(ref);
+                       if(graph != null) {
+                               // probably not the best way to do this, should be able
+                               // to render without the style being set.
+                               //GraphicImpl parent = graph.getGraphicParent();
+                               //graph.setParent(area);
+                               // need to clip (if necessary) to the use area
+                               // the style of the linked element is as if is was
+                               // a direct descendant of the use element.
+                               renderElement(fontState, graph, posx, posy);
+                               //graph.setParent(parent);
+                       }
+               }
+               else if (area instanceof SVGImageElementImpl)
+               {
+                       SVGImageElementImpl ig = (SVGImageElementImpl)area;
+                       renderImage(fontState, ig.link, ig.x, ig.y, ig.width, ig.height);
+               }
+               else if (area instanceof SVGSVGElement)
+               {
+                       // the x and y pos will be wrong!
+                       renderSVG(fontState, (SVGSVGElement)area, x, y);
+               }
+               else if (area instanceof SVGAElement)
+               {
+                       SVGAElement ael = (SVGAElement)area;
+                       org.w3c.dom.NodeList nl = ael.getChildNodes();
+                       for ( int count = 0 ; count < nl.getLength() ; count++ )
+                       {
+                               org.w3c.dom.Node n = nl.item(count);
+                               if ( n instanceof SVGElement )
+                               {
+                                       if ( n instanceof GraphicElement )
+                                       {
+                                               SVGRect rect = ((GraphicElement)n).getBBox();
+                                               if ( rect != null )
+                                               {
+//                                                     currentAnnotList = this.pdfDoc.makeAnnotList();
+//                                                     currentPage.setAnnotList(currentAnnotList);
+//                                                     String dest = linkSet.getDest();
+//                                                     int linkType = linkSet.getLinkType();
+//                                                     currentAnnotList.addLink(
+//                                                             this.pdfDoc.makeLink(lrect.getRectangle(), dest, linkType));
+//                                                     currentAnnotList = null;
+//                                             }
+                                       }
+                                       renderElement(fontState, (SVGElement)n, posx, posy);
+                               }
+                       }
+               }
+               else if ( area instanceof SVGSwitchElement )
+               {
+                       handleSwitchElement(fontState, posx, posy, (SVGSwitchElement)area);
+               }
+               // should be done with some cleanup code, so only
+               // required values are reset.
+               //currentStream.add("Q\n");
+       }
+*/
+
+       private void setFont(String name, float size)
+       {
+               return;
+       }
+
+/* SVG - Not implemented yet.
+       public void renderText(FontState fontState, SVGTextElementImpl tg, float x, float y)
+       {
+               PDFNumber pdfNumber = new PDFNumber();
+
+               CSSStyleDeclaration styles;
+               styles = tg.getStyle();
+               //applyStyle(tg, styles);
+               // apply transform
+               // text has a Tm and need to handle each element
+               SVGTransformList trans = tg.getTransform().getBaseVal();
+               SVGMatrix matrix = trans.consolidate().getMatrix();
+               String transstr = (pdfNumber.doubleOut(matrix.getA())
+                                                       + " " + pdfNumber.doubleOut(matrix.getB())
+                                                       + " " + pdfNumber.doubleOut(matrix.getC())
+                                                       + " " + pdfNumber.doubleOut(-matrix.getD()) + " ");
+
+               String fontFamily = null;
+               CSSValue sp = styles.getPropertyCSSValue("font-family");
+           if ( sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
+           {
+                   if ( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING )
+                               fontFamily = sp.getCssText();
+           }
+               if ( fontFamily == null )
+                       fontFamily = fontState.getFontFamily();
+               String fontStyle = null;
+               sp = styles.getPropertyCSSValue("font-style");
+           if ( sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
+           {
+                   if ( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING )
+                               fontStyle = sp.getCssText();
+           }
+               if ( fontStyle == null )
+                       fontStyle = fontState.getFontStyle();
+               String fontWeight = null;
+               sp = styles.getPropertyCSSValue("font-weight");
+           if( sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
+           {
+                   if ( ((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING )
+                               fontWeight = sp.getCssText();
+           }
+               if( fontWeight == null )
+                       fontWeight = fontState.getFontWeight();
+               float fontSize;
+               sp = styles.getPropertyCSSValue("font-size");
+           if( sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
+           {
+//                 if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_NUMBER) {
+                               fontSize = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
+//                 }
+           }
+           else
+           {
+                       fontSize = fontState.getFontSize() / 1000f;
+               }
+               FontState fs = fontState;
+               try
+               {
+                       fs = new FontState(fontState.getFontInfo(), fontFamily, fontStyle,
+                                                                       fontWeight, (int)(fontSize * 1000));
+               }
+               catch( Exception fope )
+               {
+//                     fope.printStackTrace();
+               }
+
+               //currentStream.add("/" + fs.getFontName() + " " + fontSize + " Tf\n");
+               setFont(fs.getFontName(), fontSize * 1000);
+
+               float tx = tg.x;
+               float ty = tg.y;
+               float currentX = x + tx;
+               float currentY = y + ty;
+               Vector list = tg.textList;
+               for ( Enumeration e = list.elements() ; e.hasMoreElements() ; )
+               {
+                       Object o = e.nextElement();
+                       styles = tg.getStyle();
+                       //applyStyle(tg, styles);
+                       if( o instanceof String )
+                       {
+                               String str = (String)o;
+                               //currentStream.add(transstr
+                               //      + (currentX + matrix.getE()) + " "
+                               //      + (y+ty + matrix.getF()) + " Tm " 
+                               //      + "(");
+                               boolean spacing = "preserve".equals(tg.getXMLspace());
+                               //currentX = addSVGStr(fs, currentX, str, spacing);
+                               //currentStream.add(") Tj\n");
+//                             for(int count = 0; count < str.length(); count++) {
+//                             }
+//                             currentX += fs.width(' ') / 1000f;
+                               currentStream.add("\033&a" + (currentX + matrix.getE())*10 + "h" + (y+ty + matrix.getF())*10 + "V" + str);
+                               for ( int count = 0; count < str.length(); count++ )
+                               {
+                                       currentX += fs.width(str.charAt(count)) / 1000f;
+                               }
+                               currentX += fs.width(' ') / 1000f;
+                       } else if(o instanceof SVGTextPathElementImpl) {
+                               SVGTextPathElementImpl tpg = (SVGTextPathElementImpl)o;
+                               String ref = tpg.str;
+                               SVGElement graph = null;
+//                             graph = tpg.locateDef(ref);
+                               if(graph != null && graph instanceof SVGPathElementImpl) {
+                                       // probably not the best way to do this, should be able
+                                       // to render without the style being set.
+//                                     GraphicImpl parent = graph.getGraphicParent();
+//                                     graph.setParent(tpg);
+                                       // set text path??
+                                       // how should this work
+//                                     graph.setParent(parent);
+                               }
+                       } else if(o instanceof SVGTRefElementImpl) {
+                               SVGTRefElementImpl trg = (SVGTRefElementImpl)o;
+                               String ref = trg.ref;
+                               ref = ref.substring(1, ref.length());
+                               SVGElement graph = null;
+//                             graph = trg.locateDef(ref);
+                               if(graph != null && graph instanceof SVGTextElementImpl) {
+//                                     GraphicImpl parent = graph.getGraphicParent();
+//                                     graph.setParent(trg);
+                                       SVGTextElementImpl te = (SVGTextElementImpl)graph;
+                                       renderText(fs, te, (int)(x + tx), (int)(y + ty));
+//                                     graph.setParent(parent);
+                               }
+                       } else if(o instanceof SVGTSpanElementImpl) {
+                               SVGTSpanElementImpl tsg = (SVGTSpanElementImpl)o;
+                               styles = tsg.getStyle();
+                               //applyStyle(tsg, styles);
+                               boolean changed = false;
+
+                               String newprop = null;
+                               sp = styles.getPropertyCSSValue("font-family");
+                           if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+                                   if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+                                               newprop = sp.getCssText();
+                                   }
+                           }
+                               if(newprop != null && !newprop.equals(fontFamily)) {
+                                       fontFamily = newprop;
+                                       changed = true;
+                               }
+                               sp = styles.getPropertyCSSValue("font-style");
+                           if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+                                   if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+                                               newprop = sp.getCssText();
+                                   }
+                           }
+                               if(newprop != null && !newprop.equals(fontStyle)) {
+                                       fontStyle = newprop;
+                                       changed = true;
+                               }
+                               sp = styles.getPropertyCSSValue("font-weight");
+                           if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+                                   if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+                                               newprop = sp.getCssText();
+                                   }
+                           }
+                               if(newprop != null && !newprop.equals(fontWeight)) {
+                                       fontWeight = newprop;
+                                       changed = true;
+                               }
+                               float newSize = fontSize;
+                               sp = styles.getPropertyCSSValue("font-size");
+                           if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+//                                 if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_NUMBER) {
+                                               newSize = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
+//                                 }
+                           }
+                               if ( fontSize != newSize )
+                               {
+                                       fontSize = newSize;
+                                       changed = true;
+                               }
+                               FontState oldfs = null;
+                               if ( changed )
+                               {
+                                       oldfs = fs;
+                                       try
+                                       {
+                                               fs = new FontState(fontState.getFontInfo(), fontFamily, fontStyle,
+                                                                                       fontWeight, (int)(fontSize * 1000));
+                                       }
+                                       catch(Exception fope)
+                                       {
+                                       }
+
+                                       setFont(fs.getFontName(), fontSize * 1000);
+                                       //currentStream.add("/" + fs.getFontName() + " " + fontSize + " Tf\n");
+                               }
+
+                               float baseX;
+                               float baseY;
+
+                               StringBuffer pdf = new StringBuffer();
+                               boolean spacing = "preserve".equals(tsg.getXMLspace());
+                               boolean inbetween = false;
+                               boolean addedspace = false;
+                               int charPos = 0;
+                               float xpos = currentX;
+                               float ypos = currentY;
+                               for ( int i=0 ; i < tsg.str.length() ; i++ )
+                               {
+                                       char ch = tsg.str.charAt(i);
+                                       xpos = currentX;
+                                       ypos = currentY;
+                                       if ( tsg.ylist.size() > charPos )
+                                               ypos = y + ty + ((Float)tsg.ylist.elementAt(charPos)).floatValue();
+                                       if ( tsg.dylist.size() > charPos )
+                                               ypos = ypos + ((Float)tsg.dylist.elementAt(charPos)).floatValue();
+                                       if ( tsg.xlist.size() > charPos )
+                                               xpos = x + tx + ((Float)tsg.xlist.elementAt(charPos)).floatValue();
+                                       if ( tsg.dxlist.size() > charPos )
+                                               xpos = xpos + ((Float)tsg.dxlist.elementAt(charPos)).floatValue();
+                                       switch (ch)
+                                       {
+                                               case '  ':
+                                               case ' ':
+                                                   if ( spacing )
+                                                   {
+                                                               currentX = xpos + fs.width(' ') / 1000f;
+                                                               currentY = ypos;
+                                                               charPos++;
+                                                   }
+                                                   else
+                                                   {
+                                                       if ( inbetween && !addedspace)
+                                                       {
+                                                               addedspace = true;
+                                                                       currentX = xpos + fs.width(' ') / 1000f;
+                                                                       currentY = ypos;
+                                                                       charPos++;
+                                                       }
+                                                   }
+                                               break;
+                                               case '\n':
+                                               case '\r':
+                                                   if ( spacing )
+                                                   {
+                                                               currentX = xpos + fs.width(' ') / 1000f;
+                                                               currentY = ypos;
+                                                               charPos++;
+                                                   }
+                                               break;
+                                               default:
+                                               addedspace = false;
+                                                       pdf = pdf.append(transstr
+                                                               + (xpos + matrix.getE()) + " "
+                                                               + (ypos + matrix.getF()) + " Tm " 
+                                                               + "(" + ch + ") Tj\n");
+                                                       pdf = pdf.append("\033&a" + (xpos + matrix.getE())*10 + "h" + (ypos + matrix.getF())*10 + "V" + ch);
+                                                       currentX = xpos + fs.width(ch) / 1000f;
+                                                       currentY = ypos;
+                                                       charPos++;
+                                                       inbetween = true;
+                                               break;
+                               }
+                               //currentStream.add(pdf.toString());
+                               }
+//                             currentX += fs.width(' ') / 1000f;
+                               if ( changed )
+                               {
+                                       fs = oldfs;
+                                       setFont(fs.getFontName(), fs.getFontSize() * 1000);
+                                       //currentStream.add("/" + fs.getFontName() + " " + fs.getFontSize() / 1000f + " Tf\n");
+                               }
+                       }
+                       else
+                       {
+                               System.err.println("Error: unknown text element " + o);
+                       }
+               }
+       }
+*/
+
+/* SVG - Not yet implemented
+       public void renderGArea(FontState fontState, SVGGElement area, int posx, int posy)
+       {
+               NodeList nl = area.getChildNodes();
+               for ( int count = 0 ; count < nl.getLength() ; count++ )
+               {
+                       Node n = nl.item(count);
+                       if ( n instanceof SVGElement )
+                               renderElement(fontState, (SVGElement)n, posx, posy);
+               }
+       }
+*/
+
+/* SVG - Not yet implemented
+       void handleSwitchElement(FontState fontState, int posx, int posy, SVGSwitchElement ael)
+       {
+               SVGList relist = ael.getRequiredExtensions();
+               SVGList rflist = ael.getRequiredFeatures();
+               SVGList sllist = ael.getSystemLanguage();
+               org.w3c.dom.NodeList nl = ael.getChildNodes();
+               for(int count = 0; count < nl.getLength(); count++) {
+                       org.w3c.dom.Node n = nl.item(count);
+                       // only render the first child that has a valid
+                       // test data
+                       if(n instanceof GraphicElement) {
+                               GraphicElement graphic = (GraphicElement)n;
+                               SVGList grelist = graphic.getRequiredExtensions();
+                               // if null it evaluates to true
+                               if(grelist != null) {
+                                       for(int i = 0; i < grelist.getNumberOfItems(); i++) {
+                                               String str = (String)grelist.getItem(i);
+                                               if(relist == null) {
+                                                       // use default extension set
+                                                       // currently no extensions are supported
+//                                                     if(!(str.equals("http:// ??"))) {
+                                                               continue;
+//                                                     }
+                                               } else {
+                                               }
+                                       }
+                               }
+                               SVGList grflist = graphic.getRequiredFeatures();
+                               if(grflist != null) {
+                                       for(int i = 0; i < grflist.getNumberOfItems(); i++) {
+                                               String str = (String)grflist.getItem(i);
+                                               if(rflist == null) {
+                                                       // use default feature set
+                                                       if(!(str.equals("org.w3c.svg.static")
+                                                               || str.equals("org.w3c.dom.svg.all"))) {
+                                                               continue;
+                                                       }
+                                               } else {
+                                                       boolean found = false;
+                                                       for(int j = 0; j < rflist.getNumberOfItems(); j++) {
+                                                               if(rflist.getItem(j).equals(str)) {
+                                                                       found = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                                       if(!found)
+                                                               continue;
+                                               }
+                                       }
+                               }
+                               SVGList gsllist = graphic.getSystemLanguage();
+                               if(gsllist != null) {
+                                       for(int i = 0; i < gsllist.getNumberOfItems(); i++) {
+                                               String str = (String)gsllist.getItem(i);
+                                               if(sllist == null) {
+                                                       // use default feature set
+                                                       if(!(str.equals("en"))) {
+                                                               continue;
+                                                       }
+                                               } else {
+                                                       boolean found = false;
+                                                       for(int j = 0; j < sllist.getNumberOfItems(); j++) {
+                                                               if(sllist.getItem(j).equals(str)) {
+                                                                       found = true;
+                                                                       break;
+                                                               }
+                                                       }
+                                                       if(!found)
+                                                               continue;
+                                               }
+                                       }
+                               }
+                               renderElement(fontState, (SVGElement)n, posx, posy);
+                               // only render the first valid one
+                               break;
+                       }
+               }
+       }
+*/
+
+    /**
+     * render inline area to Text
+     *
+     * @param area inline area to render
+     */
+    public void renderWordArea(WordArea area)
+    {
+//System.out.println("TXTRenderer.renderInlineArea: currentXPosition=" + this.currentXPosition + " currentYPosition=" + this.currentYPosition + " text=" + area.getText());
+               int rx = this.currentXPosition;
+               int bl = this.currentYPosition;
+
+               String s;
+               if ( area.getPageNumberID()!=null )
+               {
+                       // this text is a page number, so resolve it
+                   s = idReferences.getPageNumber(area.getPageNumberID());            
+                   if(s==null)
+                       s="";
+               }
+               else
+               {
+                   s = area.getText();
+               }
+
+if ( debug )
+System.out.println("TXTRenderer.renderInlineArea: rx=" + rx + " bl=" + bl + " pageHeight=" + pageHeight);
+               addStr((int)((pageHeight - (bl / 100))* 100 * yFactor) - 1, (int)(rx * xFactor), s, true);
+
+               this.currentXPosition += area.getContentWidth();
+    }
+
+    /**
+     * render inline space to Text
+     *
+     * @param space space to render
+     */
+    public void renderInlineSpace(InlineSpace space)
+    {
+               this.currentXPosition += space.getSize();
+    }
+
+    /**
+     * render page into Text
+     *
+     * @param page page to render
+     */
+    public void renderPage(Page page)
+    {
+if ( debug )
+System.out.println("TXTRenderer.renderPage() page.getHeight() = " + page.getHeight());
+               BodyAreaContainer body;
+               AreaContainer before, after, start, end;
+
+               maxX = (int)(textCPI * page.getWidth() / 72000 + 1);
+               maxY = (int)(textLPI * page.getHeight() / 72000 + 1);
+               xFactor = (float)(maxX - 1) / (float)page.getWidth();
+               yFactor = (float)(maxY - 1) / (float)page.getHeight();
+               charData = new StringBuffer[maxY + 1];
+               decoData = new StringBuffer[maxY + 1];
+
+               if ( paperheight > 0 )
+                       pageHeight = paperheight;
+               else
+                       pageHeight = page.getHeight() / 100;
+
+if ( debug )
+System.out.println("TXTRenderer.renderPage() maxX=" + maxX + " maxY=" + maxY + " xFactor=" + xFactor + " yFactor=" + yFactor + " paperHeight=" + pageHeight);
+             
+               body = page.getBody();
+               before = page.getBefore();
+               after = page.getAfter();
+               start = page.getStart();
+               end = page.getEnd();
+
+               this.currentFontName = "";
+               this.currentFontSize = 0;
+
+               //currentStream.add("BT\n");
+               renderBodyAreaContainer(body);
+
+               if (before != null)
+                   renderAreaContainer(before);
+
+               if (after != null)
+                   renderAreaContainer(after);
+               
+               if (start != null)
+                   renderAreaContainer(start);
+               
+               if (end != null)
+                   renderAreaContainer(end);
+               
+               // Write out the buffers.
+               for ( int row = 0 ; row <= maxY ; row++ )
+               {
+                       StringBuffer cr = charData[row];
+                       StringBuffer dr = decoData[row];
+                       StringBuffer outr = null;
+
+                       if ( cr != null && dr == null )
+                               outr = cr;
+                       else if ( dr != null && cr == null )
+                               outr = dr;
+                       else if ( cr != null && dr != null )
+                       {
+                               int     len = dr.length();
+                               if ( cr.length() > len )
+                                       len = cr.length();
+                               outr = new StringBuffer();
+                               for ( int countr = 0 ; countr < len ; countr++ )
+                               {
+                                       if ( countr < cr.length() && cr.charAt(countr) != ' ' )
+                                               outr.append(cr.charAt(countr));
+                                       else if ( countr < dr.length() )
+                                               outr.append(dr.charAt(countr));
+                                       else
+                                               outr.append(' ');
+                               }
+                       }
+
+                       if ( outr != null )
+                               currentStream.add(outr.toString());
+                       currentStream.add("\n");
+               }
+
+               // End page.
+               //if ( ++curdiv == divisions || divisions == -1 )
+               //{
+               //      curdiv = 0;
+               //      currentStream.add("\f");
+               //}
+
+               // Links, etc not implemented...
+               /*
+               currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
+                                        page.getWidth()/1000,
+                                        page.getHeight()/1000, page);
+
+               if (page.hasLinks()) {
+                       currentAnnotList = this.pdfDoc.makeAnnotList();
+                       currentPage.setAnnotList(currentAnnotList);
+
+                       Enumeration e = page.getLinkSets().elements();
+                       while (e.hasMoreElements()) {
+                       LinkSet linkSet = (LinkSet) e.nextElement();
+
+                       linkSet.align();
+                       String dest = linkSet.getDest();
+                       int linkType = linkSet.getLinkType();
+                       Enumeration f = linkSet.getRects().elements();
+                       while (f.hasMoreElements()) {
+                               LinkedRectangle lrect = (LinkedRectangle) f.nextElement();
+                               currentAnnotList.addLink(
+                                       this.pdfDoc.makeLink(lrect.getRectangle(), dest, linkType));
+                       }
+                       }
+               } else {
+                       // just to be on the safe side
+                       currentAnnotList = null;
+               }
+               */
+    }
+}