
import java.awt.*;
import java.awt.event.*;

/**
 * Iterative image rotation.
 *
 * @author Arthur van Hoff
 */
public class RotateApplet2 extends java.applet.Applet
   implements Runnable, MouseListener {
    Thread worker;
    Image img;

    /**
     * Load the image. Should be a square image, a power of 2
     * on each side.
     */
    public void init() {
	String str = getParameter("img");
	if (str == null) {
	    str = "test.gif";
	}
	img = getImage(getDocumentBase(), str);
	addMouseListener(this);
    }

    public void paint(Graphics g) {
	g.drawImage(img, 0, 0, this);
    }
    public void update(Graphics g) {
	g.drawImage(img, 0, 0, this);
    }
    
    /**
     * Recursively rotate the image.
     */
    void rotate(Graphics g, int x, int y, int w, int h) {
	int w2 = w / 2;
	int h2 = h / 2;

	g.copyArea(x, y, w2, h, w2, 0);
	g.copyArea(x + w2, y, w2, h, -w2, 0);
	g.copyArea(x, y, w2, h, w2, 0);
	
	g.copyArea(x, y, w2, h2, w2, h2);
	g.copyArea(x + w2, y + h2, w2, h2, -w2, -h2);
	g.copyArea(x, y, w2, h2, w2, h2);
    }

    /**
     * Prepare for rotating the image
     */
    public void run() {
	Dimension d = getSize();
	Image src = img;
	img = createImage(d.width, d.height);

	Graphics g = img.getGraphics();
	g.setColor(getBackground());
	g.fillRect(0, 0, d.width, d.height);
	g.drawImage(src, 0, 0, null);
	g.setXORMode(Color.black);

	for (int w = d.width, h = d.height ; (w > 1) && (h > 1) ; w /= 2, h /= 2) {
	    for (int y = 0 ; y < d.height ; y += h) {
		for (int x = 0 ; x < d.width ; x += w) {
		    rotate(g, x, y, w, h);
		}
		repaint(100);
	    }
	}
	worker = null;
    }

	public void destroy() {
		worker = null;
	}

	/*
     * Mouse methods
     */

	public void mousePressed(MouseEvent e) {
	}

	public void mouseReleased(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseClicked(MouseEvent e) {
		if (worker == null) {
			worker = new Thread(this);  
			worker.setPriority(Thread.NORM_PRIORITY-2);
			worker.start();
		}
	}
}
