1 /*
2  * Copyright (c) 1995, 2004, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.awt.image;
27 
28 import java.util.Hashtable;
29 import java.util.Enumeration;
30 
31 import java.awt.Component;
32 import java.awt.Color;
33 import java.awt.Graphics;
34 import java.awt.Image;
35 import java.awt.image.BufferedImage;
36 import java.awt.image.ColorModel;
37 import java.awt.image.ImageProducer;
38 import java.awt.image.ImageConsumer;
39 import java.awt.image.ImageObserver;
40 import sun.awt.image.ImageRepresentation;
41 import sun.awt.image.FileImageSource;
42 
43 public class ToolkitImage extends Image {
44 
45     /**
46      * The object which is used to reconstruct the original image data
47      * as needed.
48      */
49     ImageProducer source;
50 
51     InputStreamImageSource src;
52 
53     ImageRepresentation imagerep;
54 
55     static {
56         /* ensure that the necessary native libraries are loaded */
NativeLibLoader.loadLibraries()57         NativeLibLoader.loadLibraries();
58     }
59 
ToolkitImage()60     protected ToolkitImage() {
61     }
62 
63     /**
64      * Construct an image from an ImageProducer object.
65      */
ToolkitImage(ImageProducer is)66     public ToolkitImage(ImageProducer is) {
67         source = is;
68         if (is instanceof InputStreamImageSource) {
69             src = (InputStreamImageSource) is;
70         }
71     }
72 
getSource()73     public ImageProducer getSource() {
74         if (src != null) {
75             src.checkSecurity(null, false);
76         }
77         return source;
78     }
79 
80     private int width = -1;
81     private int height = -1;
82     private Hashtable<?, ?> properties;
83 
84     private int availinfo;
85 
86     /**
87      * Return the width of the original image source.
88      * If the width isn't known, then the image is reconstructed.
89      */
getWidth()90     public int getWidth() {
91         if (src != null) {
92             src.checkSecurity(null, false);
93         }
94         if ((availinfo & ImageObserver.WIDTH) == 0) {
95             reconstruct(ImageObserver.WIDTH);
96         }
97         return width;
98     }
99 
100     /**
101      * Return the width of the original image source.
102      * If the width isn't known, then the ImageObserver object will be
103      * notified when the data is available.
104      */
getWidth(ImageObserver iw)105     public synchronized int getWidth(ImageObserver iw) {
106         if (src != null) {
107             src.checkSecurity(null, false);
108         }
109         if ((availinfo & ImageObserver.WIDTH) == 0) {
110             addWatcher(iw, true);
111             if ((availinfo & ImageObserver.WIDTH) == 0) {
112                 return -1;
113             }
114         }
115         return width;
116     }
117 
118     /**
119      * Return the height of the original image source.
120      * If the height isn't known, then the image is reconstructed.
121      */
getHeight()122     public int getHeight() {
123         if (src != null) {
124             src.checkSecurity(null, false);
125         }
126         if ((availinfo & ImageObserver.HEIGHT) == 0) {
127             reconstruct(ImageObserver.HEIGHT);
128         }
129         return height;
130     }
131 
132     /**
133      * Return the height of the original image source.
134      * If the height isn't known, then the ImageObserver object will be
135      * notified when the data is available.
136      */
getHeight(ImageObserver iw)137     public synchronized int getHeight(ImageObserver iw) {
138         if (src != null) {
139             src.checkSecurity(null, false);
140         }
141         if ((availinfo & ImageObserver.HEIGHT) == 0) {
142             addWatcher(iw, true);
143             if ((availinfo & ImageObserver.HEIGHT) == 0) {
144                 return -1;
145             }
146         }
147         return height;
148     }
149 
150     /**
151      * Return a property of the image by name.  Individual property names
152      * are defined by the various image formats.  If a property is not
153      * defined for a particular image, then this method will return the
154      * UndefinedProperty object.  If the properties for this image are
155      * not yet known, then this method will return null and the ImageObserver
156      * object will be notified later.  The property name "comment" should
157      * be used to store an optional comment which can be presented to
158      * the user as a description of the image, its source, or its author.
159      */
getProperty(String name, ImageObserver observer)160     public Object getProperty(String name, ImageObserver observer) {
161         if (name == null) {
162             throw new NullPointerException("null property name is not allowed");
163         }
164 
165         if (src != null) {
166             src.checkSecurity(null, false);
167         }
168         if (properties == null) {
169             addWatcher(observer, true);
170             if (properties == null) {
171                 return null;
172             }
173         }
174         Object o = properties.get(name);
175         if (o == null) {
176             o = Image.UndefinedProperty;
177         }
178         return o;
179     }
180 
hasError()181     public boolean hasError() {
182         if (src != null) {
183             src.checkSecurity(null, false);
184         }
185         return (availinfo & ImageObserver.ERROR) != 0;
186     }
187 
check(ImageObserver iw)188     public int check(ImageObserver iw) {
189         if (src != null) {
190             src.checkSecurity(null, false);
191         }
192         if ((availinfo & ImageObserver.ERROR) == 0 &&
193             ((~availinfo) & (ImageObserver.WIDTH |
194                              ImageObserver.HEIGHT |
195                              ImageObserver.PROPERTIES)) != 0) {
196             addWatcher(iw, false);
197         }
198         return availinfo;
199     }
200 
preload(ImageObserver iw)201     public void preload(ImageObserver iw) {
202         if (src != null) {
203             src.checkSecurity(null, false);
204         }
205         if ((availinfo & ImageObserver.ALLBITS) == 0) {
206             addWatcher(iw, true);
207         }
208     }
209 
addWatcher(ImageObserver iw, boolean load)210     private synchronized void addWatcher(ImageObserver iw, boolean load) {
211         if ((availinfo & ImageObserver.ERROR) != 0) {
212             if (iw != null) {
213                 iw.imageUpdate(this, ImageObserver.ERROR|ImageObserver.ABORT,
214                                -1, -1, -1, -1);
215             }
216             return;
217         }
218         ImageRepresentation ir = getImageRep();
219         ir.addWatcher(iw);
220         if (load) {
221             ir.startProduction();
222         }
223     }
224 
reconstruct(int flags)225     private synchronized void reconstruct(int flags) {
226         if ((flags & ~availinfo) != 0) {
227             if ((availinfo & ImageObserver.ERROR) != 0) {
228                 return;
229             }
230             ImageRepresentation ir = getImageRep();
231             ir.startProduction();
232             while ((flags & ~availinfo) != 0) {
233                 try {
234                     wait();
235                 } catch (InterruptedException e) {
236                     Thread.currentThread().interrupt();
237                     return;
238                 }
239                 if ((availinfo & ImageObserver.ERROR) != 0) {
240                     return;
241                 }
242             }
243         }
244     }
245 
addInfo(int newinfo)246     synchronized void addInfo(int newinfo) {
247         availinfo |= newinfo;
248         notifyAll();
249     }
250 
setDimensions(int w, int h)251     void setDimensions(int w, int h) {
252         width = w;
253         height = h;
254         addInfo(ImageObserver.WIDTH | ImageObserver.HEIGHT);
255     }
256 
setProperties(Hashtable<?, ?> props)257     void setProperties(Hashtable<?, ?> props) {
258         if (props == null) {
259             props = new Hashtable<String, Object>();
260         }
261         properties = props;
262         addInfo(ImageObserver.PROPERTIES);
263     }
264 
infoDone(int status)265     synchronized void infoDone(int status) {
266         if (status == ImageConsumer.IMAGEERROR ||
267             ((~availinfo) & (ImageObserver.WIDTH |
268                              ImageObserver.HEIGHT)) != 0) {
269             addInfo(ImageObserver.ERROR);
270         } else if ((availinfo & ImageObserver.PROPERTIES) == 0) {
271             setProperties(null);
272         }
273     }
274 
flush()275     public void flush() {
276         if (src != null) {
277             src.checkSecurity(null, false);
278         }
279 
280         ImageRepresentation ir;
281         synchronized (this) {
282             availinfo &= ~ImageObserver.ERROR;
283             ir = imagerep;
284             imagerep = null;
285         }
286         if (ir != null) {
287             ir.abort();
288         }
289         if (src != null) {
290             src.flush();
291         }
292     }
293 
makeImageRep()294     protected ImageRepresentation makeImageRep() {
295         return new ImageRepresentation(this, ColorModel.getRGBdefault(),
296                                        false);
297     }
298 
getImageRep()299     public synchronized ImageRepresentation getImageRep() {
300         if (src != null) {
301             src.checkSecurity(null, false);
302         }
303         if (imagerep == null) {
304             imagerep = makeImageRep();
305         }
306         return imagerep;
307     }
308 
getGraphics()309     public Graphics getGraphics() {
310         throw new UnsupportedOperationException("getGraphics() not valid for images " +
311                                      "created with createImage(producer)");
312     }
313 
314     /* this method is needed by printing code */
getColorModel()315     public ColorModel getColorModel() {
316         ImageRepresentation imageRep = getImageRep();
317         return imageRep.getColorModel();
318     }
319 
320     /* this method is needed by printing code */
getBufferedImage()321     public BufferedImage getBufferedImage() {
322         ImageRepresentation imageRep = getImageRep();
323         return imageRep.getBufferedImage();
324     }
325 
setAccelerationPriority(float priority)326     public void setAccelerationPriority(float priority) {
327         super.setAccelerationPriority(priority);
328         ImageRepresentation imageRep = getImageRep();
329         imageRep.setAccelerationPriority(accelerationPriority);
330     }
331 }
332