import java.awt.*;
import java.awt.image.*;
import java.lang.Math;
import java.applet.Applet;

class mandelgenerator extends Thread
{
    int iterations = 80;        // can be changed if image is bigger

    int pix[] = new int[256*256]; // used to store the mandel
    int pix2[] = new int[256*256];  // used to quick-clear pix
    int sqrs[] = new int[256]; // this gains a few percent in speed
    int hw[] = new int[256];    // start on which pixel on row
    int re = 2;
    int im = 4;

// used to store my colors
    byte redv[] = new byte[iterations + 5];
    byte greenv[] = new byte[iterations + 5];
    byte bluev[] = new byte[iterations + 5];
    byte alfas[] = new byte[iterations + 5];
    IndexColorModel cm;         // Palette for my image
    Image img;
    
    int ingvar = 0;  // counter for re and im
    Mandel j3 = null;
    
    mandelgenerator (Mandel j)
    {
	j3 = j;
	
	// build the palette 
	buildpalette(0,0,255,255,0,0,10,0);
	buildpalette(0,255,0,0,0,255,30,10);
	buildpalette(0,0,0,0,255,0,45,40);
	
	// calculate outer bounds of fractal (need only be done once)
        // and build sqaure vector.
 	for (int i=0;i < 128; i++)
	{
	    hw[i] = hw[255 - i] = (int) (128 * Math.sin(Math.acos ((128-i)/128.0)));
	    sqrs[127 - i] = sqrs [128 + i] = i * i;
	}
	for (int i = 0; i < 256 * 256; i++)
	    pix[i] = pix2[i] = 0;
	
	// create colormap and image
	cm = new IndexColorModel(8, iterations, redv, greenv, bluev);
	img = j3.createImage(new MemoryImageSource(256, 256, cm, pix, 0, 256));
    }
    
    void buildpalette (int r2,int g2,int b2,   // to these values 
		       int r,int g,int b,      // from these
		       int n,int start){       // how many, starting from 
	int m=n;
	for (int i = 0; i < n; i++,m--){
	    redv[i + start] =(byte)(r2*i/n + r*m/n);
	    greenv[i + start] = (byte)(g2*i/n + g*m/n);
	    bluev[i + start] = (byte)(b2*i/n + b*m/n);
	    alfas[i + start] = (byte)127;
	}
    }
    
    int 
    iterate(int x, int y, int iter){
	int it;
	int nx, ny;
	int v = x - (y<<8);
	
	if (iter < iterations) {               
	    ny = (x * y + im) >> 5; // here we get errors in division
	    it = 1;
	    if (ny < 128 && ny > -128) {
		nx = (sqrs[x + 127] - sqrs[y + 127] + re) >> 6; 
		if ( nx <= hw[ny + 127] && nx >= -hw[ny + 127]) 
		    it += iterate (nx, ny, iter + 1) ;    
	    }
	}
	else 
	    it = iterations;
	return it;
    }
    
    
    public 
    void run() {
	for (int y = 0; y < 128; y++){
	    if ((y % 16) == 0) {
		img = j3.createImage(new MemoryImageSource(256, 256, cm, pix, 0, 256));
		j3.setImage (img);
	    }
	    for (int x = -hw[y + 127]; x < hw[y+127] + 1; x++){
		re = x << 6;
		im = y << 5;
		pix[x - (y << 8) + 127*257] =
		    pix[x + (y << 8) + 127*257] = 
		    iterate (x, y, 0);
	    }
	}
	img = j3.createImage(new MemoryImageSource(256, 256, cm, pix, 0, 256));
	j3.setImage (img);
    }
}

public class Mandel extends java.applet.Applet {
    mandelgenerator mandel = null;
    boolean mandelsuspended = false;
    Image img = null;

    public 
    void init() {
	resize(256,256);              // Set mandel window size
	mandel = new mandelgenerator (this);
	mandel.start ();
    }
    public 
    void start() {
	if(mandel == null)
	{
	    mandel = new mandelgenerator (this);
	    mandel.start();	
	}
    }
    public 
    void stop() {
	mandel.stop();
	mandel = null;
    }    
    public 
    void update(Graphics g) {
	paint (g);
    } 
    public 
    void paint(Graphics g) {
	if (img != null)
	    g.drawImage(img,0,0,Color.black,this);
    }
    public 
    void setImage (Image img) {
	this.img = img;
	repaint ();
    }
    public
    boolean mouseDown (Event e, int x, int y){
	if (mandelsuspended){
	    mandel.resume();
	}	
	else {
	    mandel.suspend();
	}
	mandelsuspended = !mandelsuspended;
	return true;
    }
}

