aboutsummaryrefslogtreecommitdiffstats
path: root/src/org/apache/fop/render/pcl
diff options
context:
space:
mode:
authorarved <arved@unknown>2001-03-10 18:58:49 +0000
committerarved <arved@unknown>2001-03-10 18:58:49 +0000
commit09076c443ebdb6673a4252be54dbf1b64614df86 (patch)
treebdbe956201e007b0a45033e5ac33cafec7f6a1bc /src/org/apache/fop/render/pcl
parente4b1f19c88cba6f0bf31f3731abed0ac9ef3630e (diff)
downloadxmlgraphics-fop-09076c443ebdb6673a4252be54dbf1b64614df86.tar.gz
xmlgraphics-fop-09076c443ebdb6673a4252be54dbf1b64614df86.zip
New files for PCL rendering
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194146 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/org/apache/fop/render/pcl')
-rwxr-xr-xsrc/org/apache/fop/render/pcl/PCLRenderer.java767
-rwxr-xr-xsrc/org/apache/fop/render/pcl/PCLSVGRenderer.java1394
-rwxr-xr-xsrc/org/apache/fop/render/pcl/PCLStream.java42
3 files changed, 2203 insertions, 0 deletions
diff --git a/src/org/apache/fop/render/pcl/PCLRenderer.java b/src/org/apache/fop/render/pcl/PCLRenderer.java
new file mode 100755
index 000000000..8b5fa657c
--- /dev/null
+++ b/src/org/apache/fop/render/pcl/PCLRenderer.java
@@ -0,0 +1,767 @@
+//package com.eastpoint.chrysalis;
+package org.apache.fop.render.pcl;
+
+// FOP
+import org.apache.fop.render.PrintRenderer;
+import org.apache.fop.messaging.MessageHandler;
+import org.apache.fop.image.ImageArea;
+import org.apache.fop.image.FopImage;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.properties.*;
+import org.apache.fop.datatypes.*;
+import org.apache.fop.pdf.PDFPathPaint;
+import org.apache.fop.pdf.PDFColor;
+import org.apache.fop.layout.*;
+import org.apache.fop.layout.inline.*;
+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;
+
+/**
+ * Renderer that renders areas to PCL
+
+ Created by Arthur E Welch III while at M&I EastPoint Technology
+ Donated by EastPoint to the Apache FOP project March 2, 2001.
+ */
+public class PCLRenderer extends PrintRenderer
+{
+ /** the current stream to add PCL commands to */
+ public PCLStream currentStream;
+
+ private int pageHeight = 7920;
+
+ // These variables control the virtual paggination functionality.
+ public int curdiv = 0;
+ private int divisions = -1;
+ public 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;
+ private final boolean debug = false;
+
+ private int xoffset = -180; // X Offset to allow for PCL implicit 1/4" left margin.
+
+ /**
+ * Create the PCL renderer
+ */
+ public PCLRenderer()
+ {
+ }
+
+ /**
+ * set the PCL document's producer
+ *
+ * @param producer string indicating application producing PCL
+ */
+ public void setProducer(String producer)
+ {
+ }
+
+ /**
+ * render the areas into PCL
+ *
+ * @param areaTree the laid-out area tree
+ * @param stream the Outputstream to write the PCL to
+ */
+ public void render(AreaTree areaTree, OutputStream stream) throws IOException, FOPException
+ {
+ MessageHandler.logln("rendering areas to PCL");
+ idReferences=areaTree.getIDReferences();
+ //this.pdfResources = this.pdfDoc.getResources();
+ //this.pdfDoc.setIDReferences(idReferences);
+ Enumeration e = areaTree.getPages().elements();
+
+ currentStream = new PCLStream(stream);
+
+ // Set orientation.
+ if ( orientation > -1 )
+ currentStream.add("\033&l" + orientation + "O");
+ else
+ currentStream.add("\033&l0O");
+ if ( orientation == 1 || orientation == 3 )
+ xoffset = -144;
+ else
+ xoffset = -180;
+
+ // Reset the margins.
+ currentStream.add("\033" + "9\033&l0E");
+
+
+ while (e.hasMoreElements())
+ {
+ 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 PCL");
+ stream.flush();
+ }
+
+ /**
+ * 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)
+ {
+ int dashon = 0;
+ int dashoff = 0;
+ //if ( rs != null && rs.length() > 5 && rs.charAt(0) == '[' && rs.charAt(1) != ']' && rs.charAt(4) == ']' )
+ //{
+ // dashon = rs.charAt(1) - '0';
+ // dashoff = rs.charAt(3) - '0';
+ //}
+ switch (rs)
+ {
+ case org.apache.fop.fo.properties.RuleStyle.DASHED:
+ dashon = 3;
+ dashoff = 3;
+ break;
+ case org.apache.fop.fo.properties.RuleStyle.DOTTED:
+ dashon = 1;
+ dashoff = 3;
+ break;
+ }
+ if ( x1 == x2 )
+ {
+ if ( dashon > 0 && dashoff > 0 )
+ {
+ int start = y1;
+ int len = th * dashon;
+ while ( start < y2 )
+ {
+ if ( start + len > y2 )
+ len = y2 - start;
+ addRect(x1, start, th, len, stroke, stroke);
+ start += (len + dashoff * th);
+ }
+ }
+ else
+ addRect(x1, y1, th, y2 - y1 + 1, stroke, stroke);
+ }
+ else if ( y1 == y2 )
+ {
+ if ( dashon > 0 && dashoff > 0 )
+ {
+ int start = x1;
+ int len = th * dashon;
+ while ( start < x2 )
+ {
+ if ( start + len > x2 )
+ len = x2 - start;
+ addRect(start, y1, len, th, stroke, stroke);
+ start += (len + dashoff * th);
+ }
+ }
+ else
+ addRect(x1, y1, x2 - x1 + 1, th, stroke, stroke);
+ }
+ }
+
+ /**
+ * 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)
+ {
+ if ((w == 0) || (h == 0))
+ return;
+ if ( h < 0 )
+ h *= -1;
+
+ 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));
+
+ int xpos = xoffset + (x / 100);
+ if ( xpos < 0 )
+ {
+ xpos = 0;
+ MessageHandler.errorln("PCLRenderer.addRect() WARNING: Horizontal position out of bounds.");
+ }
+
+ currentStream.add("\033*v1O\033&a" + xpos + "h" + (pageHeight - (y / 100)) + "V"
+ + "\033*c" + (w / 100) + "h" + (h / 100) + "V"
+ + "\033*c" + lineshade + "G"
+ + "\033*c2P");
+ if ( fillshade != lineshade && (w >= 720 || h >= 720) )
+ {
+ xpos = xoffset + ((x + 240) / 100);
+ if ( xpos < 0 )
+ {
+ xpos = 0;
+ MessageHandler.errorln("PCLRenderer.addRect() WARNING: Horizontal position out of bounds.");
+ }
+ currentStream.add("\033&a" + xpos + "h" + (pageHeight - ((y + 240)) / 100) + "V"
+ + "\033*c" + ((w - 480) / 100) + "h" + ((h - 480) / 100) + "V"
+ + "\033*c" + fillshade + "G"
+ + "\033*c2P");
+ }
+ // Reset pattern transparency mode.
+ currentStream.add("\033*v0O");
+ }
+
+ boolean printBMP(FopImage img, int x, int y, int w, int h) throws FopImageException
+ {
+ // Print the passed image file in PCL.
+ byte imgmap[] = img.getBitmaps();
+
+ int ix = 0;
+ int iy = 0;
+ int indx = 0;
+ int iw = img.getWidth();
+ int ih = img.getHeight();
+ int bytewidth = (iw / 8);
+ if ( (iw % 8) != 0 )
+ bytewidth++;
+ byte ib;
+ char ic[] = new char[bytewidth * 2];
+ char icu[] = new char[bytewidth];
+ int lastcount = -1;
+ byte lastbyte = 0;
+ int icwidth = 0;
+ int cr = 0;
+ int cg = 0;
+ int cb = 0;
+ int grey = 0;
+ boolean iscolor = img.getColorSpace().getColorSpace() != ColorSpace.DEVICE_GRAY;
+ int dcount = 0;
+ int xres = (iw * 72000) / w;
+ int yres = (ih * 72000) / h;
+ int resolution = xres;
+ if ( yres > xres )
+ resolution = yres;
+
+ if ( resolution > 300 )
+ resolution = 600;
+ else if ( resolution > 150 )
+ resolution = 300;
+ else if ( resolution > 100 )
+ resolution = 150;
+ else if ( resolution > 75 )
+ resolution = 100;
+ else
+ resolution = 75;
+if ( debug )
+System.out.println("PCLRenderer.printBMP() iscolor = " + iscolor);
+ // Setup for graphics
+ currentStream.add("\033*t" + resolution + "R\033*r0F\033*r1A");
+
+ // Transfer graphics data
+ for ( iy = 0 ; iy < ih ; iy++ )
+ {
+ ib = 0;
+ //int padding = iw % 8;
+ //if ( padding != 0 )
+ // padding = 8 - padding;
+ //padding = 0;
+ //indx = (ih - iy - 1 + padding) * iw;
+ indx = iy * iw;
+ if ( iscolor )
+ indx *= 3;
+ //currentStream.add("\033*b" + bytewidth + "W");
+ for ( ix = 0 ; ix < iw ; ix++ )
+ {
+ if ( iscolor )
+ {
+ cr = imgmap[indx++] & 0xFF;
+ cg = imgmap[indx++] & 0xFF;
+ cb = imgmap[indx++] & 0xFF;
+ grey = (cr * 30 + cg * 59 + cb * 11) / 100;
+ }
+ else
+ grey = imgmap[indx++] & 0xFF;
+ if ( grey < 128 )
+ ib |= (1 << (7 - (ix % 8)));
+ if ( (ix % 8) == 7 || ((ix + 1) == iw))
+ {
+ if ( icwidth < bytewidth )
+ {
+ if ( lastcount >= 0 )
+ {
+ if ( ib == lastbyte )
+ lastcount++;
+ else
+ {
+ ic[icwidth++] = (char)(lastcount & 0xFF);
+ ic[icwidth++] = (char)lastbyte;
+ lastbyte = ib;
+ lastcount = 0;
+ }
+ }
+ else
+ {
+ lastbyte = ib;
+ lastcount = 0;
+ }
+ if ( lastcount == 255 || ((ix + 1) == iw) )
+ {
+ ic[icwidth++] = (char)(lastcount & 0xFF);
+ ic[icwidth++] = (char)lastbyte;
+ lastbyte = 0;
+ lastcount = -1;
+ }
+ }
+ icu[ix / 8] = (char)ib;
+ ib = 0;
+ }
+ }
+ if ( icwidth < bytewidth )
+ {
+ currentStream.add("\033*b1m" + icwidth + "W");
+ currentStream.add(new String(ic, 0, icwidth));
+ }
+ else
+ {
+ currentStream.add("\033*b0m" + bytewidth + "W");
+ currentStream.add(new String(icu));
+ }
+ lastcount = -1;
+ icwidth = 0;
+ }
+
+ // End graphics
+ currentStream.add("\033*rB");
+
+
+ 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();
+
+ int xpos = xoffset + (x / 100);
+ if ( xpos < 0 )
+ {
+ xpos = 0;
+ MessageHandler.errorln("PCLRenderer.renderImageArea() WARNING: Horizontal position out of bounds.");
+ }
+
+ currentStream.add("\033&a" + xpos + "h" + (pageHeight - (y / 100)) + "V");
+
+ try
+ {
+ printBMP(img, x, y, w, h);
+ }
+ catch ( FopImageException e )
+ {
+ //e.printStackTrace(System.out);
+ MessageHandler.errorln("PCLRenderer.renderImageArea() Error printing BMP (" + e.toString() + ")");
+ }
+ }
+
+ /** 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();
+ }
+
+ /**
+ * render SVG area to PCL
+ *
+ * @param area the SVG area to render
+ */
+ public void renderSVGArea(SVGArea area)
+ {
+if ( debug )
+System.out.println("PCLRenderer.renderSVGArea(" + area + ")");
+ int x = this.currentXPosition;
+ 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);
+
+ /*
+ * Clip to the svg area.
+ * Note: To have the svg overlay (under) a text area then use
+ * an fo:block-container
+ */
+
+ // TODO - translate and clip to viewbox
+
+ PCLSVGRenderer svgRenderer =
+ new PCLSVGRenderer(this, area.getFontState(), currentFontName, currentFontSize, currentXPosition, currentYPosition, pageHeight, xoffset);
+ svgRenderer.renderSVG(svg, x, y);
+ //currentStream.add(svgRenderer.getString());
+
+ //currentStream.add("Q\n");
+ }
+
+ public void setFont(String name, float size)
+ {
+ int fontcode = 0;
+ if ( name.length() > 1 && name.charAt(0) == 'F' )
+ {
+ try
+ {
+ fontcode = Integer.parseInt(name.substring(1));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ switch (fontcode)
+ {
+ case 1: // F1 = Helvetica
+ //currentStream.add("\033(8U\033(s1p" + (size / 1000) + "v0s0b24580T");
+ // Arial is more common among PCL5 printers than Helvetica - so use Arial
+ currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v0s0b16602T");
+ break;
+ case 2: // F2 = Helvetica Oblique
+ currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v1s0b16602T");
+ break;
+ case 3: // F3 = Helvetica Bold
+ currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v0s3b16602T");
+ break;
+ case 4: // F4 = Helvetica Bold Oblique
+ currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v1s3b16602T");
+ break;
+ case 5: // F5 = Times Roman
+ //currentStream.add("\033(8U\033(s1p" + (size / 1000) + "v0s0b25093T");
+ // Times New is more common among PCL5 printers than Times - so use Times New
+ currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v0s0b16901T");
+ break;
+ case 6: // F6 = Times Italic
+ currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v1s0b16901T");
+ break;
+ case 7: // F7 = Times Bold
+ currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v0s3b16901T");
+ break;
+ case 8: // F8 = Times Bold Italic
+ currentStream.add("\033(0N\033(s1p" + (size / 1000) + "v1s3b16901T");
+ break;
+ case 9: // F9 = Courier
+ currentStream.add("\033(0N\033(s0p" + (120.01f / (size / 1000.00f)) + "h0s0b4099T");
+ break;
+ case 10: // F10 = Courier Oblique
+ currentStream.add("\033(0N\033(s0p" + (120.01f / (size / 1000.00f)) + "h1s0b4099T");
+ break;
+ case 11: // F11 = Courier Bold
+ currentStream.add("\033(0N\033(s0p" + (120.01f / (size / 1000.00f)) + "h0s3b4099T");
+ break;
+ case 12: // F12 = Courier Bold Oblique
+ currentStream.add("\033(0N\033(s0p" + (120.01f / (size / 1000.00f)) + "h1s3b4099T");
+ break;
+ case 13: // F13 = Symbol
+ currentStream.add("\033(19M\033(s1p" + (size / 1000) + "v0s0b16686T");
+ //currentStream.add("\033(9U\033(s1p" + (size / 1000) + "v0s0b25093T"); // ECMA Latin 1 Symbol Set in Times Roman???
+ break;
+ case 14: // F14 = Zapf Dingbats
+ currentStream.add("\033(14L\033(s1p" + (size / 1000) + "v0s0b45101T");
+ break;
+ default:
+ currentStream.add("\033(0N\033(s" + (size / 1000) + "V");
+ break;
+ }
+ }
+
+ /**
+ * render inline area to PCL
+ *
+ * @param area inline area to render
+ */
+ public void renderWordArea(WordArea area)
+ {
+ String name = area.getFontState().getFontName();
+ int size = area.getFontState().getFontSize();
+
+ float red = area.getRed();
+ float green = area.getGreen();
+ float blue = area.getBlue();
+ PDFColor theAreaColor = new PDFColor((double) area.getRed(),
+ (double) area.getGreen(), (double) area.getBlue());
+
+ //currentStream.add("\033*c" + (int)(100 - ((0.3f * red + 0.59f * green + 0.11f * blue) * 100f)) + "G\033*v2T");
+ currentStream.add("\033*v1O\033*c" + (int)(100 - ((0.3f * red + 0.59f * green + 0.11f * blue) * 100f)) + "G\033*v2T");
+
+ if ((!name.equals(this.currentFontName)) || (size != this.currentFontSize))
+ {
+ this.currentFontName = name;
+ this.currentFontSize = size;
+ setFont(name, size);
+ }
+
+ this.currentFill = theAreaColor;
+
+ 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();
+ }
+
+ addWordLines(area, rx, bl, size, theAreaColor);
+
+ int xpos = xoffset + (rx / 100);
+ if ( xpos < 0 )
+ {
+ xpos = 0;
+ MessageHandler.errorln("PCLRenderer.renderWordArea() WARNING: Horizontal position out of bounds.");
+ }
+ currentStream.add("\033&a" + xpos + "h" + (pageHeight - (bl / 100)) + "V" + s);
+
+ this.currentXPosition += area.getContentWidth();
+ }
+
+ /**
+ * render page into PCL
+ *
+ * @param page page to render
+ */
+ public void renderPage(Page page)
+ {
+if ( debug )
+System.out.println("PCLRenderer.renderPage() page.Height() = " + page.getHeight());
+ BodyAreaContainer body;
+ AreaContainer before, after, start, end;
+
+ if ( paperheight > 0 && divisions == -1 )
+ divisions = paperheight / (page.getHeight() / 100);
+
+if ( debug )
+System.out.println("PCLRenderer.renderPage() paperheight=" + paperheight + " divisions=" + divisions);
+
+ // Set top margin.
+ //float fullmargin = 0;
+ if ( divisions > 0 )
+ fullmargin = paperheight * curdiv / divisions;
+ if ( topmargin > 0 )
+ fullmargin += topmargin;
+if ( debug )
+System.out.println("PCLRenderer.renderPage() curdiv=" + curdiv + " fullmargin=" + fullmargin);
+ //if ( fullmargin > 0 )
+ // currentStream.add("\033&l" + (fullmargin / 15f) + "c1e8C");
+ //this.currentYPosition = fullmargin * 100;
+
+ if ( paperheight > 0 )
+ pageHeight = (paperheight / divisions) + fullmargin;
+ else
+ pageHeight = page.getHeight() / 100;
+if ( debug )
+System.out.println("PCLRenderer.renderPage() Set currentYPosition=" + this.currentYPosition);
+ if ( leftmargin > 0 && curdiv == 0 )
+ currentStream.add("\033&k" + (leftmargin / 6f) + "H\033&a1L\033&k12H");
+
+ body = page.getBody();
+ before = page.getBefore();
+ after = page.getAfter();
+ start = page.getStart();
+ end = page.getEnd();
+
+ this.currentFontName = "";
+ this.currentFontSize = 0;
+
+ renderBodyAreaContainer(body);
+
+ if (before != null)
+ renderAreaContainer(before);
+
+ if (after != null)
+ renderAreaContainer(after);
+
+ if (start != null)
+ renderAreaContainer(start);
+
+ if (end != null)
+ renderAreaContainer(end);
+
+ // 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;
+ }
+ */
+ }
+}
diff --git a/src/org/apache/fop/render/pcl/PCLSVGRenderer.java b/src/org/apache/fop/render/pcl/PCLSVGRenderer.java
new file mode 100755
index 000000000..e1e194d86
--- /dev/null
+++ b/src/org/apache/fop/render/pcl/PCLSVGRenderer.java
@@ -0,0 +1,1394 @@
+//package com.eastpoint.chrysalis;
+package org.apache.fop.render.pcl;
+
+// FOP
+import org.apache.fop.messaging.MessageHandler;
+import org.apache.fop.fo.properties.*;
+import org.apache.fop.svg.PathPoint;
+import org.apache.fop.pdf.PDFColor;
+import org.apache.fop.layout.*;
+import org.apache.fop.image.*;
+
+import org.w3c.dom.*;
+import org.w3c.dom.svg.*;
+import org.w3c.dom.css.*;
+
+import org.apache.fop.dom.svg.*;
+
+// Java
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * Renderer that renders SVG to PCL
+ */
+public class PCLSVGRenderer
+{
+ FontState fontState;
+
+ /** the current stream to add PCL commands to */
+ PCLStream currentStream;
+
+ /** the current (internal) font name */
+ protected String currentFontName;
+
+ /** the current font size in millipoints */
+ protected int currentFontSize;
+
+ /** the current vertical position in millipoints from bottom */
+ protected int currentYPosition = 0;
+
+ /** the current horizontal position in millipoints from left */
+ protected int currentXPosition = 0;
+
+ /** the current colour for use in svg */
+ private PDFColor currentColour = new PDFColor(0, 0, 0);
+
+ private PCLRenderer renderer;
+
+ final boolean debug = false;
+
+ private int pageHeight;
+ private int rendxoffset;
+
+ /**
+ * create the SVG renderer
+ */
+ public PCLSVGRenderer(PCLRenderer rend, FontState fs, String font, int size, int xpos, int ypos, int ph, int xo)
+ {
+ renderer = rend;
+ currentFontName = font;
+ currentFontSize = size;
+ currentYPosition = ypos;
+ currentXPosition = xpos;
+ fontState = fs;
+
+ currentStream = rend.currentStream;
+
+ pageHeight = ph;
+ rendxoffset = xo;
+ }
+
+ /**
+ * Renders an SVG element in an SVG document.
+ * This renders each of the child elements.
+ */
+ protected void renderSVG(SVGSVGElement svg, int x, int y) {
+ NodeList nl = svg.getChildNodes();
+ for (int count = 0; count < nl.getLength(); count++) {
+ Node n = nl.item(count);
+ if (n instanceof SVGElement) {
+ renderElement((SVGElement) n, x, y);
+ }
+ }
+ }
+
+ public void renderGArea(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((SVGElement) n, posx, posy);
+ }
+ }
+ }
+
+ /**
+ * Handles the SVG switch element.
+ * The switch determines which of its child elements should be rendered
+ * according to the required extensions, required features and system language.
+ */
+ protected void handleSwitchElement(int posx, int posy,
+ SVGSwitchElement ael) {
+ SVGStringList relist = ael.getRequiredExtensions();
+ SVGStringList rflist = ael.getRequiredFeatures();
+ SVGStringList sllist = ael.getSystemLanguage();
+ NodeList nl = ael.getChildNodes();
+ choices:
+ 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;
+ SVGStringList grelist = graphic.getRequiredExtensions();
+ // if null it evaluates to true
+ if (grelist != null) {
+ if (grelist.getNumberOfItems() == 0) {
+ if ((relist != null) &&
+ relist.getNumberOfItems() != 0) {
+ continue choices;
+ }
+ }
+ 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 choices;
+ // }
+ } else {
+ }
+ }
+ }
+ SVGStringList grflist = graphic.getRequiredFeatures();
+ if (grflist != null) {
+ if (grflist.getNumberOfItems() == 0) {
+ if ((rflist != null) &&
+ rflist.getNumberOfItems() != 0) {
+ continue choices;
+ }
+ }
+ 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 choices;
+ }
+ } else {
+ boolean found = false;
+ for (int j = 0;
+ j < rflist.getNumberOfItems(); j++) {
+ if (rflist.getItem(j).equals(str)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue choices;
+ }
+ }
+ }
+ SVGStringList gsllist = graphic.getSystemLanguage();
+ if (gsllist != null) {
+ if (gsllist.getNumberOfItems() == 0) {
+ if ((sllist != null) &&
+ sllist.getNumberOfItems() != 0) {
+ continue choices;
+ }
+ }
+ 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 choices;
+ }
+ } else {
+ boolean found = false;
+ for (int j = 0;
+ j < sllist.getNumberOfItems(); j++) {
+ if (sllist.getItem(j).equals(str)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ continue choices;
+ }
+ }
+ }
+ renderElement((SVGElement) n, posx, posy);
+ // only render the first valid one
+ break;
+ }
+ }
+ }
+
+ protected void addLine(float x1, float y1, float x2, float y2, PDFColor sc, float sw)
+ {
+if ( debug )
+System.out.println("PCLSVGRenderer.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 )
+ {
+ // Do something for these?
+
+ // Convert dimensions to pixels.
+ float cfact = 300f / 72f; // 300 dpi, 1pt=1/72in
+ int ix1 = (int)(x1 * cfact);
+ int iy1 = (int)(y1 * cfact);
+ int ix2 = (int)(x2 * cfact);
+ int iy2 = (int)(y2 * cfact);
+ int isw = (int)(sw * cfact);
+ 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("PCLRenderer.addLine(" + ix1 + ", " + iy1 + ", " + ix2 + ", " + iy2 + ", " + isw + ")");
+ int runlen = (int)Math.sqrt(Math.pow(isw, 2) * (1 + Math.pow((ix1 - ix2) / (iy1 - iy2), 2)));
+//System.out.println("PCLRenderer.addLine: runlen = " + runlen);
+
+ // Set Transparency modes and select shading.
+ currentStream.add("\033*v0n1O\033*c" + (int)(100 - ((0.3f * sc.red() + 0.59f * sc.green() + 0.11f * sc.blue()) * 100f)) + "G\033*v2T");
+
+ // 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 ( origix < 0 )
+ MessageHandler.errorln("PCLSVGRenderer.addLine() WARNING: Horizontal position out of bounds.");
+
+ 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)
+ {
+//System.out.println("PCLRenderer.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 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)
+ {
+if ( debug )
+System.out.println("PCLSVGRenderer.addRect(" + x + ", " + y + ", " + w + ", " + h + ", " + rx + ", " + ry + ", " + fc + ", " + sc + ", " + sw + ")");
+
+ if ( x < 0 || y < 0 )
+ MessageHandler.errorln("PCLSVGRenderer.addRect() WARNING: Position out of bounds.");
+
+ 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 = rendxoffset / 10 + pc.x + posx / 1000;
+ lasty = ((pageHeight / 10) - posy/1000) + pc.y;
+ startx = lastx;
+ starty = lasty;
+ //currentStream.add(lastx + " " + lasty + " m\n");
+ }
+ while(e.hasMoreElements())
+ {
+ pc = (PathPoint)e.nextElement();
+ curx = rendxoffset / 10 + pc.x + posx / 1000;
+ cury = ((pageHeight / 10) - posy/1000) + pc.y;
+ addLine(lastx, lasty, curx, cury, sc, sw);
+ lastx = curx;
+ lasty = cury;
+ //currentStream.add(lastx + " " + lasty + " l\n");
+ }
+ if(close)
+ {
+ addLine(lastx, lasty, startx, starty, sc, sw);
+ //currentStream.add("h\n");
+ }
+ //doDrawing(di);
+ }
+
+ public void renderImage(String href, float x, float y, float width, float height)
+ {
+ if ( x < 0 || y < 0 )
+ MessageHandler.errorln("PCLSVGRenderer.renderImage() WARNING: Position out of bounds.");
+
+ 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(svg, (int)x * 1000, (int)y * 1000);
+ }
+ else
+ {
+ currentStream.add("\033&a" + (x * 10) + "h" + (y * 10) + "V");
+ renderer.printBMP(img, (int)x, (int)y, (int)width, (int)height);
+ }
+
+ }
+ }
+ catch(Exception e)
+ {
+ MessageHandler.errorln("could not add image to SVG: " + href);
+ }
+ }
+
+ /**
+ * A symbol has a viewbox and preserve aspect ratio.
+ */
+ protected void renderSymbol(SVGSymbolElement symbol, int x, int y) {
+ NodeList nl = symbol.getChildNodes();
+ for (int count = 0; count < nl.getLength(); count++) {
+ Node n = nl.item(count);
+ if (n instanceof SVGElement) {
+ renderElement((SVGElement) n, x, y);
+ }
+ }
+ }
+
+ /**
+ * Main rendering selection.
+ * This applies any transform ans style and then calls the appropriate
+ * rendering method depending on the type of the element.
+ */
+ public void renderElement(SVGElement area, int posx, int posy)
+ {
+if ( debug )
+System.out.println("PCLRenderer.renderElement(" + fontState + ", " + area + ", " + posx + ", " + posy + ")");
+ int x = posx;
+ int y = posy;
+ SVGStylable style = null;
+ if ( area instanceof SVGStylable )
+ style = (SVGStylable)area;
+ PDFColor fillColour = null;
+ PDFColor strokeColour = null;
+ float strokeWidth = 1;
+
+ //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;
+ sp = style.getPresentationAttribute("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);
+ currentColour = fillColour;
+ }
+ else if ( ((CSSPrimitiveValue) sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING)
+ {
+ String str = ((CSSPrimitiveValue) sp).getCssText();
+ if ( str.equals("none") )
+ {
+ fillColour = null;
+ }
+ else if ( str.equals("currentColor") )
+ {
+ fillColour = currentColour;
+ }
+ }
+ }
+ }
+ else
+ {
+ fillColour = new PDFColor(0, 0, 0);
+ }
+ sp = style.getPresentationAttribute("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);
+ }
+ else if ( ((CSSPrimitiveValue) sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING )
+ {
+ String str = ((CSSPrimitiveValue) sp).getCssText();
+ if (str.equals("none"))
+ {
+ strokeColour = null;
+ }
+ }
+ }
+ }
+ else
+ {
+ strokeColour = new PDFColor(0, 0, 0);
+ }
+ sp = style.getPresentationAttribute("stroke-width");
+ if ( sp != null )
+ {
+ if ( sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE )
+ {
+ strokeWidth = ((CSSPrimitiveValue) sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
+ }
+ }
+ }
+
+ if (area instanceof SVGRectElement)
+ {
+ SVGRectElement rg = (SVGRectElement)area;
+ float rectx = rendxoffset / 10 + 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 = rendxoffset / 10 + lg.getX1().getBaseVal().getValue() + posx / 1000;
+ float y1 = ((pageHeight / 10) - posy/1000) + lg.getY1().getBaseVal().getValue();
+ float x2 = rendxoffset / 10 + 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((SVGTextElementImpl)area, rendxoffset + posx / 1000f, ((float)(pageHeight / 10) - posy/1000f));
+ //currentStream.add("ET\n");
+ SVGTextRenderer str = new SVGTextRenderer(fontState, (SVGTextElementImpl)area, rendxoffset / 10 + posx / 1000f, ((float)(pageHeight / 10) - posy/1000f));
+ str.renderText((SVGTextElementImpl)area);
+ }
+ else if (area instanceof SVGCircleElement)
+ {
+ SVGCircleElement cg = (SVGCircleElement)area;
+ float cx = rendxoffset / 10 + 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 = rendxoffset / 10 + 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((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;
+ graph = locateDef(ref, ug);
+ if (graph != null) {
+ // probably not the best way to do this, should be able
+ // to render without the style being set.
+ // SVGElement parent = graph.getGraphicParent();
+ // graph.setParent(area);
+ // need to clip (if necessary) to the use area
+ // the style of the linked element is as if it was
+ // a direct descendant of the use element.
+
+ // scale to the viewBox
+
+ if (graph instanceof SVGSymbolElement) {
+ //currentStream.write("q\n");
+ SVGSymbolElement symbol = (SVGSymbolElement) graph;
+ SVGRect view = symbol.getViewBox().getBaseVal();
+ float usex = ug.getX().getBaseVal().getValue();
+ float usey = ug.getY().getBaseVal().getValue();
+ float usewidth = ug.getWidth().getBaseVal().getValue();
+ float useheight =
+ ug.getHeight().getBaseVal().getValue();
+ float scaleX;
+ float scaleY;
+ scaleX = usewidth / view.getWidth();
+ scaleY = useheight / view.getHeight();
+ //currentStream.write(usex + " " + usey + " m\n");
+ //currentStream.write((usex + usewidth) + " " +
+ // usey + " l\n");
+ //currentStream.write((usex + usewidth) + " " +
+ // (usey + useheight) + " l\n");
+ //currentStream.write(usex + " " +
+ // (usey + useheight) + " l\n");
+ //currentStream.write("h\n");
+ //currentStream.write("W\n");
+ //currentStream.write("n\n");
+ //currentStream.write(scaleX + " 0 0 " + scaleY +
+ // " " + usex + " " + usey + " cm\n");
+ renderSymbol(symbol, posx, posy);
+ //currentStream.write("Q\n");
+ } else {
+ renderElement(graph, posx, posy);
+ }
+ // graph.setParent(parent);
+ }
+ else
+ {
+ MessageHandler.logln("Use Element: " + ref + " not found");
+ }
+ }
+ else if (area instanceof SVGImageElementImpl)
+ {
+ SVGImageElementImpl ig = (SVGImageElementImpl)area;
+ renderImage(ig.link, ig.x, ig.y, ig.width, ig.height);
+ }
+ else if (area instanceof SVGSVGElement)
+ {
+ //currentStream.write("q\n");
+ SVGSVGElement svgel = (SVGSVGElement) area;
+ float svgx = 0;
+ if (svgel.getX() != null)
+ svgx = svgel.getX().getBaseVal().getValue();
+ float svgy = 0;
+ if (svgel.getY() != null)
+ svgy = svgel.getY().getBaseVal().getValue();
+ //currentStream.write(1 + " 0 0 " + 1 + " " + svgx + " " +
+ // svgy + " cm\n");
+ renderSVG(svgel, (int)(x + 1000 * svgx),
+ (int)(y + 1000 * svgy));
+ //currentStream.write("Q\n");
+ // } else if (area instanceof SVGSymbolElement) {
+ // 'symbol' element is not rendered (except by 'use')
+ }
+ 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((SVGElement)n, posx, posy);
+ }
+ }
+ }
+ else if ( area instanceof SVGSwitchElement )
+ {
+ handleSwitchElement(posx, posy, (SVGSwitchElement)area);
+ }
+ // should be done with some cleanup code, so only
+ // required values are reset.
+ //currentStream.add("Q\n");
+ }
+
+ /**
+ * Adds an svg string to the output.
+ * This handles the escaping of special pdf chars and deals with
+ * whitespace.
+ */
+ protected float addSVGStr(FontState fs, float currentX, String str,
+ boolean spacing) {
+ boolean inbetween = false;
+ boolean addedspace = false;
+ StringBuffer pdf = new StringBuffer();
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ switch (ch)
+ {
+ case '\t':
+ case ' ':
+ if (spacing) {
+ pdf = pdf.append(' ');
+ currentX += fs.width(' ') / 1000f;
+ } else {
+ if (inbetween && !addedspace) {
+ addedspace = true;
+ pdf = pdf.append(' ');
+ currentX += fs.width(' ') / 1000f;
+ }
+ }
+ break;
+ case '\n':
+ case '\r':
+ if (spacing) {
+ pdf = pdf.append(' ');
+ currentX += fs.width(' ') / 1000f;
+ }
+ break;
+ default:
+ addedspace = false;
+ pdf = pdf.append(ch);
+ currentX += fs.width(ch) / 1000f;
+ inbetween = true;
+ break;
+ }
+ }
+ currentStream.add(pdf.toString());
+ return currentX;
+ }
+
+ /**
+ * Locates a defined element in an svg document.
+ * Either gets the element defined by its "id" in the current
+ * SVGDocument, or if the uri reference is to an external
+ * document it loads the document and returns the element.
+ */
+ protected SVGElement locateDef(String ref, SVGElement currentElement) {
+ int pos;
+ ref = ref.trim();
+ pos = ref.indexOf("#");
+ if (pos == 0) {
+ // local doc
+ Document doc = currentElement.getOwnerDocument();
+ Element ele =
+ doc.getElementById(ref.substring(1, ref.length()));
+ if (ele instanceof SVGElement) {
+ return (SVGElement) ele;
+ }
+ } else if (pos != -1) {
+ String href = ref.substring(0, pos);
+ if (href.indexOf(":") == -1) {
+ href = "file:" + href;
+ }
+ try {
+ // this is really only to get a cached svg image
+ FopImage img = FopImageFactory.Make(href);
+ if (img instanceof SVGImage) {
+ SVGDocument doc = ((SVGImage) img).getSVGDocument();
+ Element ele = doc.getElementById(
+ ref.substring(pos + 1, ref.length()));
+ if (ele instanceof SVGElement) {
+ return (SVGElement) ele;
+ }
+ }
+ } catch (Exception e) {
+ MessageHandler.errorln(e.toString());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * This class is used to handle the rendering of svg text.
+ * This is so that it can deal with the recursive rendering
+ * of text markup, while keeping track of the state and position.
+ */
+ class SVGTextRenderer {
+ FontState fs;
+ String transstr;
+ float currentX;
+ float currentY;
+ float baseX;
+ float baseY;
+ SVGMatrix matrix;
+ float x;
+ float y;
+
+ SVGTextRenderer(FontState fontState, SVGTextElementImpl tg,
+ float x, float y) {
+ fs = fontState;
+
+ //PDFNumber pdfNumber = new PDFNumber();
+ SVGTransformList trans = tg.getTransform().getBaseVal();
+ matrix = trans.consolidate().getMatrix();
+ //transstr = (pdfNumber.doubleOut(matrix.getA()) + " " +
+ // pdfNumber.doubleOut(matrix.getB()) + " " +
+ // pdfNumber.doubleOut(matrix.getC()) + " " +
+ // pdfNumber.doubleOut(-matrix.getD()) + " ");
+ this.x = x;
+ this.y = y;
+ }
+
+ void renderText(SVGTextElementImpl te) {
+ float xoffset = 0;
+
+ if (te.anchor.getEnum() != TextAnchor.START) {
+ // This is a bit of a hack: The code below will update
+ // the current position, so all I have to do is to
+ // prevent that the code will write anything to the
+ // PCL stream...
+ currentStream.setDoOutput(false);
+
+ _renderText (te, 0f, true);
+
+ float width = currentX - te.x;
+ currentStream.setDoOutput(true);
+
+ if (te.anchor.getEnum() == TextAnchor.END) {
+ xoffset = -width;
+ } else if (te.anchor.getEnum() == TextAnchor.MIDDLE) {
+ xoffset = -width/2;
+ }
+ }
+
+ _renderText (te, xoffset, false);
+ }
+
+ void _renderText(SVGTextElementImpl te, float xoffset, boolean getWidthOnly)
+ {
+ //DrawingInstruction di = applyStyle(te, te);
+ //if (di.fill) {
+ // if (di.stroke) {
+ // currentStream.write("2 Tr\n");
+ // } else {
+ // currentStream.write("0 Tr\n");
+ // }
+ //} else if (di.stroke) {
+ // currentStream.write("1 Tr\n");
+ //}
+ updateFont(te, fs);
+
+ float tx = te.x;
+ float ty = te.y;
+ currentX = x + tx + xoffset;
+ currentY = y + ty;
+ baseX = currentX;
+ baseY = currentY;
+ NodeList nodel = te.getChildNodes();
+ // Vector list = te.textList;
+ for (int count = 0; count < nodel.getLength(); count++) {
+ Object o = nodel.item(count);
+ //applyStyle(te, te);
+ if ( o instanceof CharacterData )
+ {
+ String str = ((CharacterData) o).getData();
+ //currentStream.write(transstr +
+ // (currentX + matrix.getE()) + " " +
+ // (baseY + matrix.getF()) + " Tm " + "(");
+ boolean spacing = "preserve".equals(te.getXMLspace());
+ //currentX = addSVGStr(fs, currentX, str, spacing);
+ //currentStream.write(") Tj\n");
+ currentStream.add("\033&a" + (currentX + matrix.getE())*10 + "h" + (baseY + matrix.getF())*10 + "V");
+ currentX = addSVGStr(fs, currentX, str, spacing);
+ }
+ else if ( o instanceof SVGTextPathElementImpl )
+ {
+ SVGTextPathElementImpl tpg = (SVGTextPathElementImpl) o;
+ String ref = tpg.str;
+ SVGElement graph = null;
+ graph = locateDef(ref, tpg);
+ if (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;
+ SVGElement element = locateDef(ref, trg);
+ if (element instanceof SVGTextElementImpl) {
+ // GraphicImpl parent = graph.getGraphicParent();
+ // graph.setParent(trg);
+ SVGTextElementImpl tele =
+ (SVGTextElementImpl) element;
+ // the style should be from tele, but it needs to be placed as a child
+ // of trg to work
+ //di = applyStyle(trg, trg);
+ //if (di.fill) {
+ // if (di.stroke) {
+ // currentStream.write("2 Tr\n");
+ // } else {
+ // currentStream.write("0 Tr\n");
+ // }
+ //} else if (di.stroke) {
+ // currentStream.write("1 Tr\n");
+ //}
+ boolean changed = false;
+ FontState oldfs = fs;
+ changed = updateFont(te, fs);
+ NodeList nl = tele.getChildNodes();
+ boolean spacing =
+ "preserve".equals(trg.getXMLspace());
+ renderTextNodes(spacing, nl,
+ trg.getX().getBaseVal(),
+ trg.getY().getBaseVal(),
+ trg.getDx().getBaseVal(),
+ trg.getDy().getBaseVal());
+
+ if (changed) {
+ fs = oldfs;
+ //currentStream.write("/" +
+ // fs.getFontName() + " " +
+ // fs.getFontSize() / 1000f + " Tf\n");
+ }
+ // graph.setParent(parent);
+ }
+ } else if (o instanceof SVGTSpanElementImpl) {
+ SVGTSpanElementImpl tsg = (SVGTSpanElementImpl) o;
+ //applyStyle(tsg, tsg);
+ boolean changed = false;
+ FontState oldfs = fs;
+ changed = updateFont(tsg, fs);
+ boolean spacing = "preserve".equals(tsg.getXMLspace());
+ renderTextNodes(spacing, tsg.getChildNodes(),
+ tsg.getX().getBaseVal(),
+ tsg.getY().getBaseVal(),
+ tsg.getDx().getBaseVal(),
+ tsg.getDy().getBaseVal());
+
+ // currentX += fs.width(' ') / 1000f;
+ if (changed) {
+ fs = oldfs;
+ //currentStream.write("/" + fs.getFontName() +
+ // " " + fs.getFontSize() / 1000f + " Tf\n");
+ }
+ } else {
+ MessageHandler.errorln("Error: unknown text element " + o);
+ }
+ }
+ }
+
+ void renderTextNodes(boolean spacing, NodeList nl,
+ SVGLengthList xlist, SVGLengthList ylist,
+ SVGLengthList dxlist, SVGLengthList dylist) {
+ boolean inbetween = false;
+ boolean addedspace = false;
+ int charPos = 0;
+ float xpos = currentX;
+ float ypos = currentY;
+
+ for (int count = 0; count < nl.getLength(); count++) {
+ Node n = nl.item(count);
+ if (n instanceof CharacterData) {
+ //StringBuffer pdf = new StringBuffer();
+ String str = ((CharacterData) n).getData();
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ xpos = currentX;
+ ypos = currentY;
+ if (ylist.getNumberOfItems() > charPos) {
+ ypos = baseY + (ylist.getItem(charPos)).
+ getValue();
+ }
+ if (dylist.getNumberOfItems() > charPos) {
+ ypos = ypos + (dylist.getItem(charPos)).
+ getValue();
+ }
+ if (xlist.getNumberOfItems() > charPos) {
+ xpos = baseX + (xlist.getItem(charPos)).
+ getValue();
+ }
+ if (dxlist.getNumberOfItems() > charPos) {
+ xpos = xpos + (dxlist.getItem(charPos)).
+ getValue();
+ }
+
+ switch (ch) {
+ case '\t':
+ 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");
+ currentStream.add("\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.write(pdf.toString());
+ }
+ }
+ }
+ }
+
+ protected boolean updateFont(SVGStylable style, FontState fs) {
+ boolean changed = false;
+ String fontFamily = fs.getFontFamily();
+ CSSValue sp = style.getPresentationAttribute("font-family");
+ if (sp != null &&
+ sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if (((CSSPrimitiveValue) sp).getPrimitiveType() ==
+ CSSPrimitiveValue.CSS_STRING) {
+ fontFamily = sp.getCssText();
+ }
+ }
+ if (!fontFamily.equals(fs.getFontFamily())) {
+ changed = true;
+ }
+ String fontStyle = fs.getFontStyle();
+ sp = style.getPresentationAttribute("font-style");
+ if (sp != null &&
+ sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if (((CSSPrimitiveValue) sp).getPrimitiveType() ==
+ CSSPrimitiveValue.CSS_STRING) {
+ fontStyle = sp.getCssText();
+ }
+ }
+ if (!fontStyle.equals(fs.getFontStyle())) {
+ changed = true;
+ }
+ String fontWeight = fs.getFontWeight();
+ sp = style.getPresentationAttribute("font-weight");
+ if (sp != null &&
+ sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if (((CSSPrimitiveValue) sp).getPrimitiveType() ==
+ CSSPrimitiveValue.CSS_STRING) {
+ fontWeight = sp.getCssText();
+ }
+ }
+ if (!fontWeight.equals(fs.getFontWeight())) {
+ changed = true;
+ }
+ float newSize = fs.getFontSize() / 1000f;
+ sp = style.getPresentationAttribute("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 (fs.getFontSize() / 1000f != newSize) {
+ changed = true;
+ }
+ if (changed) {
+ try {
+ fs = new FontState(fs.getFontInfo(), fontFamily,
+ fontStyle, fontWeight, (int)(newSize * 1000),
+ FontVariant.NORMAL);
+ } catch (Exception fope) {
+ }
+ this.fs = fs;
+
+ //currentStream.write("/" + fs.getFontName() + " " +
+ // newSize + " Tf\n");
+ renderer.setFont(fs.getFontName(), newSize * 1000);
+ } else {
+ if (!currentFontName.equals(fs.getFontName()) ||
+ currentFontSize != fs.getFontSize()) {
+ // currentFontName = fs.getFontName();
+ // currentFontSize = fs.getFontSize();
+ //currentStream.write("/" + fs.getFontName() + " " +
+ // (fs.getFontSize() / 1000) + " Tf\n");
+ renderer.setFont(fs.getFontName(), fs.getFontSize());
+ }
+ }
+ return changed;
+ }
+ }
+}
diff --git a/src/org/apache/fop/render/pcl/PCLStream.java b/src/org/apache/fop/render/pcl/PCLStream.java
new file mode 100755
index 000000000..8b5521bd2
--- /dev/null
+++ b/src/org/apache/fop/render/pcl/PCLStream.java
@@ -0,0 +1,42 @@
+//package com.eastpoint.chrysalis;
+package org.apache.fop.render.pcl;
+
+import java.io.*;
+
+public class PCLStream
+{
+ OutputStream out = null;
+ boolean doOutput = true;
+
+ public PCLStream(OutputStream os)
+ {
+ out = os;
+ }
+
+ public void add(String str)
+ {
+ if ( !doOutput )
+ return;
+
+ byte buff[] = new byte[str.length()];
+ int countr;
+ int len = str.length();
+ for ( countr = 0 ; countr < len ; countr++ )
+ buff[countr] = (byte)str.charAt(countr);
+ try
+ {
+ out.write(buff);
+ }
+ catch (IOException e)
+ {
+ //e.printStackTrace();
+ //e.printStackTrace(System.out);
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ public void setDoOutput(boolean doout)
+ {
+ doOutput = doout;
+ }
+}