OSDN Git Service

libjava/
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / awt / image / AsyncImage.java
1 /* AsyncImage.java -- Loads images asynchronously
2    Copyright (C) 2008 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package gnu.java.awt.image;
40
41
42 import java.awt.Graphics;
43 import java.awt.Image;
44 import java.awt.image.ImageConsumer;
45 import java.awt.image.ImageObserver;
46 import java.awt.image.ImageProducer;
47 import java.util.HashSet;
48 import java.util.Iterator;
49
50 /**
51  * Supports asynchronous loading of images.
52  */
53 public class AsyncImage
54   extends Image
55 {
56
57   /**
58    * The image source for AsyncImages.
59    */
60   private class AsyncImageSource
61     implements ImageProducer
62   {
63     /**
64      * The real image source, if already present, or <code>null</code>
65      * otherwise.
66      */
67     private ImageProducer realSource;
68
69     public void addConsumer(ImageConsumer ic)
70     {
71       startProduction(ic);
72     }
73
74     public boolean isConsumer(ImageConsumer ic)
75     {
76       return false;
77     }
78
79     public void removeConsumer(ImageConsumer ic)
80     {
81       // Nothing to do here.
82     }
83
84     public void requestTopDownLeftRightResend(ImageConsumer ic)
85     {
86       startProduction(ic);
87     }
88
89     public void startProduction(ImageConsumer ic)
90     {
91       ImageProducer ip = getRealSource();
92       if (ip == null)
93         {
94           ic.setDimensions(1, 1);
95           ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
96         }
97       else
98         {
99           ip.startProduction(ic);
100         }
101     }
102
103     /**
104      * Returns the real image source, if already present. Otherwise, this
105      * returns <code>null</code>.
106      *
107      * @return the real image source, or <code>null</code> if not present
108      */
109     private ImageProducer getRealSource()
110     {
111       synchronized (AsyncImage.this)
112         {
113           ImageProducer source = realSource;
114           if (source == null)
115             {
116               Image ri = realImage;
117               if (ri != null)
118                 {
119                   realSource = source = ri.getSource();
120                 }
121             }
122           return source;
123         }
124     }
125   }
126
127   /**
128    * The real image. This is null as long as the image is not complete.
129    */
130   private volatile Image realImage;
131
132   /**
133    * The image observers.
134    *
135    * This is package private to avoid accessor methods.
136    */
137   HashSet<ImageObserver> observers;
138
139   private volatile boolean complete = false;
140
141   /**
142    * Creates a new AsyncImage.
143    */
144   AsyncImage()
145   {
146     observers = new HashSet<ImageObserver>();
147   }
148
149   public void flush()
150   {
151     // Nothing to do here.
152   }
153
154   public Graphics getGraphics()
155   {
156     Image r = realImage;
157     Graphics g = null;
158     if (r != null)
159       g = r.getGraphics(); // Should we return some dummy graphics instead?
160     return g;
161   }
162   
163   public boolean isComplete() {
164         return complete;
165   }
166
167   public int getHeight(ImageObserver observer)
168   {
169     addObserver(observer);
170     int height = -1;
171     waitForImage(observer);
172     Image r = realImage;
173     if (r != null)
174       height = r.getHeight(observer);
175     return height;
176   }
177
178   public Object getProperty(String name, ImageObserver observer)
179   {
180     addObserver(observer);
181     Image r = realImage;
182     Object prop = null;
183     if (r != null)
184       prop = r.getProperty(name, observer);
185     return prop;
186   }
187
188   public ImageProducer getSource()
189   {
190     return new AsyncImageSource();
191   }
192
193   public int getWidth(ImageObserver observer)
194   {
195     addObserver(observer);
196     int width = -1;
197     waitForImage(observer);
198     Image r = realImage;
199     if (r != null)
200       width = r.getWidth(observer);
201     return width;
202   }
203
204   public void addObserver(ImageObserver obs)
205   {
206     if (obs != null)
207       {
208         synchronized (this)
209           {
210             // This field gets null when image loading is complete and we don't
211             // need to store any more observers.
212             HashSet<ImageObserver> observs = observers;
213             if (observs != null)
214               {
215                 observs.add(obs);
216               }
217           }
218       }
219   }
220
221   public boolean prepareImage(int w, int h, ImageObserver obs)
222   {
223     addObserver(obs);
224     return realImage != null;
225   }
226
227   public int checkImage(int w, int h, ImageObserver obs)
228   {
229     addObserver(obs);
230     int flags = 0;
231     if (realImage != null)
232       flags = ImageObserver.ALLBITS | ImageObserver.WIDTH
233               | ImageObserver.HEIGHT | ImageObserver.PROPERTIES;
234     return flags;
235   }
236
237   public Image getRealImage()
238   {
239     return realImage;
240   }
241
242   public void setRealImage(Image im)
243   {
244     realImage = im;
245     int status = ImageObserver.HEIGHT | ImageObserver.WIDTH;
246     notifyObservers(status, 0, 0, im.getWidth(null), im.getHeight(null));
247   }
248
249   public void notifyObservers(int status, int x, int y, int w, int h)
250   {
251     synchronized (this)
252     {
253       HashSet observs = observers;
254       if (observs != null)
255         {
256           Iterator i = observs.iterator();
257           while (i.hasNext())
258             {
259               ImageObserver obs = (ImageObserver) i.next();
260               boolean complete = obs.imageUpdate(this, status, x, y, realImage.getWidth(obs), realImage.getHeight(obs));
261               if (complete) // Remove completed observers.
262                 i.remove();
263             }
264         }
265       if ((status & ImageObserver.ALLBITS) != 0)
266         {
267           complete = true;
268           notifyAll();
269         }
270     }
271   }
272
273   /**
274    * Waits for the image to be loaded completely, if the image observer
275    * is <code>null</code>. Otherwise this is not necessary, because the
276    * image observer can be notified about later completion.
277    *
278    * @param observer the image observer
279    */
280   public void waitForImage(ImageObserver observer)
281   {
282     if (!complete && observer == null)
283       {
284         synchronized (this)
285           {
286             while (! complete)
287               {
288                 try
289                   {
290                     wait();
291                   }
292                 catch (InterruptedException ex)
293                   {
294                     Thread.currentThread().interrupt();
295                   }
296               }
297           }
298       }
299   }
300 }