blob: cec69e9c39d9ae269afe313b621056b0d289013d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.swing.colorchooser;
27
28import java.awt.*;
29import java.awt.image.*;
30
31/** A helper class to make computing synthetic images a little easier.
32 * All you need to do is define a subclass that overrides computeRow
33 * to compute a row of the image. It is passed the y coordinate of the
34 * row and an array into which to put the pixels in
35 * <a href="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.image.ColorModel.html#getRGBdefault()">
36 * standard ARGB format</a>.
37 * <p>Normal usage looks something like this:
38 * <pre>&nbsp;Image i = createImage(new SyntheticImage(200, 100) {
39 * &nbsp; protected void computeRow(int y, int[] row) {
40 * &nbsp; for(int i = width; --i>=0; ) {
41 * &nbsp; int grey = i*255/(width-1);
42 * &nbsp; row[i] = (255<<24)|(grey<<16)|(grey<<8)|grey;
43 * &nbsp; }
44 * &nbsp; }
45 * &nbsp;}
46 * </pre>This creates a image 200 pixels wide and 100 pixels high
47 * that is a horizontal grey ramp, going from black on the left to
48 * white on the right.
49 * <p>
50 * If the image is to be a movie, override isStatic to return false,
51 * <i>y</i> cycling back to 0 is computeRow's signal that the next
52 * frame has started. It is acceptable (expected?) for computeRow(0,r)
53 * to pause until the appropriate time to start the next frame.
54 *
55 * @author James Gosling
56 */
57abstract class SyntheticImage implements ImageProducer {
58 private SyntheticImageGenerator root;
59 protected int width=10, height=100;
60 static final ColorModel cm = ColorModel.getRGBdefault();
61 public static final int pixMask = 0xFF;
62 private Thread runner;
63 protected SyntheticImage() { }
64 protected SyntheticImage(int w, int h) { width = w; height = h; }
65 protected void computeRow(int y, int[] row) {
66 int p = 255-255*y/(height-1);
67 p = (pixMask<<24)|(p<<16)|(p<<8)|p;
68 for (int i = row.length; --i>=0; ) row[i] = p;
69 }
70 public synchronized void addConsumer(ImageConsumer ic){
71 for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next)
72 if (ics.ic == ic) return;
73 root = new SyntheticImageGenerator(ic, root, this);
74 }
75 public synchronized boolean isConsumer(ImageConsumer ic){
76 for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next)
77 if (ics.ic == ic) return true;
78 return false;
79 }
80 public synchronized void removeConsumer(ImageConsumer ic) {
81 SyntheticImageGenerator prev = null;
82 for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) {
83 if (ics.ic == ic) {
84 ics.useful = false;
85 if (prev!=null) prev.next = ics.next;
86 else root = ics.next;
87 return;
88 }
89 prev = ics;
90 }
91 }
92 public synchronized void startProduction(ImageConsumer ic) {
93 addConsumer(ic);
94 for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next)
95 if (ics.useful && !ics.isAlive())
96 ics.start();
97 }
98 protected boolean isStatic() { return true; }
99 public void nextFrame(int param) {}//Override if !isStatic
100 public void requestTopDownLeftRightResend(ImageConsumer ic){}
101
102 protected volatile boolean aborted = false;
103}
104
105class SyntheticImageGenerator extends Thread {
106 ImageConsumer ic;
107 boolean useful;
108 SyntheticImageGenerator next;
109 SyntheticImage parent;
110 SyntheticImageGenerator(ImageConsumer ic, SyntheticImageGenerator next,
111 SyntheticImage parent) {
112 super("SyntheticImageGenerator");
113 this.ic = ic;
114 this.next = next;
115 this.parent = parent;
116 useful = true;
117 setDaemon(true);
118 }
119 public void run() {
120 ImageConsumer ic = this.ic;
121 int w = parent.width;
122 int h = parent.height;
123 int hints = ic.SINGLEPASS|ic.COMPLETESCANLINES|ic.TOPDOWNLEFTRIGHT;
124 if (parent.isStatic())
125 hints |= ic.SINGLEFRAME;
126 ic.setHints(hints);
127 ic.setDimensions(w, h);
128 ic.setProperties(null);
129 ic.setColorModel(parent.cm);
130
131 if (useful) {
132 int[] row=new int[w];
133 doPrivileged( new Runnable() {
134 public void run() {
135 Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
136 }
137 });
138
139 do {
140 for (int y = 0; y<h && useful; y++) {
141 parent.computeRow(y,row);
142
143 if (parent.aborted) {
144 ic.imageComplete(ic.IMAGEABORTED);
145 return;
146 }
147
148 ic.setPixels(0, y, w, 1, parent.cm, row, 0, w);
149 }
150 ic.imageComplete(parent.isStatic() ? ic.STATICIMAGEDONE
151 : ic.SINGLEFRAMEDONE );
152 } while(!parent.isStatic() && useful);
153 }
154 }
155
156 private final static void doPrivileged(final Runnable doRun) {
157 java.security.AccessController.doPrivileged(
158 new java.security.PrivilegedAction() {
159 public Object run() {
160 doRun.run();
161 return null;
162 }
163 }
164 );
165 }
166}