/* * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ 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 * <a href="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.image.ColorModel.html#getRGBdefault()"> * standard ARGB format</a>. * <p>Normal usage looks something like this: * <pre> 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; *   } *   } *  } * </pre>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. * <p> * If the image is to be a movie, override isStatic to return false, * <i>y</i> 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. * * @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<h && useful; y++) { parent.computeRow(y,row); if (parent.aborted) { ic.imageComplete(ic.IMAGEABORTED); return; } ic.setPixels(0, y, w, 1, parent.cm, row, 0, w); } ic.imageComplete(parent.isStatic() ? ic.STATICIMAGEDONE : ic.SINGLEFRAMEDONE ); } while(!parent.isStatic() && useful); } } private final static void doPrivileged(final Runnable doRun) { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { doRun.run(); return null; } } ); } }