
import java.awt.*;
import java.awt.event.*;

/**
 * Recursive image rotation.
 *
 * @author Arthur van Hoff
 */
public class RotateApplet 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) {
	if ((w > 1) && (h > 1)) {
	    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);

	    repaint(100);

	    rotate(g, x, y, w2, h2);
	    rotate(g, x + w2, y, w2, h2);
	    rotate(g, x + w2, y + h2, w2, h2);
	    rotate(g, x, y + 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);

	rotate(g, 0, 0, d.width, d.height);
	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();
		}
	}
}
