/*
 * @(#)RainbowHR.java      
 *
 * Copyright (c) 1996 NAKAGAWA Masami
 *
 * Permission to use, copy, modify, and distribute this software
 * for NON-COMMERCIAL purpose and without fee is hereby granted. 
 */

import java.applet.Applet;
import java.awt.*;
import java.util.*;

/**
 * A rainbow-like HR class to decorate a Web page instead of HR tag.
 * 
 * @author	NAKAGAWA Masami
 * @version	1.2, 3 Dec 1996
 */
public class RainbowHR extends Applet implements Runnable {
	final int _blendNum = 50;
	Thread thread;
	int boundX;
	int speed = 8;
	int repeat = 1;
	Image offImage;
	Graphics offScreen;
	Color[] color;
	Dimension mySize;

	public void init() {
		mySize = size();
		String s = getParameter("speed");
		if (s != null) speed = Integer.parseInt(s) % mySize.width;
		s = getParameter("color");
		if (s != null) {
			StringTokenizer st = new StringTokenizer(s, "|");
			color = new Color[st.countTokens()];
			for (int i = 0; i < color.length; i++) {
				color[i] = new Color(Integer.valueOf(st.nextToken(), 16).intValue());
			}
		}
		s = getParameter("repeat");
		if (s != null) repeat = Integer.parseInt(s);
		if (repeat < 1) repeat = 1;
		offImage = createImage(mySize.width, mySize.height);
		offScreen = offImage.getGraphics();
		if (color == null) {
			for (float hue=0.0f;hue<1.0f;hue+=0.01f) {
				offScreen.setColor(Color.getHSBColor(hue, 1.0f, 1.0f));
				int x = (int)(mySize.width*hue/repeat);
				offScreen.fillRect(x, 0, mySize.width-x, mySize.height);
			}
		} else {
			for (int i = 0; i < color.length; i++) {
				Color[] c = blendColor(color[i], color[(i+1)%color.length], _blendNum);
				for (int j = 0; j < _blendNum; j++) {
					offScreen.setColor(c[j]);
					int x = (j*mySize.width/color.length/_blendNum + i*mySize.width/color.length)/repeat;
					offScreen.fillRect(x, 0, mySize.width-x, mySize.height);
				}
			}
		}
		if (repeat > 1) {
			for (int i = 0; i < repeat; i++) {
				offScreen.copyArea(0, 0, mySize.width/repeat, mySize.height, i*mySize.width/repeat, 0);
			}
		}
	}

	public void start() {
		if(thread==null) {
			thread = new Thread(this);
			thread.start();
		}
	}

	public void stop() {
		if(thread!=null) {
			thread.stop();
			thread = null;
		}
	}

	public void run() {
		Graphics g = getGraphics();
		while(thread!=null) {
			paint(g);
			try {
				Thread.sleep(50);
			} catch(InterruptedException e) {
			}
		}
	}

	public void paint(Graphics g) {
		g.drawImage(offImage, boundX-mySize.width, 0, null);
		g.drawImage(offImage, boundX, 0, null);
		boundX += speed;
		if (boundX >= mySize.width) boundX -= mySize.width;
		if (boundX < 0) boundX += mySize.width;
	}

	private Color[] blendColor(Color c1, Color c2, int n) {
		Color[] col = new Color[n];
		for (int i = 0; i < n; i++) {
			int r = c1.getRed()*(n-i)/n + c2.getRed()*i/n;
			int g = c1.getGreen()*(n-i)/n + c2.getGreen()*i/n;
			int b = c1.getBlue()*(n-i)/n + c2.getBlue()*i/n;
			col[i] = new Color(r, g, b);
		}
		return col;
	}
}
