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
26package sun.awt.image;
27
28import java.util.Hashtable;
29import java.util.Enumeration;
30
31import java.awt.Component;
32import java.awt.Color;
33import java.awt.Graphics;
34import java.awt.Image;
35import java.awt.image.BufferedImage;
36import java.awt.image.ColorModel;
37import java.awt.image.ImageProducer;
38import java.awt.image.ImageConsumer;
39import java.awt.image.ImageObserver;
40import sun.awt.image.ImageRepresentation;
41import sun.awt.image.FileImageSource;
42
43public 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 */
57        NativeLibLoader.loadLibraries();
58    }
59
60    protected ToolkitImage() {
61    }
62
63    /**
64     * Construct an image from an ImageProducer object.
65     */
66    public ToolkitImage(ImageProducer is) {
67        source = is;
68        if (is instanceof InputStreamImageSource) {
69            src = (InputStreamImageSource) is;
70        }
71    }
72
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     */
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     */
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     */
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     */
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     */
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
181    public boolean hasError() {
182        if (src != null) {
183            src.checkSecurity(null, false);
184        }
185        return (availinfo & ImageObserver.ERROR) != 0;
186    }
187
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
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
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
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
246    synchronized void addInfo(int newinfo) {
247        availinfo |= newinfo;
248        notifyAll();
249    }
250
251    void setDimensions(int w, int h) {
252        width = w;
253        height = h;
254        addInfo(ImageObserver.WIDTH | ImageObserver.HEIGHT);
255    }
256
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
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
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
294    protected ImageRepresentation makeImageRep() {
295        return new ImageRepresentation(this, ColorModel.getRGBdefault(),
296                                       false);
297    }
298
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
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 */
315    public ColorModel getColorModel() {
316        ImageRepresentation imageRep = getImageRep();
317        return imageRep.getColorModel();
318    }
319
320    /* this method is needed by printing code */
321    public BufferedImage getBufferedImage() {
322        ImageRepresentation imageRep = getImageRep();
323        return imageRep.getBufferedImage();
324    }
325
326    public void setAccelerationPriority(float priority) {
327        super.setAccelerationPriority(priority);
328        ImageRepresentation imageRep = getImageRep();
329        imageRep.setAccelerationPriority(accelerationPriority);
330    }
331}
332