package ps;

import java.io.*;
import java.awt.*;
import java.awt.geom.*;
import java.text.*;

public class ToPS {
    PrintStream out;
    DecimalFormat formatter;

    /**
       Sets up an output .ps file
    */
    
    public ToPS(String filename) throws FileNotFoundException {
	out = new PrintStream(new FileOutputStream(filename));
	formatter = new DecimalFormat("######.####");
    }

    /**
       Sets up an output .eps file with given BoundingBox
    */
    
    public ToPS(String filename, int llx, int lly, int urx, int ury) 
	throws FileNotFoundException {
	this(filename);
	out.println("%!PS-Adobe-3.0 EPSF-3.0");
	out.println("%%BoundingBox: " + llx + " " + lly + " " + urx + " " + ury);
    }

    /**
       Sets the number of significant digits to use when writing floats
       and doubles
    */
    
    public void setDigits(int n) {
	if (n < 0) return;
	String s = "######.";
	while(n > 0) {
	    s += "#";
	    n--;
	}
	formatter = new DecimalFormat(s);
    }

    public void setgray(float g) {
	out.println(formatter.format(g) + " setgray");
    }

    public void setrgbcolor(Color c) {
	float[] comps = c.getComponents(null);
	setrgbcolor(comps[0], comps[1], comps[2]);
    }

    public void setrgbcolor(float r, float g, float b) {
	out.println(formatter.format(r) + " " +
		    formatter.format(g) + " " +
		    formatter.format(b) + " setrgbcolor");
    }
    
    public void gsave() {
	out.println("gsave");
    }

    public void grestore() {
	out.println("grestore");
    }

    public void stroke() {
	out.println("stroke");
    }

    public void fill() {
	out.println("fill");
    }

    public void translate(double x, double y) {
	out.println(formatter.format(x) + " " + formatter.format(y) + " translate");
    }

    public void scale(double sx, double sy) {
	out.println(formatter.format(sx) + " " + formatter.format(sy) + " scale");
    }

    public void rotate(double angle) {
	out.println(formatter.format(angle) + " rotate");
    }

    public void concat(AffineTransform at) {
	double[] coeffs = new double[6];
	at.getMatrix(coeffs);
	out.print("[");
	for (int i = 0; i < 6; i++) out.print(formatter.format(coeffs[0]) + " ");
	out.println("] concat");
    }

    /**
       Reads a file and copies it into the PostScript file.  This
       could be useful for reading in a library of procedures.
    */

    public void copyFile(String filename) 
	throws FileNotFoundException, IOException {
	BufferedReader in = new BufferedReader(new FileReader(filename));
	for (String line = in.readLine(); line != null; line = in.readLine())
	    out.println(line);
    }

    public void newpath() {
	out.println("newpath");
    }

    public void clip() {
	out.println("clip");
    }

    public void showpage() {
	out.println("showpage");
    }

    public void setlinewidth(float w) {
	out.println(formatter.format(w) + " setlinewidth");
    }

    public void setmiterlimit(float l) {
	out.println(formatter.format(l) + " setmiterlimit");
    }

    public void setdash(float[] d, float offset) {
	out.print("[");
	for (int i = 0; i < d.length; i++) 
	    out.print(formatter.format(d[i]) + " ");
	out.println("] " + formatter.format(offset) + " setdash");
    }

    /**
       Writes a String into the PostScript file.  You could use this
       if there are PostScript commands not given in this class.
    */

    public void writeString(String s) {
	out.println(s);
    }

    public void appendToPath(Shape shape, AffineTransform transform) {
	appendToPath(transform.createTransformedShape(shape));
    }

    public void appendToPath(Shape shape) {
	PathIterator iterator = shape.getPathIterator(null);
	float lastX = 0, lastY = 0;
	while(iterator.isDone() == false) {
	    float[] coords = new float[6];
	    int type = iterator.currentSegment(coords);
	    switch(type) {
	    case(PathIterator.SEG_MOVETO): {
		out.println(formatter.format(coords[0]) + " " +
			    formatter.format(coords[1]) + " moveto");
		lastX = coords[0];
		lastY = coords[1];
		break;
	    }
	    case(PathIterator.SEG_LINETO): {
		out.println(formatter.format(coords[0]) + " " +
			    formatter.format(coords[1]) + " lineto");
		lastX = coords[0];
		lastY = coords[1];
		break;
	    }
	    case(PathIterator.SEG_QUADTO): {
		out.println(formatter.format(2.*coords[0]/3. + lastX/3.) + " " +
			    formatter.format(2.*coords[1]/3. + lastY/3.) + " " +
			    formatter.format(2.*coords[0]/3. + coords[2]/3) + " " +
			    formatter.format(2.*coords[1]/3. + coords[3]/3) + " " +
			    formatter.format(coords[2]) + " " + 
			    formatter.format(coords[3]) + " " +
			    " curveto");
		lastX = coords[2];
		lastY = coords[3];
		break;
	    }
	    case(PathIterator.SEG_CUBICTO): {
		for (int i = 0; i < 6; i++) 
		    out.print(formatter.format(coords[i]) + " ");
		out.println("curveto");
		lastX = coords[4];
		lastY = coords[5];
		break;
	    }
	    case(PathIterator.SEG_CLOSE): {
		out.println("closepath");
		break;
	    }
	    }
	    iterator.next();
	}


    }

    

	




}
