//

import java.applet.Applet;
import java.util.*;
import java.awt.*;
import java.lang.Double;

//-------------------------

class AIClass{
int x, y, height, width;
int dX, dY, dHeight, dWidth;
float maxSteps = 50;
float flatness = (float) 1.0;

	public void size(int x,int  y,int  height,int  width){
		this.x = x;
		this.y = y;
		this.height = height;
		this.width = width;
	}
	
	public void dSize(int x,int  y,int  height,int  width){
		this.x = dX;
		this.y = dY;
		this.height = dHeight;
		this.width = dWidth;
	}
	
	public void AddAColor(Vector ColorList, int C, int M, int Y, int K){
		int R, G, B;
		Color curColor;

		R = RofCMYK(C, M, Y, K);
		G = GofCMYK(C, M, Y, K);
		B = BofCMYK(C, M, Y, K);
		curColor = new Color(R, G, B);		
		ColorList.addElement(curColor);
	}
	
	public Color SetCMYKColor( float C, float M, float Y, float K){
		int R, G, B;
		Color theColor;

		R = RofCMYK((int) (C*100.0),(int)  (M*100.0),(int)  (Y*100.0),(int)  (K*100.0));
		G = GofCMYK((int) (C*100.0),(int)  (M*100.0),(int)  (Y*100.0),(int)  (K*100.0));
		B = BofCMYK((int) (C*100.0),(int)  (M*100.0),(int)  (Y*100.0),(int)  (K*100.0));
		theColor = new Color(R, G, B);
		return theColor;
			
	}
	
	public Color SetCustomColor(float T, float C, float M, float Y, float K){
		int R, G, B;
		float oneMinusT;
		Color theColor;

		oneMinusT = ((float) 1.0 - T);
		R = RofCMYK((int) (C*100 * oneMinusT),(int) (M*100 * oneMinusT),(int) (Y*100 * oneMinusT),(int) (K*100 * oneMinusT));
		G = GofCMYK((int) (C*100 * oneMinusT),(int) (M*100 * oneMinusT),(int) (Y*100 * oneMinusT),(int) (K*100 * oneMinusT));
		B = BofCMYK((int) (C*100 * oneMinusT),(int) (M*100 * oneMinusT),(int) (Y*100 * oneMinusT),(int) (K*100 * oneMinusT));
		theColor = new Color(R, G, B);
		return theColor;
			
	}
	
	public int RofCMYK(int C, int M, int Y, int K){
		int hue;
		hue = ((100 - C) * 255 / 100);
		return (int) hue - ((hue * K)/ 100);
	
	}
	
	public int GofCMYK(int C, int M, int Y, int K){
		int hue;
		hue = ((100 - M) * 255 / 100);
		return (int) hue - ((hue * K)/ 100);
	}
	
	public int BofCMYK(int C, int M, int Y, int K){
		int hue;
		hue = ((100 - Y) * 255 / 100);
		return (int) hue - ((hue * K)/ 100);
	}
	
	public Polygon buildSimpleBezierPolygon(Vector curve, float yInvert, float top, float left, float bottom, float right, float xo, float yo, float xs, float ys){
		Polygon thePolygon;
		AIPathSegment curSegment1, curSegment2;
		double V0x, V0y, V1x, V1y, V2x, V2y, V3x, V3y; 
		double ddx, ddy;
		double u, oneMinusU, threeU, threeUU, uCubed;
		//double dist1, dist2, dist3, dist4, dist;
		int dist;
		int numSegments, numSteps;
		int i, j;
		int x, y;
	
		numSegments = curve.size();
		thePolygon = new Polygon();
		for (i = 0; i < (numSegments - 1); i++){
			curSegment1 = (AIPathSegment) curve.elementAt(i);
			curSegment2 = (AIPathSegment) curve.elementAt(i + 1);
			// a segment has six numbers, px, py, ix, iy, ox, oy
			// the V values are set according to Bezier's rules
			V0x = Math.round(((curSegment1.px - left) * xs / 100.0) + xo); // segment 1 x point
			V0y = Math.round(((top - curSegment1.py) * ys /100.0) + yo); // segment 1 y point
			V1x = Math.round(((curSegment1.ox - left) * xs / 100.0) + xo); // segment 1 out x point
			V1y = Math.round(((top - curSegment1.oy) * ys /100.0) + yo); // segment 1 out x point
			V2x = Math.round(((curSegment2.ix - left) * xs / 100.0) + xo); // segment 2 in x point
			V2y = Math.round(((top - curSegment2.iy) * ys /100.0) + yo); // segment 2 in y point
			V3x = Math.round(((curSegment2.px - left) * xs / 100.0) + xo); // segment 2 x point
			V3y = Math.round(((top - curSegment2.py) * ys /100.0) + yo); // segment 2 x point
			
			//build the polygon by adding segments' points according to Bezier's rules
			dist = (int) Math.sqrt(((V0x - V1x) * (V0x - V1x)) + ((V0y - V1y) * (V0y - V1y)));
			dist = dist + (int) Math.sqrt(((V1x - V2x) * (V1x - V2x)) + ((V1y - V2y) * (V1y - V2y)));
			dist = dist + (int) Math.sqrt(((V2x - V3x) * (V2x - V3x)) + ((V2y - V3y) * (V2y - V3y)));

			numSteps = Math.round((dist / flatness));
			
			for (j = 0; j <= (numSteps - 0); j = j + 1){
				u = ((double) j / (double) numSteps);
				oneMinusU = 1.0 - u;
				threeU = 3.0 * u;
				threeUU = threeU * u;
				uCubed = u * u * u;

				/* v1 straight from the book (round off errors!)
				dx = new Double((V0x * (oneMinusU * oneMinusU * oneMinusU)) +
					 (V1x * 3.0 * u * (oneMinusU * oneMinusU)) +
					 (V2x * 3.0 * u * u * oneMinusU) +
					 (V3x * u * u * u));
				*/
				// v2 Doing some factoring...better
				ddx = V0x * oneMinusU * oneMinusU * oneMinusU; 
				ddx = ddx + (V1x * threeU * oneMinusU * oneMinusU); 
				ddx = ddx + (V2x * threeUU * oneMinusU);
				ddx = ddx + (V3x * uCubed);
					 
				//x = dx.intValue();
				x = (int) Math.round(ddx);
				
				/* v1 straight from the book (round off errors!)
				dy = new Double((V0y * (oneMinusU * oneMinusU * oneMinusU)) +
					 (V1y * 3.0 * u * (oneMinusU * oneMinusU)) +
					 (V2y * 3.0 * u * u * oneMinusU) +
					 (V3y * u * u * u));
				*/
				// v2 Doing some factoring...better
				ddy = V0y * oneMinusU * oneMinusU * oneMinusU; 
				ddy = ddy + (V1y * threeU * oneMinusU * oneMinusU); 
				ddy = ddy + (V2y * threeUU * oneMinusU);
				ddy = ddy + (V3y * uCubed);
	 
				//y = dy.intValue();
				y = (int) Math.round(ddy);

					 
				thePolygon.addPoint(x, y);
			}
		}
		return thePolygon;
	}
	
	public Polygon buildCompoundBezierPolygon(Vector compoundCurve, float yInvert, float top, float left, float bottom, float right, float xo, float yo, float xs, float ys){
		Vector curve;
		int numCurves;
		Vector lastPoints;
		AIPoint curPoint;
		int numPoints = 0;
		
		Polygon thePolygon;
		AIPathSegment curSegment1, curSegment2;
		double V0x, V0y, V1x, V1y, V2x, V2y, V3x, V3y; 
		double ddx, ddy;
		double u, oneMinusU, threeU, threeUU, uCubed;
		int dist;
		int numSteps;
		int numSegments;
		int i, j, k;
		int x, y;
			
		lastPoints = new Vector();	
			
		numCurves = compoundCurve.size();
		thePolygon = new Polygon();
		x = 0;
		y = 0;
		
		for (k = 0; k < numCurves; k++){				
			curve = (Vector) compoundCurve.elementAt(k);
			numSegments = curve.size();
			for (i = 0; i < (numSegments - 1); i++){
				curSegment1 = (AIPathSegment) curve.elementAt(i);
				curSegment2 = (AIPathSegment) curve.elementAt(i + 1);
				// a segment has six numbers, px, py, ix, iy, ox, oy
				// the V values are set according to Bezier's rules
				V0x = Math.round(((curSegment1.px - left) * xs / 100.0) + xo); // segment 1 x point
				V0y = Math.round(((top - curSegment1.py) * ys /100.0) + yo); // segment 1 y point
				V1x = Math.round(((curSegment1.ox - left) * xs / 100.0) + xo); // segment 1 out x point
				V1y = Math.round(((top - curSegment1.oy) * ys /100.0) + yo); // segment 1 out x point
				V2x = Math.round(((curSegment2.ix - left) * xs / 100.0) + xo); // segment 2 in x point
				V2y = Math.round(((top - curSegment2.iy) * ys /100.0) + yo); // segment 2 in y point
				V3x = Math.round(((curSegment2.px - left) * xs / 100.0) + xo); // segment 2 x point
				V3y = Math.round(((top - curSegment2.py) * ys /100.0) + yo); // segment 2 x point
				
				//build the polygon by adding segments' points according to Bezier's rules
				dist = (int) Math.sqrt(((V0x - V1x) * (V0x - V1x)) + ((V0y - V1y) * (V0y - V1y)));
				dist = dist + (int) Math.sqrt(((V1x - V2x) * (V1x - V2x)) + ((V1y - V2y) * (V1y - V2y)));
				dist = dist + (int) Math.sqrt(((V2x - V3x) * (V2x - V3x)) + ((V2y - V3y) * (V2y - V3y)));

				//dist = dist4;
				numSteps = (int) Math.round((dist / flatness));
				//numSteps = maxSteps;

				for (j = 0 ; j <= numSteps; j = j + 1){
					u = ((double) j / (double) numSteps);
					oneMinusU = 1.0 - u;
					threeU = 3.0 * u;
					threeUU = threeU * u;
					uCubed = u * u * u;
					
					/* v1 straight from the book (round off errors!)
					dx = new Double((V0x * (oneMinusU * oneMinusU * oneMinusU)) +
						 (V1x * 3.0 * u * (oneMinusU * oneMinusU)) +
						 (V2x * 3.0 * u * u * oneMinusU) +
						 (V3x * u * u * u));
					*/
					// v2 Doing some factoring...better
					ddx = V0x * oneMinusU * oneMinusU * oneMinusU; 
					ddx = ddx + (V1x * threeU * oneMinusU * oneMinusU); 
					ddx = ddx + (V2x * threeUU * oneMinusU);
					ddx = ddx + (V3x * uCubed);
					 
					x = (int) Math.round(ddx);
						 
					/* v1 straight from the book (round off errors!)
					dy = new Double((V0y * (oneMinusU * oneMinusU * oneMinusU)) +
						 (V1y * 3.0 * u * (oneMinusU * oneMinusU)) +
						 (V2y * 3.0 * u * u * oneMinusU) +
						 (V3y * u * u * u));
					*/
					// v2 Doing some factoring...better
					ddy = V0y * oneMinusU * oneMinusU * oneMinusU; 
					ddy = ddy + (V1y * threeU * oneMinusU * oneMinusU); 
					ddy = ddy + (V2y * threeUU * oneMinusU);
					ddy = ddy + (V3y * uCubed);
					 
					y = (int) Math.round(ddy);
						 
					thePolygon.addPoint(x, y);
				}
			}
			//we want to save the last point so we can back out of the path and end on the 
			//last point of the first path.
			numPoints++;
			curPoint = new AIPoint(x, y);
			lastPoints.addElement(curPoint);			
		}
		// just add the closing points for compound paths, skipping last point
		for (i = (numPoints - 1); i >= 1; i--){
			curPoint = (AIPoint) lastPoints.elementAt(i-1);
			thePolygon.addPoint(curPoint.x, curPoint.y);
		}
		return thePolygon;
	}
}

public class AIPathSegment {
	float px, py, ix, iy, ox, oy;
	
	public AIPathSegment(){
		this.px = 0;
		this.py = 0;
		this.ix = 0;
		this.iy = 0;
		this.ox = 0;
		this.oy = 0;

	}
	
	public AIPathSegment(float px, float py, float ix, float iy, float ox, float oy){
		this.px = px;
		this.py = py;
		this.ix = ix;
		this.iy = iy;
		this.ox = ox;
		this.oy = oy;
	}
	
	public AIPathSegment(int px, int py, int ix, int iy, int ox, int oy){
		this.px = (float) px;
		this.py = (float) py;
		this.ix = (float) ix;
		this.iy = (float) iy;
		this.ox = (float) ox;
		this.oy = (float) oy;
	}
	
	public void setValues(int px, int py, int ix, int iy, int ox, int oy){
		this.px = px;
		this.py = py;
		this.ix = ix;
		this.iy = iy;
		this.ox = ox;
		this.oy = oy;
	}
	
	
}public class AIPoint {
	int x, y;
	
	public AIPoint(){
		this.x = 0;
		this.y = 0;
	}
	
	public AIPoint(int x, int y){
		this.x = x;
		this.y = y;
	}
	
	public void setValues(int x, int y){
		this.x = x;
		this.y = y;
 	}
	
	
}
//