/* * @(#)SyntheticImage.java 1.24 03/12/19 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package javax.swing.colorchooser; import java.awt.*; import java.awt.image.*; /** A helper class to make computing synthetic images a little easier. * All you need to do is define a subclass that overrides computeRow * to compute a row of the image. It is passed the y coordinate of the * row and an array into which to put the pixels in * * standard ARGB format. *

Normal usage looks something like this: *

 Image i = createImage(new SyntheticImage(200, 100) {
 *       protected void computeRow(int y, int[] row) {
 *   	for(int i = width; --i>=0; ) {
 *   	    int grey = i*255/(width-1);
 *   	    row[i] = (255<<24)|(grey<<16)|(grey<<8)|grey;
 *   	}
 *       }
 *   }
 *  
This creates a image 200 pixels wide and 100 pixels high * that is a horizontal grey ramp, going from black on the left to * white on the right. *

* If the image is to be a movie, override isStatic to return false, * y cycling back to 0 is computeRow's signal that the next * frame has started. It is acceptable (expected?) for computeRow(0,r) * to pause until the appropriate time to start the next frame. * * @version 1.24 12/19/03 * @author James Gosling */ abstract class SyntheticImage implements ImageProducer { private SyntheticImageGenerator root; protected int width=10, height=100; static final ColorModel cm = ColorModel.getRGBdefault(); public static final int pixMask = 0xFF; private Thread runner; protected SyntheticImage() { } protected SyntheticImage(int w, int h) { width = w; height = h; } protected void computeRow(int y, int[] row) { int p = 255-255*y/(height-1); p = (pixMask<<24)|(p<<16)|(p<<8)|p; for (int i = row.length; --i>=0; ) row[i] = p; } public synchronized void addConsumer(ImageConsumer ic){ for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) if (ics.ic == ic) return; root = new SyntheticImageGenerator(ic, root, this); } public synchronized boolean isConsumer(ImageConsumer ic){ for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) if (ics.ic == ic) return true; return false; } public synchronized void removeConsumer(ImageConsumer ic) { SyntheticImageGenerator prev = null; for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) { if (ics.ic == ic) { ics.useful = false; if (prev!=null) prev.next = ics.next; else root = ics.next; return; } prev = ics; } } public synchronized void startProduction(ImageConsumer ic) { addConsumer(ic); for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) if (ics.useful && !ics.isAlive()) ics.start(); } protected boolean isStatic() { return true; } public void nextFrame(int param) {}//Override if !isStatic public void requestTopDownLeftRightResend(ImageConsumer ic){} protected volatile boolean aborted = false; } class SyntheticImageGenerator extends Thread { ImageConsumer ic; boolean useful; SyntheticImageGenerator next; SyntheticImage parent; SyntheticImageGenerator(ImageConsumer ic, SyntheticImageGenerator next, SyntheticImage parent) { super("SyntheticImageGenerator"); this.ic = ic; this.next = next; this.parent = parent; useful = true; setDaemon(true); } public void run() { ImageConsumer ic = this.ic; int w = parent.width; int h = parent.height; int hints = ic.SINGLEPASS|ic.COMPLETESCANLINES|ic.TOPDOWNLEFTRIGHT; if (parent.isStatic()) hints |= ic.SINGLEFRAME; ic.setHints(hints); ic.setDimensions(w, h); ic.setProperties(null); ic.setColorModel(parent.cm); if (useful) { int[] row=new int[w]; doPrivileged( new Runnable() { public void run() { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); } }); do { for (int y = 0; y