You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ar...@apache.org on 2001/03/10 19:59:45 UTC

cvs commit: xml-fop/src/org/apache/fop/render/txt TXTRenderer.java

arved       01/03/10 10:59:45

  Added:       src/org/apache/fop/render/txt TXTRenderer.java
  Log:
  New files for text rendering
  
  Revision  Changes    Path
  1.1                  xml-fop/src/org/apache/fop/render/txt/TXTRenderer.java
  
  Index: TXTRenderer.java
  ===================================================================
  //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;
  		}
  		*/
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: fop-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: fop-cvs-help@xml.apache.org