]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
First step at bringing back the PostScript renderer. Basic text works to a
authorJeremias Maerki <jeremias@apache.org>
Mon, 27 Jan 2003 09:17:04 +0000 (09:17 +0000)
committerJeremias Maerki <jeremias@apache.org>
Mon, 27 Jan 2003 09:17:04 +0000 (09:17 +0000)
certain degree. Well, it compiles. :-)

Started to factor out PS generation for cleaner separation of PS transcoder and PS renderer
Separation of PostScript procsets so they don't clutter the code of PSRenderer.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195894 13f79535-47bb-0310-9956-ffa450edef68

src/org/apache/fop/render/ps/DSCConstants.java [new file with mode: 0644]
src/org/apache/fop/render/ps/PSGenerator.java [new file with mode: 0644]
src/org/apache/fop/render/ps/PSGraphics2D.java
src/org/apache/fop/render/ps/PSProcSets.java [new file with mode: 0644]
src/org/apache/fop/render/ps/PSRenderer.java
src/org/apache/fop/render/ps/PSStream.java [deleted file]

diff --git a/src/org/apache/fop/render/ps/DSCConstants.java b/src/org/apache/fop/render/ps/DSCConstants.java
new file mode 100644 (file)
index 0000000..4982589
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * $Id$
+ * Copyright (C) 2003 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+package org.apache.fop.render.ps;
+
+/**
+ * This class defines constants with Strings for the DSC specification.
+ * 
+ * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
+ * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
+ * @version $Id$
+ */
+public class DSCConstants {
+
+    // ----==== General Header Comments ====----
+    
+    /** Lead-in for a DSC-conformant PostScript file */
+    public static final String PS_ADOBE_30       = "%!PS-Adobe-3.0";
+    
+    /** Bounding box for the document */
+    public static final String BBOX              = "BoundingBox";
+    /** Copyright information associated with the document or resource */
+    public static final String COPYRIGHT         = "Copyright";
+    /** Creator of the document */
+    public static final String CREATOR           = "Creator";
+    /** Date and time when the document was created */
+    public static final String CREATION_DATE     = "CreationDate";
+    /** Type of data */
+    public static final String DOCUMENT_DATA     = "BoundingBox";
+    /** Use for inidicating an emulator being invoked in the document */
+    public static final String EMULATION         = "Emulation";
+    /** Explicit end of comments */
+    public static final String END_COMMENTS      = "EndComments";
+    /** Required PostScript Level 1 extension for this document */
+    public static final String EXTENSIONS        = "Extensions";
+    /** Indicates who is this document printed for */
+    public static final String FOR               = "For";
+    /** Indicates the PostScript language level used in the document */
+    public static final String LANGUAGE_LEVEL    = "LanguageLevel";
+    /** Indicates the orientation of the document */
+    public static final String ORIENTATION       = "Orientation";
+    /** Number of pages in the document */
+    public static final String PAGES             = "Pages";
+    /** Indicates the order of the pages */
+    public static final String PAGE_ORDER        = "PageOrder";
+    /** Indicates how the document should be routed back to its owner */
+    public static final String ROUTING           = "Routing";
+    /** Title of the document */
+    public static final String TITLE             = "Title";
+    /** Version of the document */
+    public static final String VERSION           = "Version";
+    // ----==== General Body Comments ====----
+    
+    /** Indicates a continued line */
+    public static final String NEXT_LINE         = "+ ";
+    
+    //Skipping BeginBinary/EndBinary. They are deprecated.
+    
+    /** Indicates the start of a data section*/
+    public static final String BEGIN_DATA        = "BeginData";
+    /** Indicates the end of a data section*/
+    public static final String END_DATA          = "EndData";
+    
+    /** Indicates the start of the defaults section */
+    public static final String BEGIN_DEFAULTS    = "BeginDefaults";
+    /** Indicates the end of the defaults section */
+    public static final String END_DEFAULTS      = "EndDefaults";
+    
+    /** Indicates the start of a non-PostScript section */
+    public static final String BEGIN_EMULATION   = "BeginEmulation";
+    /** Indicates the end of a non-PostScript section */
+    public static final String END_EMULATION     = "EndEmulation";
+    
+    /** Indicates the start of a preview section (EPS only)*/
+    public static final String BEGIN_PREVIEW     = "BeginPreview";
+    /** Indicates the end of a preview section (EPS only)*/
+    public static final String END_PREVIEW       = "EndPreview";
+    
+    /** Indicates the start of the prolog */
+    public static final String BEGIN_PROLOG      = "BeginProlog";
+    /** Indicates the end of the prolog */
+    public static final String END_PROLOG        = "EndProlog";
+    
+    /** Indicates the start of the document setup */
+    public static final String BEGIN_SETUP       = "BeginSetup";
+    /** Indicates the end of the document setup */
+    public static final String END_SETUP         = "EndSetup";
+
+
+    // ----==== General Page Comments ====----
+    
+    /** Indicates the start of a graphic object */
+    public static final String BEGIN_OBJECT      = "BeginObject";
+    /** Indicates the end of a graphic object */
+    public static final String END_OBJECT        = "EndObject";
+
+    /** Indicates the start of the page setup section */
+    public static final String BEGIN_PAGE_SETUP  = "BeginPageSetup";
+    /** Indicates the end of the page setup section */
+    public static final String END_PAGE_SETUP    = "EndPageSetup";
+
+    /** Indicates a page number */
+    public static final String PAGE              = "Page";
+    /** Bounding box for a page */
+    public static final String PAGE_BBOX         = "PageBoundingBox";
+    /** Bounding box for a page */
+    public static final String PAGE_ORIENTATION  = "PageOrientation";
+
+    
+    // ----==== General Trailer Comments ====----
+
+    /** Indicates the start of the page trailer */    
+    public static final String PAGE_TRAILER     = "PageTrailer";
+    /** Indicates the start of the document trailer */    
+    public static final String TRAILER          = "Trailer";
+    /** Indicates the end of a page (NON-STANDARD!) */    
+    public static final String END_PAGE         = "EndPage";
+    /** Indicates the end of the document */    
+    public static final String EOF              = "EOF";
+
+
+    // ----==== Requirements Conventions ====----
+
+    /**@todo Add the missing comments */
+    
+    // ----==== Requirement Body Comments ====----
+    
+    /** Indicates the start of an embedded document */
+    public static final String BEGIN_DOCUMENT   = "BeginDocument";
+    /** Indicates the end of an embedded document */
+    public static final String END_DOCUMENT     = "EndDocument";
+    /** Indicates a referenced embedded document */
+    public static final String INCLUDE_DOCUMENT = "IncludeDocument";
+    
+    /** Indicates the start of a PPD feature */
+    public static final String BEGIN_FEATURE    = "BeginFeature";
+    /** Indicates the end of a PPD feature */
+    public static final String END_FEATURE      = "EndFeature";
+    /** Indicates a referenced a PPD feature */
+    public static final String INCLUDE_FEATURE  = "IncludeFeature";
+    
+    //Skipping BeginFile/EndFile/IncludeFile. They are deprecated.
+    //Skipping BeginFont/EndFont/IncludeFont. They are deprecated.
+    //Skipping BeginProcSet/EndProcSet/IncludeProcSet. They are deprecated.
+    
+    /** Indicates the start of a resource (font, file, procset) */
+    public static final String BEGIN_RESOURCE       = "BeginResource";
+    /** Indicates the end of a resource (font, file, procset) */
+    public static final String END_RESOURCE         = "EndResource";
+    /** Indicates a referenced a resource (font, file, procset) */
+    public static final String INCLUDE_RESOURCE     = "IncludeResource";
+    
+    
+}
diff --git a/src/org/apache/fop/render/ps/PSGenerator.java b/src/org/apache/fop/render/ps/PSGenerator.java
new file mode 100644 (file)
index 0000000..3181f20
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * $Id$
+ * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+package org.apache.fop.render.ps;
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.util.Date;
+
+/**
+ * This class is used to output PostScript code to an OutputStream.
+ *
+ * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
+ * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
+ * @version $Id$
+ */
+public class PSGenerator {
+
+    /** 
+     * Indicator for the PostScript interpreter that the value is provided 
+     * later in the document (mostly in the %%Trailer section).
+     */
+    public static final AtendIndicator ATEND = new AtendIndicator() {};
+
+    private OutputStream out;
+
+    private StringBuffer tempBuffer = new StringBuffer(256);
+
+    /** @see java.io.FilterOutputStream **/
+    public PSGenerator(OutputStream out) {
+        this.out = out;
+    }
+
+    /**
+     * Writes a newline character to the OutputStream.
+     * 
+     * @throws IOException In case of an I/O problem
+     */
+    public final void newLine() throws IOException {
+        out.write('\n');
+    }
+
+    /**
+     * Formats a double value for PostScript output.
+     * 
+     * @param value value to format
+     * @return the formatted value
+     */
+    public String formatDouble(double value) {
+        NumberFormat nf = new java.text.DecimalFormat("0.#");
+        return nf.format(value);
+    }
+
+    /**
+     * Writes a PostScript command to the stream.
+     *
+     * @param cmd              The PostScript code to be written.
+     * @exception IOException  In case of an I/O problem
+     */
+    public void write(String cmd) throws IOException {
+        if (cmd.length() > 255) {
+            throw new RuntimeException("PostScript command exceeded limit of 255 characters");
+        }
+        out.write(cmd.getBytes("US-ASCII"));
+    }
+
+    /**
+     * Writes a PostScript command to the stream and ends the line.
+     *
+     * @param cmd              The PostScript code to be written.
+     * @exception IOException  In case of an I/O problem
+     */
+    public void writeln(String cmd) throws IOException {
+        write(cmd);
+        newLine();
+    }
+
+    /**
+     * Writes encoded data to the PostScript stream.
+     *
+     * @param cmd              The encoded PostScript code to be written.
+     * @exception IOException  In case of an I/O problem
+     */
+    public void writeByteArr(byte[] cmd) throws IOException {
+        out.write(cmd);
+        newLine();
+    }
+    
+    
+    /**
+     * Flushes the OutputStream.
+     * 
+     * @exception IOException In case of an I/O problem
+     */
+    public void flush() throws IOException {
+        out.flush();
+    }
+
+
+    /**
+     * Escapes a character conforming to the rules established in the PostScript
+     * Language Reference (Search for "Literal Text Strings").
+     * @param c character to escape
+     * @param target target StringBuffer to write the escaped character to
+     */
+    public static final void escapeChar(char c, StringBuffer target) {
+        if (c > 127) {
+            target.append("\\");
+            target.append(Integer.toOctalString(c));
+        } else {
+            switch (c) {
+                case '\n':
+                    target.append("\\n");
+                    break;
+                case '\r':
+                    target.append("\\r");
+                    break;
+                case '\t':
+                    target.append("\\t");
+                    break;
+                case '\b':
+                    target.append("\\b");
+                    break;
+                case '\f':
+                    target.append("\\f");
+                    break;
+                case '\\':
+                    target.append("\\\\");
+                    break;
+                case '(':
+                    target.append("\\(");
+                    break;
+                case ')':
+                    target.append("\\)");
+                    break;
+                default:
+                    target.append(c);
+            }
+        }
+    }
+
+
+    /**
+     * Converts text by applying escaping rules established in the DSC specs.
+     * @param text Text to convert
+     * @return String The resulting String
+     */
+    public static final String convertStringToDSC(String text) {
+        return convertStringToDSC(text, false);
+    }
+
+
+    /**
+     * Converts text by applying escaping rules established in the DSC specs.
+     * @param text Text to convert
+     * @param forceParentheses Force the use of parentheses
+     * @return String The resulting String
+     */
+    public static final String convertStringToDSC(String text, 
+                                                  boolean forceParentheses) {
+        if ((text == null) || (text.length() == 0)) {
+            return "()";
+        } else {
+            int initialSize = text.length();
+            initialSize += initialSize / 2;
+            StringBuffer sb = new StringBuffer(initialSize);
+            if ((Long.getLong(text) != null) 
+                    || (text.indexOf(" ") >= 0) 
+                    || forceParentheses) {
+                        
+                sb.append("(");
+                for (int i = 0; i < text.length(); i++) {
+                    final char c = text.charAt(i);
+                    escapeChar(c, sb);
+                }
+                sb.append(")");
+                return sb.toString();
+            } else {
+                return text;
+            }
+        }
+    }
+
+
+    /**
+     * Writes a DSC comment to the output stream.
+     * @param name Name of the DSC comment
+     * @exception IOException In case of an I/O problem
+     * @see org.apache.fop.render.ps.DSCConstants
+     */
+    public void writeDSCComment(String name) throws IOException {
+        writeln("%%" + name);
+    }
+
+
+    /**
+     * Writes a DSC comment to the output stream. The parameter to the DSC 
+     * comment can be any object. The object is converted to a String as
+     * necessary.
+     * @param name Name of the DSC comment
+     * @param param Single parameter to the DSC comment
+     * @exception IOException In case of an I/O problem
+     * @see org.apache.fop.render.ps.DSCConstants
+     */
+    public void writeDSCComment(String name, Object param) throws IOException {
+        writeDSCComment(name, new Object[] {param});    
+    }
+
+        
+    /**
+     * Writes a DSC comment to the output stream. The parameters to the DSC 
+     * comment can be any object. The objects are converted to Strings as
+     * necessary. Please see the source code to find out what parameters are
+     * currently supported.
+     * @param name Name of the DSC comment
+     * @param params Array of parameters to the DSC comment
+     * @exception IOException In case of an I/O problem
+     * @see org.apache.fop.render.ps.DSCConstants
+     */
+    public void writeDSCComment(String name, Object[] params) throws IOException {
+        tempBuffer.setLength(0);
+        tempBuffer.append("%%");
+        tempBuffer.append(name);
+        if ((params != null) && (params.length > 0)) {
+            tempBuffer.append(": ");
+            for (int i = 0; i < params.length; i++) {
+                if (i > 0) {
+                    tempBuffer.append(" ");
+                }
+                
+                if (params[i] instanceof String) {
+                    tempBuffer.append(convertStringToDSC((String)params[i]));
+                } else if (params[i] instanceof AtendIndicator) {
+                    tempBuffer.append("(atend)");
+                } else if (params[i] instanceof Number) {
+                    tempBuffer.append(params[i].toString());
+                } else if (params[i] instanceof Date) {
+                    DateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+                    tempBuffer.append(convertStringToDSC(df.format((Date)params[i])));
+                } else {
+                    throw new IllegalArgumentException("Unsupported parameter type: " 
+                            + params[i].getClass().getName());
+                }
+            }
+        }
+        writeln(tempBuffer.toString());
+    }
+    
+    
+    /** Used for the ATEND constant. See there. */
+    private static interface AtendIndicator {
+    }
+
+}
index 58d732f2590fb5ca0979c4e690921014f1db428a..93b2d78f0ae08328f5b0b33e6426fdd56bd4c77e 100644 (file)
@@ -37,13 +37,11 @@ import java.awt.image.ImageObserver;
 import java.awt.image.Raster;
 import java.awt.image.RenderedImage;
 import java.awt.image.renderable.RenderableImage;
+import java.io.IOException;
 
 // FOP
 import org.apache.fop.layout.FontInfo;
 import org.apache.fop.layout.FontState;
-import org.apache.fop.pdf.PDFColor;
-//import org.apache.fop.pdf.PDFColorSpace;
-import org.apache.fop.pdf.PDFNumber;
 
 // Batik
 import org.apache.batik.ext.awt.g2d.AbstractGraphics2D;
@@ -67,9 +65,9 @@ public class PSGraphics2D extends AbstractGraphics2D {
     private boolean standalone = false;
 
     /**
-     * the PDF Document being created
+     * the PostScript genertaor being created
      */
-    protected PSRenderer psRenderer;
+    protected PSGenerator gen;
 
     /** Currently valid FontState */
     protected FontState fontState;
@@ -97,7 +95,7 @@ public class PSGraphics2D extends AbstractGraphics2D {
     /**
      * the current colour for use in svg
      */
-    protected PDFColor currentColour = new PDFColor(0, 0, 0);
+    protected Color currentColour = new Color(0, 0, 0);
 
     /** FontInfo containing all available fonts */
     protected FontInfo fontInfo;
@@ -106,17 +104,17 @@ public class PSGraphics2D extends AbstractGraphics2D {
      * Create a new Graphics2D that generates PostScript code.
      * @param textAsShapes True if text should be rendered as graphics
      * @param fs currently valid FontState object
-     * @param ren PostScript renderer
+     * @param gen PostScript generator to use for output
      * @param font current font name
      * @param size current font size
      * @param xpos current x pos
      * @param ypos current y pos
      * @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D#AbstractGraphics2D(boolean)
      */
-    public PSGraphics2D(boolean textAsShapes, FontState fs, PSRenderer ren,
+    public PSGraphics2D(boolean textAsShapes, FontState fs, PSGenerator gen,
                         String font, int size, int xpos, int ypos) {
         super(textAsShapes);
-        psRenderer = ren;
+        this.gen = gen;
         currentFontName = font;
         currentFontSize = size;
         currentYPosition = ypos;
@@ -158,6 +156,14 @@ public class PSGraphics2D extends AbstractGraphics2D {
         return new PSGraphics2D(this);
     }
 
+    /**
+     * Central handler for IOExceptions for this class.
+     * @param ioe IOException to handle
+     */
+    protected void handleIOException(IOException ioe) {
+        ioe.printStackTrace();
+    }
+
     /**
      * Draws as much of the specified image as is currently available.
      * The image is drawn with its top-left corner at
@@ -441,7 +447,7 @@ public class PSGraphics2D extends AbstractGraphics2D {
      */
     public void dispose() {
         // System.out.println("dispose");
-        psRenderer = null;
+        this.gen = null;
         fontState = null;
         currentFontName = null;
         currentColour = null;
@@ -465,58 +471,62 @@ public class PSGraphics2D extends AbstractGraphics2D {
      * @see #setComposite
      */
     public void draw(Shape s) {
-        // System.out.println("draw(Shape)");
-        psRenderer.write("gsave");
-        Shape imclip = getClip();
-        writeClip(imclip);
-        Color c = getColor();
-        psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
-                         + " setrgbcolor");
-
-        applyPaint(getPaint(), false);
-        applyStroke(getStroke());
-
-        psRenderer.write("newpath");
-        PathIterator iter = s.getPathIterator(getTransform());
-        while (!iter.isDone()) {
-            double vals[] = new double[6];
-            int type = iter.currentSegment(vals);
-            switch (type) {
-            case PathIterator.SEG_CUBICTO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[2]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[3]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[4]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[5])
-                                 + " curveto");
-                break;
-            case PathIterator.SEG_LINETO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1])
-                                 + " lineto");
-                break;
-            case PathIterator.SEG_MOVETO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1])
-                                 + " M");
-                break;
-            case PathIterator.SEG_QUADTO:
-                // psRenderer.write((1000 * PDFNumber.doubleOut(vals[0])) +
-                // " " + (1000 * PDFNumber.doubleOut(vals[1])) + " " +
-                // (1000 * PDFNumber.doubleOut(vals[2])) + " " +
-                // (1000 * PDFNumber.doubleOut(vals[3])) + " y\n");
-                break;
-            case PathIterator.SEG_CLOSE:
-                psRenderer.write("closepath");
-                break;
-            default:
-                break;
+        try {
+            // System.out.println("draw(Shape)");
+            gen.writeln("gsave");
+            Shape imclip = getClip();
+            writeClip(imclip);
+            Color c = getColor();
+            gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
+                             + " setrgbcolor");
+            
+            applyPaint(getPaint(), false);
+            applyStroke(getStroke());
+            
+            gen.writeln("newpath");
+            PathIterator iter = s.getPathIterator(getTransform());
+            while (!iter.isDone()) {
+                double vals[] = new double[6];
+                int type = iter.currentSegment(vals);
+                switch (type) {
+                case PathIterator.SEG_CUBICTO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1]) + " "
+                              + gen.formatDouble(1000 * vals[2]) + " "
+                              + gen.formatDouble(1000 * vals[3]) + " "
+                              + gen.formatDouble(1000 * vals[4]) + " "
+                              + gen.formatDouble(1000 * vals[5])
+                              + " curveto");
+                    break;
+                case PathIterator.SEG_LINETO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1])
+                              + " lineto");
+                    break;
+                case PathIterator.SEG_MOVETO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1])
+                              + " M");
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    // psRenderer.write((1000 * PDFNumber.doubleOut(vals[0])) +
+                    // " " + (1000 * PDFNumber.doubleOut(vals[1])) + " " +
+                    // (1000 * PDFNumber.doubleOut(vals[2])) + " " +
+                    // (1000 * PDFNumber.doubleOut(vals[3])) + " y\n");
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    gen.writeln("closepath");
+                    break;
+                default:
+                    break;
+                }
+                iter.next();
             }
-            iter.next();
+            doDrawing(false, true, false);
+            gen.writeln("grestore");
+        } catch (IOException ioe) {
+            handleIOException(ioe);
         }
-        doDrawing(false, true, false);
-        psRenderer.write("grestore");
     }
 
     /**
@@ -524,47 +534,51 @@ public class PSGraphics2D extends AbstractGraphics2D {
      * @param s Shape defining the clipping region
      */
     protected void writeClip(Shape s) {
-        PathIterator iter = s.getPathIterator(getTransform());
-        psRenderer.write("newpath");
-        while (!iter.isDone()) {
-            double vals[] = new double[6];
-            int type = iter.currentSegment(vals);
-            switch (type) {
-            case PathIterator.SEG_CUBICTO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[2]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[3]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[4]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[5])
-                                 + " curveto");
-                break;
-            case PathIterator.SEG_LINETO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1])
-                                 + " lineto");
-                break;
-            case PathIterator.SEG_MOVETO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1])
-                                 + " M");
-                break;
-            case PathIterator.SEG_QUADTO:
-                // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
-                // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
-                // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
-                // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
-                break;
-            case PathIterator.SEG_CLOSE:
-                psRenderer.write("closepath");
-                break;
-            default:
-                break;
+        try {
+            PathIterator iter = s.getPathIterator(getTransform());
+            gen.writeln("newpath");
+            while (!iter.isDone()) {
+                double vals[] = new double[6];
+                int type = iter.currentSegment(vals);
+                switch (type) {
+                case PathIterator.SEG_CUBICTO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1]) + " "
+                              + gen.formatDouble(1000 * vals[2]) + " "
+                              + gen.formatDouble(1000 * vals[3]) + " "
+                              + gen.formatDouble(1000 * vals[4]) + " "
+                              + gen.formatDouble(1000 * vals[5])
+                              + " curveto");
+                    break;
+                case PathIterator.SEG_LINETO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1])
+                              + " lineto");
+                    break;
+                case PathIterator.SEG_MOVETO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1])
+                              + " M");
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
+                    // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
+                    // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
+                    // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    gen.writeln("closepath");
+                    break;
+                default:
+                    break;
+                }
+                iter.next();
             }
-            iter.next();
+            // clip area
+            gen.writeln("clippath");
+        } catch (IOException ioe) {
+            handleIOException(ioe);
         }
-        // clip area
-        psRenderer.write("clippath");
     }
 
     /**
@@ -609,10 +623,10 @@ public class PSGraphics2D extends AbstractGraphics2D {
 
             List someColors = new java.util.ArrayList();
 
-            PDFColor color1 = new PDFColor(c1.getRed(), c1.getGreen(),
+            Color color1 = new Color(c1.getRed(), c1.getGreen(),
                                            c1.getBlue());
             someColors.add(color1);
-            PDFColor color2 = new PDFColor(c2.getRed(), c2.getGreen(),
+            Color color2 = new Color(c2.getRed(), c2.getGreen(),
                                            c2.getBlue());
             someColors.add(color2);
 
@@ -627,54 +641,56 @@ public class PSGraphics2D extends AbstractGraphics2D {
      * @param stroke Stroke object to use
      */
     protected void applyStroke(Stroke stroke) {
-        if (stroke instanceof BasicStroke) {
-            BasicStroke bs = (BasicStroke)stroke;
-
-            float[] da = bs.getDashArray();
-            if (da != null) {
-                psRenderer.write("[");
-                for (int count = 0; count < da.length; count++) {
-                    psRenderer.write("" + (1000 * (int)da[count]));
-                    if (count < da.length - 1) {
-                        psRenderer.write(" ");
+        try {
+            if (stroke instanceof BasicStroke) {
+                BasicStroke bs = (BasicStroke)stroke;
+            
+                float[] da = bs.getDashArray();
+                if (da != null) {
+                    gen.writeln("[");
+                    for (int count = 0; count < da.length; count++) {
+                        gen.writeln("" + (1000 * (int)da[count]));
+                        if (count < da.length - 1) {
+                            gen.writeln(" ");
+                        }
                     }
+                    gen.writeln("] ");
+                    float offset = bs.getDashPhase();
+                    gen.writeln((1000 * (int)offset) + " setdash");
                 }
-                psRenderer.write("] ");
-                float offset = bs.getDashPhase();
-                psRenderer.write((1000 * (int)offset) + " setdash");
-            }
-            int ec = bs.getEndCap();
-            switch (ec) {
-            case BasicStroke.CAP_BUTT:
-                psRenderer.write(0 + " setlinecap");
-                break;
-            case BasicStroke.CAP_ROUND:
-                psRenderer.write(1 + " setlinecap");
-                break;
-            case BasicStroke.CAP_SQUARE:
-                psRenderer.write(2 + " setlinecap");
-                break;
-            }
-
-            int lj = bs.getLineJoin();
-            switch (lj) {
-            case BasicStroke.JOIN_MITER:
-                psRenderer.write(0 + " setlinejoin");
-                break;
-            case BasicStroke.JOIN_ROUND:
-                psRenderer.write(1 + " setlinejoin");
-                break;
-            case BasicStroke.JOIN_BEVEL:
-                psRenderer.write(2 + " setlinejoin");
-                break;
+                int ec = bs.getEndCap();
+                switch (ec) {
+                case BasicStroke.CAP_BUTT:
+                    gen.writeln(0 + " setlinecap");
+                    break;
+                case BasicStroke.CAP_ROUND:
+                    gen.writeln(1 + " setlinecap");
+                    break;
+                case BasicStroke.CAP_SQUARE:
+                    gen.writeln(2 + " setlinecap");
+                    break;
+                }
+            
+                int lj = bs.getLineJoin();
+                switch (lj) {
+                case BasicStroke.JOIN_MITER:
+                    gen.writeln("0 setlinejoin");
+                    break;
+                case BasicStroke.JOIN_ROUND:
+                    gen.writeln("1 setlinejoin");
+                    break;
+                case BasicStroke.JOIN_BEVEL:
+                    gen.writeln("2 setlinejoin");
+                    break;
+                }
+                float lw = bs.getLineWidth();
+                gen.writeln(gen.formatDouble(1000 * lw) + " setlinewidth");
+            
+                float ml = bs.getMiterLimit();
+                gen.writeln(gen.formatDouble(1000 * ml) + " setmiterlimit");
             }
-            float lw = bs.getLineWidth();
-            psRenderer.write(PDFNumber.doubleOut(1000 * lw)
-                             + " setlinewidth");
-
-            float ml = bs.getMiterLimit();
-            psRenderer.write(PDFNumber.doubleOut(1000 * ml)
-                             + " setmiterlimit");
+        } catch (IOException ioe) {
+            handleIOException(ioe);
         }
     }
 
@@ -763,28 +779,32 @@ public class PSGraphics2D extends AbstractGraphics2D {
      * @see #setClip
      */
     public void drawString(String s, float x, float y) {
-        System.out.println("drawString(String)");
-        psRenderer.write("BT");
-        Shape imclip = getClip();
-        writeClip(imclip);
-        Color c = getColor();
-        psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
-                         + " setrgbcolor");
-
-        AffineTransform trans = getTransform();
-        trans.translate(x, y);
-        double[] vals = new double[6];
-        trans.getMatrix(vals);
-
-        psRenderer.write(PDFNumber.doubleOut(vals[0]) + " "
-                         + PDFNumber.doubleOut(vals[1]) + " "
-                         + PDFNumber.doubleOut(vals[2]) + " "
-                         + PDFNumber.doubleOut(vals[3]) + " "
-                         + PDFNumber.doubleOut(vals[4]) + " "
-                         + PDFNumber.doubleOut(vals[5]) + " "
-                         + PDFNumber.doubleOut(vals[6]) + " Tm [" + s + "]");
-
-        psRenderer.write("ET");
+        try {
+            System.out.println("drawString(String)");
+            gen.writeln("BT");
+            Shape imclip = getClip();
+            writeClip(imclip);
+            Color c = getColor();
+            gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
+                             + " setrgbcolor");
+            
+            AffineTransform trans = getTransform();
+            trans.translate(x, y);
+            double[] vals = new double[6];
+            trans.getMatrix(vals);
+            
+            gen.writeln(gen.formatDouble(vals[0]) + " "
+                      + gen.formatDouble(vals[1]) + " "
+                      + gen.formatDouble(vals[2]) + " "
+                      + gen.formatDouble(vals[3]) + " "
+                      + gen.formatDouble(vals[4]) + " "
+                      + gen.formatDouble(vals[5]) + " "
+                      + gen.formatDouble(vals[6]) + " Tm [" + s + "]");
+            
+            gen.writeln("ET");
+        } catch (IOException ioe) {
+            handleIOException(ioe);
+        }
     }
 
     /**
@@ -814,38 +834,42 @@ public class PSGraphics2D extends AbstractGraphics2D {
      */
     public void drawString(AttributedCharacterIterator iterator, float x,
                            float y) {
-        System.err.println("drawString(AttributedCharacterIterator)");
-
-        psRenderer.write("BT");
-        Shape imclip = getClip();
-        writeClip(imclip);
-        Color c = getColor();
-        currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue());
-        psRenderer.write(currentColour.getColorSpaceOut(true));
-        c = getBackground();
-        PDFColor col = new PDFColor(c.getRed(), c.getGreen(), c.getBlue());
-        psRenderer.write(col.getColorSpaceOut(false));
-
-        AffineTransform trans = getTransform();
-        trans.translate(x, y);
-        double[] vals = new double[6];
-        trans.getMatrix(vals);
-
-        for (char ch = iterator.first(); ch != CharacterIterator.DONE;
-                ch = iterator.next()) {
-            //Map attr = iterator.getAttributes();
-
-            psRenderer.write(PDFNumber.doubleOut(vals[0]) + " "
-                             + PDFNumber.doubleOut(vals[1]) + " "
-                             + PDFNumber.doubleOut(vals[2]) + " "
-                             + PDFNumber.doubleOut(vals[3]) + " "
-                             + PDFNumber.doubleOut(vals[4]) + " "
-                             + PDFNumber.doubleOut(vals[5]) + " "
-                             + PDFNumber.doubleOut(vals[6]) + " Tm [" + ch
-                             + "]");
+        try {
+            System.err.println("drawString(AttributedCharacterIterator)");
+            
+            gen.writeln("BT");
+            Shape imclip = getClip();
+            writeClip(imclip);
+            Color c = getColor();
+            currentColour = new Color(c.getRed(), c.getGreen(), c.getBlue());
+            //gen.writeln(currentColour.getColorSpaceOut(true));
+            c = getBackground();
+            Color col = new Color(c.getRed(), c.getGreen(), c.getBlue());
+            //gen.writeln(col.getColorSpaceOut(false));
+            
+            AffineTransform trans = getTransform();
+            trans.translate(x, y);
+            double[] vals = new double[6];
+            trans.getMatrix(vals);
+            
+            for (char ch = iterator.first(); ch != CharacterIterator.DONE;
+                    ch = iterator.next()) {
+                //Map attr = iterator.getAttributes();
+            
+                gen.writeln(gen.formatDouble(vals[0]) + " "
+                          + gen.formatDouble(vals[1]) + " "
+                          + gen.formatDouble(vals[2]) + " "
+                          + gen.formatDouble(vals[3]) + " "
+                          + gen.formatDouble(vals[4]) + " "
+                          + gen.formatDouble(vals[5]) + " "
+                          + gen.formatDouble(vals[6]) + " Tm [" + ch
+                          + "]");
+            }
+            
+            gen.writeln("ET");
+        } catch (IOException ioe) {
+            handleIOException(ioe);
         }
-
-        psRenderer.write("ET");
     }
 
     /**
@@ -863,83 +887,90 @@ public class PSGraphics2D extends AbstractGraphics2D {
      * @see #setClip
      */
     public void fill(Shape s) {
-        // System.err.println("fill");
-        psRenderer.write("gsave");
-        Shape imclip = getClip();
-        writeClip(imclip);
-        Color c = getColor();
-        psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
-                         + " setrgbcolor");
-
-        applyPaint(getPaint(), true);
-
-        psRenderer.write("newpath");
-        PathIterator iter = s.getPathIterator(getTransform());
-        while (!iter.isDone()) {
-            double vals[] = new double[6];
-            int type = iter.currentSegment(vals);
-            switch (type) {
-            case PathIterator.SEG_CUBICTO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[2]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[3]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[4]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[5])
-                                 + " curveto");
-                break;
-            case PathIterator.SEG_LINETO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1])
-                                 + " lineto");
-                break;
-            case PathIterator.SEG_MOVETO:
-                psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
-                                 + PDFNumber.doubleOut(1000 * vals[1])
-                                 + " M");
-                break;
-            case PathIterator.SEG_QUADTO:
-                // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
-                // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
-                // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
-                // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
-                break;
-            case PathIterator.SEG_CLOSE:
-                psRenderer.write("closepath");
-                break;
-            default:
-                break;
+        try {
+            // System.err.println("fill");
+            gen.writeln("gsave");
+            Shape imclip = getClip();
+            writeClip(imclip);
+            Color c = getColor();
+            gen.writeln(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
+                             + " setrgbcolor");
+            
+            applyPaint(getPaint(), true);
+            
+            gen.writeln("newpath");
+            PathIterator iter = s.getPathIterator(getTransform());
+            while (!iter.isDone()) {
+                double vals[] = new double[6];
+                int type = iter.currentSegment(vals);
+                switch (type) {
+                case PathIterator.SEG_CUBICTO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1]) + " "
+                              + gen.formatDouble(1000 * vals[2]) + " "
+                              + gen.formatDouble(1000 * vals[3]) + " "
+                              + gen.formatDouble(1000 * vals[4]) + " "
+                              + gen.formatDouble(1000 * vals[5])
+                              + " curveto");
+                    break;
+                case PathIterator.SEG_LINETO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1])
+                              + " lineto");
+                    break;
+                case PathIterator.SEG_MOVETO:
+                    gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
+                              + gen.formatDouble(1000 * vals[1])
+                              + " M");
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
+                    // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
+                    // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
+                    // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    gen.writeln("closepath");
+                    break;
+                default:
+                    break;
+                }
+                iter.next();
             }
-            iter.next();
+            doDrawing(true, false,
+                      iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
+            gen.writeln("grestore");
+        } catch (IOException ioe) {
+            handleIOException(ioe);
         }
-        doDrawing(true, false,
-                  iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
-        psRenderer.write("grestore");
     }
 
     /**
      * Commits a painting operation.
      * @param fill filling
      * @param stroke stroking
+     * @param nonzero ???
+     * @exception IOException In case of an I/O problem
      */
-    protected void doDrawing(boolean fill, boolean stroke, boolean nonzero) {
+    protected void doDrawing(boolean fill, boolean stroke, boolean nonzero) 
+                throws IOException {
         if (fill) {
             if (stroke) {
                 if (!nonzero) {
-                    psRenderer.write("stroke");
+                    gen.writeln("stroke");
                 } else {
-                    psRenderer.write("stroke");
+                    gen.writeln("stroke");
                 }
             } else {
                 if (!nonzero) {
-                    psRenderer.write("fill");
+                    gen.writeln("fill");
                 } else {
-                    psRenderer.write("fill");
+                    gen.writeln("fill");
                 }
             }
         } else {
             // if(stroke)
-            psRenderer.write("stroke");
+            gen.writeln("stroke");
         }
     }
 
diff --git a/src/org/apache/fop/render/ps/PSProcSets.java b/src/org/apache/fop/render/ps/PSProcSets.java
new file mode 100644 (file)
index 0000000..03e4571
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * $Id$
+ * Copyright (C) 2001-2003 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+package org.apache.fop.render.ps;
+
+import java.io.IOException;
+
+/**
+ * This class defines the basic resources (procsets) used by FOP's PostScript
+ * renderer and SVG transcoder.
+ * 
+ * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
+ * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
+ * @version $Id$
+ */
+public final class PSProcSets {
+
+    /**
+     * Generates a resource defining standard procset for FOP.
+     * @param gen PSGenerator to use for output
+     * @throws IOException In case of an I/O problem
+     */
+    public static final void writeFOPStdProcSet(PSGenerator gen) throws IOException {
+        gen.writeln("%%BeginResource: procset (Apache FOP Std ProcSet) 1.0 0");
+        gen.writeln("%%Version: 1.0 0");
+        gen.writeln("%%Copyright: Copyright (C) 2001-2003 "
+                    + "The Apache Software Foundation. All rights reserved.");
+        gen.writeln("%%Title: Basic set of procedures used by FOP");
+
+        gen.writeln("/bd{bind def}bind def");
+        gen.writeln("/ld{load def}bd");
+        gen.writeln("/M/moveto ld");
+        gen.writeln("/RM/rmoveto ld");
+        gen.writeln("/t/show ld");
+
+        gen.writeln("/_ctm matrix def"); //Holds the current matrix
+        gen.writeln("/_tm matrix def");
+        //BT: save currentmatrix, set _tm to identitymatrix and move to 0/0
+        gen.writeln("/BT { _ctm currentmatrix pop matrix _tm copy pop 0 0 moveto } bd"); 
+        //ET: restore last currentmatrix
+        gen.writeln("/ET { _ctm setmatrix } bd");
+        gen.writeln("/iTm { _ctm setmatrix _tm concat } bd");
+        gen.writeln("/Tm { _tm astore pop iTm 0 0 moveto } bd");
+        
+        gen.writeln("/ux 0.0 def");
+        gen.writeln("/uy 0.0 def");
+
+        // <font> <size> F
+        gen.writeln("/F {");
+        gen.writeln("  /Tp exch def");
+        // gen.writeln("  currentdict exch get");
+        gen.writeln("  /Tf exch def");
+        gen.writeln("  Tf findfont Tp scalefont setfont");
+        gen.writeln("  /cf Tf def  /cs Tp def  /cw ( ) stringwidth pop def");
+        gen.writeln("} bd");
+
+        gen.writeln("/ULS {currentpoint /uy exch def /ux exch def} bd");
+        gen.writeln("/ULE {");
+        gen.writeln("  /Tcx currentpoint pop def");
+        gen.writeln("  gsave");
+        gen.writeln("  newpath");
+        gen.writeln("  cf findfont cs scalefont dup");
+        gen.writeln("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
+        gen.writeln("  /UnderlinePosition get Ts mul /To exch def");
+        gen.writeln("  /UnderlineThickness get Ts mul /Tt exch def");
+        gen.writeln("  ux uy To add moveto  Tcx uy To add lineto");
+        gen.writeln("  Tt setlinewidth stroke");
+        gen.writeln("  grestore");
+        gen.writeln("} bd");
+
+        gen.writeln("/OLE {");
+        gen.writeln("  /Tcx currentpoint pop def");
+        gen.writeln("  gsave");
+        gen.writeln("  newpath");
+        gen.writeln("  cf findfont cs scalefont dup");
+        gen.writeln("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
+        gen.writeln("  /UnderlinePosition get Ts mul /To exch def");
+        gen.writeln("  /UnderlineThickness get Ts mul /Tt exch def");
+        gen.writeln("  ux uy To add cs add moveto Tcx uy To add cs add lineto");
+        gen.writeln("  Tt setlinewidth stroke");
+        gen.writeln("  grestore");
+        gen.writeln("} bd");
+
+        gen.writeln("/SOE {");
+        gen.writeln("  /Tcx currentpoint pop def");
+        gen.writeln("  gsave");
+        gen.writeln("  newpath");
+        gen.writeln("  cf findfont cs scalefont dup");
+        gen.writeln("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
+        gen.writeln("  /UnderlinePosition get Ts mul /To exch def");
+        gen.writeln("  /UnderlineThickness get Ts mul /Tt exch def");
+        gen.writeln("  ux uy To add cs 10 mul 26 idiv add moveto "
+                    + "Tcx uy To add cs 10 mul 26 idiv add lineto");
+        gen.writeln("  Tt setlinewidth stroke");
+        gen.writeln("  grestore");
+        gen.writeln("} bd");
+
+        gen.writeln("%%EndResource");
+    }
+
+
+    /**
+     * Generates a resource defining a procset for including EPS graphics.
+     * @param gen PSGenerator to use for output
+     * @throws IOException In case of an I/O problem
+     */
+    public static final void writeFOPEPSProcSet(PSGenerator gen) throws IOException {
+        gen.writeln("%%BeginResource: procset (Apache FOP EPS ProcSet) 1.0 0");
+        gen.writeln("%%Version: 1.0 0");
+        gen.writeln("%%Copyright: Copyright (C) 2002-2003 "
+                    + "The Apache Software Foundation. All rights reserved.");
+        gen.writeln("%%Title: EPS procedures used by FOP");
+
+        gen.writeln("/BeginEPSF { %def");
+        gen.writeln("/b4_Inc_state save def         % Save state for cleanup");
+        gen.writeln("/dict_count countdictstack def % Count objects on dict stack");
+        gen.writeln("/op_count count 1 sub def      % Count objects on operand stack");
+        gen.writeln("userdict begin                 % Push userdict on dict stack");
+        gen.writeln("/showpage { } def              % Redefine showpage, { } = null proc");
+        gen.writeln("0 setgray 0 setlinecap         % Prepare graphics state");
+        gen.writeln("1 setlinewidth 0 setlinejoin");
+        gen.writeln("10 setmiterlimit [ ] 0 setdash newpath");
+        gen.writeln("/languagelevel where           % If level not equal to 1 then");
+        gen.writeln("{pop languagelevel             % set strokeadjust and");
+        gen.writeln("1 ne                           % overprint to their defaults.");
+        gen.writeln("{false setstrokeadjust false setoverprint");
+        gen.writeln("} if");
+        gen.writeln("} if");
+        gen.writeln("} bd");
+
+        gen.writeln("/EndEPSF { %def");
+        gen.writeln("count op_count sub {pop} repeat            % Clean up stacks");
+        gen.writeln("countdictstack dict_count sub {end} repeat");
+        gen.writeln("b4_Inc_state restore");
+        gen.writeln("} bd");
+        
+        gen.writeln("%%EndResource");
+    }
+
+}
index 9a84a08c63f78d3381d9061fc93f70f2eb501799..b3d1a37116c1ed7b492ab624f85ca516beee0190 100644 (file)
@@ -8,16 +8,28 @@
 package org.apache.fop.render.ps;
 
 // Java
+import java.awt.geom.Rectangle2D;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 // FOP
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.BlockViewport;
+import org.apache.fop.area.CTM;
+import org.apache.fop.area.PageViewport;
+import org.apache.fop.area.Trait;
+import org.apache.fop.area.inline.ForeignObject;
+import org.apache.fop.area.inline.Word;
 import org.apache.fop.datatypes.ColorType;
 import org.apache.fop.fonts.Font;
 import org.apache.fop.layout.FontInfo;
 import org.apache.fop.render.AbstractRenderer;
+import org.apache.fop.render.RendererContext;
+import org.w3c.dom.Document;
 
 
 /**
@@ -32,21 +44,27 @@ import org.apache.fop.render.AbstractRenderer;
  * sure to also follow the DSC to make it simpler to programmatically modify
  * the generated Postscript files (ex. extract pages etc.).
  * <br>
+ * The PS renderer operates in millipoints as the layout engine. Since PostScript
+ * initially uses points, scaling is applied as needed.
  * @todo Rebuild the PostScript renderer
+ * 
+ * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
+ * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
+ * @version $Id$
  */
 public class PSRenderer extends AbstractRenderer {
 
-    /**
-     * the application producing the PostScript
-     */
+    /** The MIME type for PostScript */
+    public static final String MIME_TYPE = "application/postscript";
+
+    /** The application producing the PostScript */
     protected String producer;
+    private int currentPageNumber = 0;
 
     private boolean enableComments = true;
 
-    /**
-     * the stream used to output the PostScript
-     */
-    protected PSStream out;
+    /** The PostScript generator used to output the PostScript */
+    protected PSGenerator gen;
     private boolean ioTrouble = false;
 
     private String currentFontName;
@@ -72,13 +90,17 @@ public class PSRenderer extends AbstractRenderer {
      * Write out a command
      * @param cmd PostScript command
      */
-    protected void write(String cmd) {
+    protected void writeln(String cmd) {
         try {
-            out.write(cmd);
-        } catch (IOException e) {
-            if (!ioTrouble) {
-                e.printStackTrace();
-            }
+            gen.writeln(cmd);
+        } catch (IOException ioe) {
+            handleIOTrouble(ioe);
+        }
+    }
+
+    protected void handleIOTrouble(IOException ioe) {
+        if (!ioTrouble) {
+            getLogger().error("Error while writing to target file", ioe);
             ioTrouble = true;
         }
     }
@@ -89,7 +111,7 @@ public class PSRenderer extends AbstractRenderer {
      */
     protected void comment(String comment) {
         if (this.enableComments) {
-            write(comment);
+            writeln(comment);
         }
     }
 
@@ -98,71 +120,9 @@ public class PSRenderer extends AbstractRenderer {
      * @param fontInfo available fonts
      */
     protected void writeFontDict(FontInfo fontInfo) {
-        write("%%BeginResource: procset FOPFonts");
-        write("%%Title: Font setup (shortcuts) for this file");
-        write("/FOPFonts 100 dict dup begin");
-        write("/bd{bind def}bind def");
-        write("/ld{load def}bd");
-        write("/M/moveto ld");
-        write("/RM/rmoveto ld");
-        write("/t/show ld");
-
-        write("/ux 0.0 def");
-        write("/uy 0.0 def");
-        // write("/cf /Helvetica def");
-        // write("/cs 12000 def");
-
-        // <font> <size> F
-        write("/F {");
-        write("  /Tp exch def");
-        // write("  currentdict exch get");
-        write("  /Tf exch def");
-        write("  Tf findfont Tp scalefont setfont");
-        write("  /cf Tf def  /cs Tp def  /cw ( ) stringwidth pop def");
-        write("} bd");
-
-        write("/ULS {currentpoint /uy exch def /ux exch def} bd");
-        write("/ULE {");
-        write("  /Tcx currentpoint pop def");
-        write("  gsave");
-        write("  newpath");
-        write("  cf findfont cs scalefont dup");
-        write("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
-        write("  /UnderlinePosition get Ts mul /To exch def");
-        write("  /UnderlineThickness get Ts mul /Tt exch def");
-        write("  ux uy To add moveto  Tcx uy To add lineto");
-        write("  Tt setlinewidth stroke");
-        write("  grestore");
-        write("} bd");
-
-        write("/OLE {");
-        write("  /Tcx currentpoint pop def");
-        write("  gsave");
-        write("  newpath");
-        write("  cf findfont cs scalefont dup");
-        write("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
-        write("  /UnderlinePosition get Ts mul /To exch def");
-        write("  /UnderlineThickness get Ts mul /Tt exch def");
-        write("  ux uy To add cs add moveto Tcx uy To add cs add lineto");
-        write("  Tt setlinewidth stroke");
-        write("  grestore");
-        write("} bd");
-
-        write("/SOE {");
-        write("  /Tcx currentpoint pop def");
-        write("  gsave");
-        write("  newpath");
-        write("  cf findfont cs scalefont dup");
-        write("  /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
-        write("  /UnderlinePosition get Ts mul /To exch def");
-        write("  /UnderlineThickness get Ts mul /Tt exch def");
-        write("  ux uy To add cs 10 mul 26 idiv add moveto "
-                    + "Tcx uy To add cs 10 mul 26 idiv add lineto");
-        write("  Tt setlinewidth stroke");
-        write("  grestore");
-        write("} bd");
-
-
+        writeln("%%BeginResource: procset FOPFonts");
+        writeln("%%Title: Font setup (shortcuts) for this file");
+        writeln("/FOPFonts 100 dict dup begin");
 
         // write("/gfF1{/Helvetica findfont} bd");
         // write("/gfF3{/Helvetica-Bold findfont} bd");
@@ -171,21 +131,21 @@ public class PSRenderer extends AbstractRenderer {
         while (enum.hasNext()) {
             String key = (String)enum.next();
             Font fm = (Font)fonts.get(key);
-            write("/" + key + " /" + fm.getFontName() + " def");
+            writeln("/" + key + " /" + fm.getFontName() + " def");
         }
-        write("end def");
-        write("%%EndResource");
+        writeln("end def");
+        writeln("%%EndResource");
         enum = fonts.keySet().iterator();
         while (enum.hasNext()) {
             String key = (String)enum.next();
             Font fm = (Font)fonts.get(key);
-            write("/" + fm.getFontName() + " findfont");
-            write("dup length dict begin");
-            write("  {1 index /FID ne {def} {pop pop} ifelse} forall");
-            write("  /Encoding ISOLatin1Encoding def");
-            write("  currentdict");
-            write("end");
-            write("/" + fm.getFontName() + " exch definefont pop");
+            writeln("/" + fm.getFontName() + " findfont");
+            writeln("dup length dict begin");
+            writeln("  {1 index /FID ne {def} {pop pop} ifelse} forall");
+            writeln("  /Encoding ISOLatin1Encoding def");
+            writeln("  currentdict");
+            writeln("end");
+            writeln("/" + fm.getFontName() + " exch definefont pop");
         }
     }
 
@@ -193,9 +153,38 @@ public class PSRenderer extends AbstractRenderer {
      * Make sure the cursor is in the right place.
      */
     protected void movetoCurrPosition() {
-        write(this.currentIPPosition + " " + this.currentBPPosition + " M");
+        moveTo(this.currentIPPosition, this.currentBPPosition);
     }
 
+    /**
+     * Moves the cursor.
+     * @param x X coordinate
+     * @param y Y coordinate
+     */
+    protected void moveTo(int x, int y) {
+        writeln(x + " " + y + " M");
+    }
+
+    /** Saves the graphics state of the rendering engine. */
+    protected void saveGraphicsState() {
+        writeln("gsave");
+    }
+    
+    /** Restores the last graphics state of the rendering engine. */
+    protected void restoreGraphicsState() {
+        writeln("grestore");
+    }
+    
+    /** Indicates the beginning of a text object. */
+    protected void beginTextObject() {
+        writeln("BT");
+    }
+        
+    /** Indicates the end of a text object. */
+    protected void endTextObject() {
+        writeln("ET");
+    }
+        
     /**
      * Set up the font info
      *
@@ -215,17 +204,27 @@ public class PSRenderer extends AbstractRenderer {
      * @param h height
      * @param col color to fill with
      */
-    protected void addFilledRect(int x, int y, int w, int h,
+    protected void fillRect(int x, int y, int w, int h,
                                  ColorType col) {
-        write("newpath");
-        write(x + " " + y + " M");
-        write(w + " 0 rlineto");
-        write("0 " + (-h) + " rlineto");
-        write((-w) + " 0 rlineto");
-        write("0 " + h + " rlineto");
-        write("closepath");
         useColor(col);
-        write("fill");
+        writeln(x + " " + y + " " + w + " " + h + " rectfill");
+    }
+
+    protected void drawRect(int x, int y, int w, int h) {
+        writeln(x + " " + y + " " + w + " " + h + " rectstroke");
+    }
+
+    /**
+     * Clip an area.
+     * Write a clipping operation given coordinates in the current
+     * transform.
+     * @param x the x coordinate
+     * @param y the y coordinate
+     * @param width the width of the area
+     * @param height the height of the area
+     */
+    protected void clip(float x, float y, float width, float height) {
+        writeln(x + " " + y + " " + width + " " + height + " rectclip");
     }
 
     /**
@@ -235,7 +234,7 @@ public class PSRenderer extends AbstractRenderer {
      */
     public void useFont(String name, int size) {
         if ((currentFontName != name) || (currentFontSize != size)) {
-            write(name + " " + size + " F");
+            writeln(name + " " + size + " F");
             currentFontName = name;
             currentFontSize = size;
         }
@@ -247,7 +246,7 @@ public class PSRenderer extends AbstractRenderer {
 
     private void useColor(float red, float green, float blue) {
         if ((red != currRed) || (green != currGreen) || (blue != currBlue)) {
-            write(red + " " + green + " " + blue + " setrgbcolor");
+            writeln(red + " " + green + " " + blue + " setrgbcolor");
             currRed = red;
             currGreen = green;
             currBlue = blue;
@@ -258,61 +257,327 @@ public class PSRenderer extends AbstractRenderer {
      * @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
      */
     public void startRenderer(OutputStream outputStream)
-    throws IOException {
+                throws IOException {
         getLogger().debug("rendering areas to PostScript");
 
-        this.out = new PSStream(outputStream);
-        write("%!PS-Adobe-3.0");
-        write("%%Creator: " + this.producer);
-        write("%%DocumentProcessColors: Black");
-        write("%%DocumentSuppliedResources: procset FOPFonts");
-        write("%%EndComments");
-        write("%%BeginDefaults");
-        write("%%EndDefaults");
-        write("%%BeginProlog");
-        write("%%EndProlog");
-        write("%%BeginSetup");
+        //Setup for PostScript generation
+        this.gen = new PSGenerator(outputStream);
+        this.currentPageNumber = 0;
+        
+        //PostScript Header
+        writeln(DSCConstants.PS_ADOBE_30);
+        gen.writeDSCComment(DSCConstants.CREATOR, new String[] {"FOP " + this.producer});
+        gen.writeDSCComment(DSCConstants.CREATION_DATE, new Object[] {new java.util.Date()});
+        gen.writeDSCComment(DSCConstants.PAGES, new Object[] {PSGenerator.ATEND});
+        gen.writeDSCComment(DSCConstants.END_COMMENTS);
+        
+        //Defaults
+        gen.writeDSCComment(DSCConstants.BEGIN_DEFAULTS);
+        gen.writeDSCComment(DSCConstants.END_DEFAULTS);
+        
+        //Prolog
+        gen.writeDSCComment(DSCConstants.BEGIN_PROLOG);
+        gen.writeDSCComment(DSCConstants.END_PROLOG);
+        
+        //Setup
+        gen.writeDSCComment(DSCConstants.BEGIN_SETUP);
+        PSProcSets.writeFOPStdProcSet(gen);
+        PSProcSets.writeFOPEPSProcSet(gen);
         writeFontDict(fontInfo);
-
-        /* Write proc for including EPS */
-        write("%%BeginResource: procset EPSprocs");
-        write("%%Title: EPS encapsulation procs");
-
-        write("/BeginEPSF { %def");
-        write("/b4_Inc_state save def         % Save state for cleanup");
-        write("/dict_count countdictstack def % Count objects on dict stack");
-        write("/op_count count 1 sub def      % Count objects on operand stack");
-        write("userdict begin                 % Push userdict on dict stack");
-        write("/showpage { } def              % Redefine showpage, { } = null proc");
-        write("0 setgray 0 setlinecap         % Prepare graphics state");
-        write("1 setlinewidth 0 setlinejoin");
-        write("10 setmiterlimit [ ] 0 setdash newpath");
-        write("/languagelevel where           % If level not equal to 1 then");
-        write("{pop languagelevel             % set strokeadjust and");
-        write("1 ne                           % overprint to their defaults.");
-        write("{false setstrokeadjust false setoverprint");
-        write("} if");
-        write("} if");
-        write("} bind def");
-
-        write("/EndEPSF { %def");
-        write("count op_count sub {pop} repeat            % Clean up stacks");
-        write("countdictstack dict_count sub {end} repeat");
-        write("b4_Inc_state restore");
-        write("} bind def");
-        write("%%EndResource");
-
-        write("%%EndSetup");
-        write("FOPFonts begin");
+        gen.writeDSCComment(DSCConstants.END_SETUP);
     }
 
     /**
      * @see org.apache.fop.render.Renderer#stopRenderer()
      */
     public void stopRenderer() throws IOException {
-        write("%%Trailer");
-        write("%%EOF");
-        this.out.flush();
+        gen.writeDSCComment(DSCConstants.TRAILER);
+        gen.writeDSCComment(DSCConstants.PAGES, new Integer(this.currentPageNumber));
+        gen.writeDSCComment(DSCConstants.EOF);
+        gen.flush();
+    }
+
+    /**
+     * @see org.apache.fop.render.Renderer#renderPage(PageViewport)
+     */
+    public void renderPage(PageViewport page)
+            throws IOException, FOPException {
+        getLogger().debug("renderPage(): " + page);
+        
+        this.currentPageNumber++;
+        gen.writeDSCComment(DSCConstants.PAGE, new Object[] 
+                {page.getPageNumber(),
+                 new Integer(this.currentPageNumber)});
+        final Integer zero = new Integer(0);
+        final Long pagewidth = new Long(Math.round(page.getViewArea().getWidth() / 1000f));
+        final Long pageheight = new Long(Math.round(page.getViewArea().getHeight() / 1000f));
+        gen.writeDSCComment(DSCConstants.PAGE_BBOX, new Object[]
+                {zero, zero, pagewidth, pageheight});
+        gen.writeDSCComment(DSCConstants.BEGIN_PAGE_SETUP);         
+        gen.writeln("FOPFonts begin");
+        gen.writeln("[1 0 0 -1 0 " + pageheight + "] concat");
+        gen.writeln("0.001 0.001 scale");
+        gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);         
+        
+        //Process page
+        super.renderPage(page);
+        
+        writeln("showpage");        
+        gen.writeDSCComment(DSCConstants.PAGE_TRAILER);
+        gen.writeDSCComment(DSCConstants.END_PAGE);
+    }
+
+    protected void paintText(int rx, int bl, String text, Font font) {
+        saveGraphicsState();
+        writeln("1 0 0 -1 " + rx + " " + bl + " Tm");
+        
+        int initialSize = text.length();
+        initialSize += initialSize / 2;
+        StringBuffer sb = new StringBuffer(initialSize);
+        sb.append("(");
+        for (int i = 0; i < text.length(); i++) {
+            final char c = text.charAt(i);
+            final char mapped = font.mapChar(c);
+            gen.escapeChar(mapped, sb);
+        }
+        sb.append(") t");
+        writeln(sb.toString());
+        restoreGraphicsState();
+    }
+
+    /**
+     * @see org.apache.fop.render.Renderer#renderWord(Word)
+     */
+    public void renderWord(Word area) {
+        String fontname = (String)area.getTrait(Trait.FONT_NAME);
+        int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
+
+        // This assumes that *all* CIDFonts use a /ToUnicode mapping
+        Font f = (Font)fontInfo.getFonts().get(fontname);
+        
+        //Determine position
+        int rx = currentBlockIPPosition;
+        int bl = currentBPPosition + area.getOffset();
+
+        useFont(fontname, fontsize);
+        
+        paintText(rx, bl, area.getWord(), f);
+
+/*
+        String psString = null;
+        if (area.getFontState().getLetterSpacing() > 0) {
+            //float f = area.getFontState().getLetterSpacing() * 1000 / this.currentFontSize;
+            float f = area.getFontState().getLetterSpacing();
+            psString = (new StringBuffer().append(f).append(" 0.0 (")
+              .append(sb.toString()).append(") A")).toString();
+        } else {
+            psString = (new StringBuffer("(").append(sb.toString())
+              .append(") t")).toString();
+        }
+
+
+        // System.out.println("["+s+"] --> ["+sb.toString()+"]");
+
+        // comment("% --- InlineArea font-weight="+fontWeight+": " + sb.toString());
+        useFont(fs.getFontName(), fs.getFontSize());
+        useColor(area.getRed(), area.getGreen(), area.getBlue());
+        if (area.getUnderlined() || area.getLineThrough()
+                || area.getOverlined())
+            write("ULS");
+        write(psString);
+        if (area.getUnderlined())
+            write("ULE");
+        if (area.getLineThrough())
+            write("SOE");
+        if (area.getOverlined())
+            write("OLE");
+        this.currentXPosition += area.getContentWidth();
+        */
+        super.renderWord(area); //Updates IPD
     }
 
+
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport, List)
+     */
+    protected void renderBlockViewport(BlockViewport bv, List children) {
+        // clip and position viewport if necessary
+
+        // save positions
+        int saveIP = currentIPPosition;
+        int saveBP = currentBPPosition;
+        String saveFontName = currentFontName;
+
+        CTM ctm = bv.getCTM();
+
+        if (bv.getPositioning() == Block.ABSOLUTE) {
+
+            currentIPPosition = 0;
+            currentBPPosition = 0;
+
+            //closeText();
+            endTextObject();
+
+            if (bv.getClip()) {
+                saveGraphicsState();
+                int x = bv.getXOffset() + containingIPPosition;
+                int y = bv.getYOffset() + containingBPPosition;
+                int width = bv.getWidth();
+                int height = bv.getHeight();
+                clip(x, y, width, height);
+            }
+
+            CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
+            ctm = tempctm.multiply(ctm);
+
+            startVParea(ctm);
+            handleBlockTraits(bv);
+            renderBlocks(children);
+            endVParea();
+
+            if (bv.getClip()) {
+                restoreGraphicsState();
+            }
+            beginTextObject();
+
+            // clip if necessary
+
+            currentIPPosition = saveIP;
+            currentBPPosition = saveBP;
+        } else {
+
+            if (ctm != null) {
+                currentIPPosition = 0;
+                currentBPPosition = 0;
+
+                //closeText();
+                endTextObject();
+
+                double[] vals = ctm.toArray();
+                //boolean aclock = vals[2] == 1.0;
+                if (vals[2] == 1.0) {
+                    ctm = ctm.translate(-saveBP - bv.getHeight(), -saveIP);
+                } else if (vals[0] == -1.0) {
+                    ctm = ctm.translate(-saveIP - bv.getWidth(), -saveBP - bv.getHeight());
+                } else {
+                    ctm = ctm.translate(saveBP, saveIP - bv.getWidth());
+                }
+            }
+
+            // clip if necessary
+            if (bv.getClip()) {
+                if (ctm == null) {
+                    //closeText();
+                    endTextObject();
+                }
+                saveGraphicsState();
+                int x = bv.getXOffset();
+                int y = bv.getYOffset();
+                int width = bv.getWidth();
+                int height = bv.getHeight();
+                clip(x, y, width, height);
+            }
+
+            if (ctm != null) {
+                startVParea(ctm);
+            }
+            handleBlockTraits(bv);
+            renderBlocks(children);
+            if (ctm != null) {
+                endVParea();
+            }
+
+            if (bv.getClip()) {
+                restoreGraphicsState();
+                if (ctm == null) {
+                    beginTextObject();
+                }
+            }
+            if (ctm != null) {
+                beginTextObject();
+            }
+
+            currentIPPosition = saveIP;
+            currentBPPosition = saveBP;
+            currentBPPosition += (int)(bv.getHeight());
+        }
+        currentFontName = saveFontName;
+    }
+    
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM)
+     */
+    protected void startVParea(CTM ctm) {
+        // Set the given CTM in the graphics state
+        //currentState.push();
+        //currentState.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
+
+        saveGraphicsState();
+        // multiply with current CTM
+        //currentStream.add(CTMHelper.toPDFString(ctm) + " cm\n");
+        final double matrix[] = ctm.toArray();
+        writeln("[" + gen.formatDouble(matrix[0]) 
+                + " " + gen.formatDouble(matrix[1])
+                + " " + gen.formatDouble(matrix[2]) 
+                + " " + gen.formatDouble(matrix[3])
+                + " " + gen.formatDouble(matrix[4])
+                + " " + gen.formatDouble(matrix[5]) + "] concat");
+        
+        // Set clip?
+        beginTextObject();        
+    }
+
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#endVParea()
+     */
+    protected void endVParea() {
+        endTextObject();
+        restoreGraphicsState();
+        //currentState.pop();
+    }
+
+    
+    /**
+     * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D)
+     */
+    public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
+        Document doc = fo.getDocument();
+        String ns = fo.getNameSpace();
+        renderDocument(doc, ns, pos);
+    }
+
+    public void renderDocument(Document doc, String ns, Rectangle2D pos) {
+        RendererContext context;
+        context = new RendererContext(MIME_TYPE);
+        context.setUserAgent(userAgent);
+
+        /*
+        context.setProperty(PDFXMLHandler.PDF_DOCUMENT, pdfDoc);
+        context.setProperty(PDFXMLHandler.OUTPUT_STREAM, ostream);
+        context.setProperty(PDFXMLHandler.PDF_STATE, currentState);
+        context.setProperty(PDFXMLHandler.PDF_PAGE, currentPage);
+        context.setProperty(PDFXMLHandler.PDF_CONTEXT, 
+                    currentContext == null ? currentPage: currentContext);
+        context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext);
+        context.setProperty(PDFXMLHandler.PDF_STREAM, currentStream);
+        context.setProperty(PDFXMLHandler.PDF_XPOS,
+                            new Integer(currentBlockIPPosition + (int) pos.getX()));
+        context.setProperty(PDFXMLHandler.PDF_YPOS,
+                            new Integer(currentBPPosition + (int) pos.getY()));
+        context.setProperty(PDFXMLHandler.PDF_FONT_INFO, fontInfo);
+        context.setProperty(PDFXMLHandler.PDF_FONT_NAME, currentFontName);
+        context.setProperty(PDFXMLHandler.PDF_FONT_SIZE,
+                            new Integer(currentFontSize));
+        context.setProperty(PDFXMLHandler.PDF_WIDTH,
+                            new Integer((int) pos.getWidth()));
+        context.setProperty(PDFXMLHandler.PDF_HEIGHT,
+                            new Integer((int) pos.getHeight()));
+        */           
+        userAgent.renderXML(context, doc, ns);
+
+    }
+
+    
+
+
 }
diff --git a/src/org/apache/fop/render/ps/PSStream.java b/src/org/apache/fop/render/ps/PSStream.java
deleted file mode 100644 (file)
index 2e1c624..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * $Id$
- * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved.
- * For details on use and redistribution please refer to the
- * LICENSE file included with these sources.
- */
-package org.apache.fop.render.ps;
-
-import java.io.OutputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-
-/**
- * PSStream is used to to output PostScript code from the PostScript renderer.
- */
-public class PSStream extends FilterOutputStream {
-
-    /** @see java.io.FilterOutputStream **/
-    public PSStream(OutputStream out) {
-        super(out);
-    }
-
-
-    /**
-     * Writes a PostScript command to the stream.
-     *
-     * @param cmd              The PostScript code to be written.
-     * @exception IOException  In case of an I/O problem
-     */
-    public void write(String cmd) throws IOException {
-        if (cmd.length() > 255) {
-            throw new RuntimeException("PostScript command exceeded limit of 255 characters");
-        }
-        write(cmd.getBytes("US-ASCII"));
-        write('\n');
-    }
-
-
-    /**
-     * Writes encoded data to the PostScript stream.
-     *
-     * @param cmd              The encoded PostScript code to be written.
-     * @exception IOException  In case of an I/O problem
-     */
-    public void writeByteArr(byte[] cmd) throws IOException {
-        write(cmd);
-        write('\n');
-    }
-
-}