/** * @(#)TearTransition.java * @version 1.51 04/06/97 * @author Robert Temple (robertt@starwave.com) */ import java.awt.image.MemoryImageSource; import java.awt.*; /** * The TearTransition class changes one image into another by making it appear * as if the old image is covering the new image, and the old image is torn * out from over the new image. */ public class TearTransition extends BillTransition { /** * The total number of cells this transition will show on the screen before * the new image is shown in its entirety */ static final int CELLS = 7; /** The number to start the x_cross variable at */ static final float INITIAL_X_CROSS = 1.6f; /** The amount the x_cross number is divided by after each cell */ static final float X_CROSS_DIVISOR = 3.5f; /** * A number the cross product of the x and y values of a pixel are * multiplied by to give a new x value */ float x_cross; /** * 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); // starting after the first row, Copy the new image into the work pixels System.arraycopy((Object)next_pixels, 0, (Object)work_pixels, 0, pixels_per_cell); // copy all of the current billboard's pixels into the work pixels System.arraycopy((Object)current_pixels, 0, (Object)work_pixels, 0, cell_w); x_cross = INITIAL_X_CROSS; // Create all the image cells, starting with the last cell. Since each // cell progressively covers more and more of the old image, we start // from the last cell to reduce the amount of drawing we need to do from // cell to cell. This is because the last cell covers the least // amount of the old image. So, after drawing the last cell, we can draw // right over the work pixels, since we know that we will be covering all // that the later cell (the one we had previouly drawn) drew onto the // work pixels anyways. So now we can just draw the pixels of the new // image, and don't have to worry about drawing pixels from the old image. // email me if this is not clear. templer@db.erau.edu for(int c = CELLS - 1; c >= 0; --c) { // give other threads a shot at the CPU try { Thread.sleep(100); } catch (InterruptedException e) {} // draw the next cell into the work pixels Tear(); // 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); // set the x_cross for the next cell x_cross /= X_CROSS_DIVISOR; } // we don't need the work pixels anymore work_pixels = null; } /** * Create the next cell in the work pixel array */ final void Tear() { float x_increment; int p, height_adder; // p represent the current offset into the work pixels that we are // drawing at p = height_adder = cell_w; // starting after the first row, draw all the rows, individually into the // work pixels for (int y = 1; y < cell_h; ++y) { // the cross product will equal x_cross * x * y. Since we are gonna // have the same x_cross and y values for this row, calculate it // x_cross * y once for this row, so we don't have to do it for each // pixel in this row. For each pixel we will multiply this value by x x_increment = x_cross * y; // This if-else structure is a speed optimization. The first block // draws the pixels, pixel by pixel. The else block draws the pixels // by copying sequences of pixels onto the work pixels. //## // A value of x_increment over 0.50 means that there will never be two // adjacent pixels from the old image that will be copied onto the work // pixels if(x_increment >= 0.50f) { float fx = 0.0f; // Adding x to a running sum of x_increment + 1 each time is the // equivalent of x += x * x_increment, but it is faster x_increment += 1.0f; int x = 0; // draw in the pixels for this row until the end of the row is // reached do { work_pixels[p++] = current_pixels[height_adder + x]; // Adding x to a running sum of x_increment each time is the // equivalent of multiplying x * x_increment x = (int)(fx += x_increment); } while(x < cell_w); } else { float overflow = 1.0f / x_increment; float dst_end = overflow / 2.0f + 1.49999999f; int dst_start = 0, src_offset = 0, length = (int)dst_end; while(dst_start + src_offset + length < cell_w) { System.arraycopy((Object)current_pixels, p + src_offset, (Object)work_pixels, p, length); ++src_offset; dst_end += overflow; p += length; dst_start += length; length = (int)dst_end - dst_start; } length = cell_w - src_offset - dst_start; System.arraycopy((Object)current_pixels, p + src_offset, (Object)work_pixels, p, length); } p = height_adder += cell_w; } } }