/**
* @(#)SmashTransition.java
* @version 1.51 04/06/97
* @author Robert Temple (robertt@starwave.com)
*/

import java.awt.image.MemoryImageSource;
import java.awt.*;

/**
* The SmashTransition class changes one image into another by dropping the
* new image onto the old one.  The old image appears to crumble under the
* weight of the new image.
*/
public class SmashTransition extends BillTransition {
// Static Members

	/**
	* The total number of CELLS this transition will show on the screen before
	* the new image is shown in its entirety
	*/
	final static int CELLS = 8;

	/**
	* The old image will appear to be folded back and forth under the weigth
	* of the new image falling on it.  This constant holds the value of the
	* number of folds that will appear each cell
	*/
	final static float FOLDS = 8.0f;

	/**
	* an array of white pixels used to fill in pixels where neither image will
	* appear in for a cell
	*/
	static int[] fill_pixels;

	static void setupFillPixels(int width) {
		if(fill_pixels != null && fill_pixels.length <= width) {
			return;
		}
		fill_pixels = new int[width];
		for(int f = 0; f < width; ++f) {
			fill_pixels[f] = 0xFFFFFFFF;
		}
	}

// Instance Members

	/** The amount of pixels to move the new image onto the old image each cell */
	int drop_amount;

	/** 
	* The index into the work_pixel array that the start of the old image
	* current is at
	*/
	int location;

	/**
	* Used to initialize the transition right after it is created.
	* creates cells
	* @param owner the component to be used to create images from cells
	*/
	public void init(Component owner, int[] current, int[] next) {
		init(owner, current, next, CELLS, 160);

		// ensure the fill pixel array is setup properly
		setupFillPixels(cell_w);

		// this cannot be reduced to 'pixels_per_cell / CELLS' because there
		// is some rounding that is done in 'cell_h / CELLS'
		drop_amount = (cell_h / CELLS) * cell_w;

		// as above, the right half of this calculation cannot be reduced
		// because of rounding
		location = pixels_per_cell - ((cell_h / CELLS) / 2) * cell_w;

		for(int c = CELLS - 1; c >= 0; --c) {

			// give other threads a shot at the CPU
			try { Thread.sleep(100); } catch (InterruptedException e) {}

			// create the next cell
			Smash(c + 1);

			// give other threads a shot at the CPU
			try { Thread.sleep(150); } catch (InterruptedException e) {}

			// create the new cell image from the work pixels
			createCellFromWorkPixels(c);

			location -= drop_amount;
		}

		// we don't need the work pixels anymore
		work_pixels = null;
	}

	/** 
	* Create the next cell in the work pixel array 
	*/
	void Smash(int max_fold) {

		// draw in the new image
		System.arraycopy((Object)next_pixels, pixels_per_cell - location,
					(Object)work_pixels, 0, location);

		// calculate the height of the new image
		int height = cell_h - location / cell_w;

		// calculate the length of the lines to draw for the smashed image
		int fold_width = cell_w - max_fold;

		// variable used to store the current fold offset
		float fold_offset = 0.0f;

		// calculate the amount to add to the fold offset after every line
		float fold_offset_adder = (float)max_fold * FOLDS / (float)height;

		// used to increment the src_y_offset defined below after every line
		float src_y_adder = (float)cell_h / (float)height;

		// used to determine the y-coordinate of the line to use from the
		// source image
		float src_y_offset = cell_h - src_y_adder / 2;

		for(int p = pixels_per_cell - cell_w; p >= location; p -= cell_w) {

			System.arraycopy((Object)fill_pixels, 0, (Object)work_pixels, p,
						cell_w);

			System.arraycopy((Object)current_pixels,
						(int)src_y_offset * cell_w, (Object)work_pixels,
						p + (int)fold_offset, fold_width);

			src_y_offset -= src_y_adder;
			fold_offset += fold_offset_adder;

			if(fold_offset < 0.0 || fold_offset >= max_fold) {
				fold_offset_adder *= -1.0f;
			}
		}
	}
}


