1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56:
57:
67: public class GtkImage extends Image
68: {
69: int width = -1, height = -1;
70:
71:
74: Hashtable<?,?> props;
75:
76:
79: boolean isLoaded;
80:
81:
85: Pointer pixbuf;
86:
87:
90: Vector<ImageObserver> observers;
91:
92:
95: boolean errorLoading;
96:
97:
100: ImageProducer source;
101:
102:
105: static ColorModel nativeModel = new DirectColorModel(32,
106: 0x000000FF,
107: 0x0000FF00,
108: 0x00FF0000,
109: 0xFF000000);
110:
111:
114: private static GtkImage errorImage;
115:
116:
122: static Object pixbufLock = new Object();
123:
124:
127: private native void initFromBuffer( long bufferPointer );
128:
129:
133: native int[] getPixels();
134:
135:
139: private native void setPixels(int[] pixels);
140:
141:
145: private native boolean loadPixbuf(String name);
146:
147:
151: private native boolean loadImageFromData(byte[] data);
152:
153:
157: private native void createPixbuf();
158:
159:
163: private native void freePixbuf();
164:
165:
169: private native void createScaledPixbuf(GtkImage src, int hints);
170:
171:
178: public GtkImage (ImageProducer producer)
179: {
180: isLoaded = false;
181: observers = new Vector<ImageObserver>();
182: source = producer;
183: errorLoading = false;
184: source.startProduction(new GtkImageConsumer(this, source));
185: }
186:
187:
193: public GtkImage ()
194: {
195: isLoaded = true;
196: observers = null;
197: props = new Hashtable<String,Object>();
198: errorLoading = false;
199: }
200:
201:
206: public GtkImage (String filename)
207: {
208: File f = new File(filename);
209: try
210: {
211: String path = f.getCanonicalPath();
212: synchronized(pixbufLock)
213: {
214: if (loadPixbuf(f.getCanonicalPath()) != true)
215: throw new IllegalArgumentException("Couldn't load image: "
216: + filename);
217: }
218: }
219: catch(IOException e)
220: {
221: IllegalArgumentException iae;
222: iae = new IllegalArgumentException("Couldn't load image: "
223: + filename);
224: iae.initCause(e);
225: throw iae;
226: }
227:
228: isLoaded = true;
229: observers = null;
230: props = new Hashtable<String,Object>();
231: }
232:
233:
239: public GtkImage (byte[] data)
240: {
241: synchronized(pixbufLock)
242: {
243: if (loadImageFromData (data) != true)
244: throw new IllegalArgumentException ("Couldn't load image.");
245: }
246:
247: isLoaded = true;
248: observers = null;
249: props = new Hashtable<String,Object>();
250: errorLoading = false;
251: }
252:
253:
256: public GtkImage (URL url)
257: {
258: isLoaded = false;
259: observers = new Vector<ImageObserver>();
260: errorLoading = false;
261: if( url == null)
262: return;
263: ByteArrayOutputStream baos = new ByteArrayOutputStream (5000);
264: try
265: {
266: BufferedInputStream bis = new BufferedInputStream (url.openStream());
267:
268: byte[] buf = new byte[5000];
269: int n = 0;
270:
271: while ((n = bis.read(buf)) != -1)
272: baos.write(buf, 0, n);
273: bis.close();
274: }
275: catch(IOException e)
276: {
277: throw new IllegalArgumentException ("Couldn't load image.");
278: }
279: byte[] array = baos.toByteArray();
280: synchronized(pixbufLock)
281: {
282: if (loadImageFromData(array) != true)
283: throw new IllegalArgumentException ("Couldn't load image.");
284: }
285:
286: isLoaded = true;
287: observers = null;
288: props = new Hashtable<String,Object>();
289: }
290:
291:
294: private GtkImage (GtkImage src, int width, int height, int hints)
295: {
296: this.width = width;
297: this.height = height;
298: props = new Hashtable<String,Object>();
299: isLoaded = true;
300: observers = null;
301:
302:
303: synchronized(pixbufLock)
304: {
305: createScaledPixbuf(src, hints);
306: }
307: }
308:
309:
313: GtkImage (Pointer pixbuf)
314: {
315: this.pixbuf = pixbuf;
316: synchronized(pixbufLock)
317: {
318: createFromPixbuf();
319: }
320: isLoaded = true;
321: observers = null;
322: props = new Hashtable<String,Object>();
323: }
324:
325:
330: GtkImage(int width, int height, long bufferPointer)
331: {
332: this.width = width;
333: this.height = height;
334: props = new Hashtable<String,Object>();
335: isLoaded = true;
336: observers = null;
337: initFromBuffer( bufferPointer );
338: }
339:
340:
345: static synchronized GtkImage getErrorImage()
346: {
347: if (errorImage == null)
348: {
349: errorImage = new GtkImage();
350: errorImage.errorLoading = true;
351: }
352: return errorImage;
353: }
354:
355:
359: private native void createFromPixbuf();
360:
361:
364: public void setImage(int width, int height,
365: int[] pixels, Hashtable<?,?> properties)
366: {
367: this.width = width;
368: this.height = height;
369: props = (properties != null) ? properties : new Hashtable<String,Object>();
370:
371: if (width <= 0 || height <= 0 || pixels == null)
372: {
373: errorLoading = true;
374: return;
375: }
376:
377: synchronized(pixbufLock)
378: {
379: createPixbuf();
380: setPixels(pixels);
381: }
382: isLoaded = true;
383: deliver();
384: }
385:
386:
387:
388: public synchronized int getWidth (ImageObserver observer)
389: {
390: if (addObserver(observer))
391: return -1;
392:
393: return width;
394: }
395:
396: public synchronized int getHeight (ImageObserver observer)
397: {
398: if (addObserver(observer))
399: return -1;
400:
401: return height;
402: }
403:
404: public synchronized Object getProperty (String name, ImageObserver observer)
405: {
406: if (addObserver(observer))
407: return UndefinedProperty;
408:
409: Object value = props.get (name);
410: return (value == null) ? UndefinedProperty : value;
411: }
412:
413:
416: public ImageProducer getSource ()
417: {
418: if (!isLoaded)
419: return null;
420:
421: int[] pixels;
422: synchronized (pixbufLock)
423: {
424: if (!errorLoading)
425: pixels = getPixels();
426: else
427: return null;
428: }
429: return new MemoryImageSource(width, height, nativeModel, pixels,
430: 0, width);
431: }
432:
433:
436: public Graphics getGraphics ()
437: {
438: throw new IllegalAccessError("This method only works for off-screen"
439: +" Images.");
440: }
441:
442:
445: public Image getScaledInstance(int width,
446: int height,
447: int hints)
448: {
449: if (width <= 0 || height <= 0)
450: throw new IllegalArgumentException("Width and height of scaled bitmap"
451: + "must be >= 0");
452:
453: return new GtkImage(this, width, height, hints);
454: }
455:
456:
464: public synchronized void flush ()
465: {
466: if (isLoaded && source != null)
467: {
468: observers = new Vector<ImageObserver>();
469: isLoaded = false;
470: synchronized(pixbufLock)
471: {
472: freePixbuf();
473: }
474: source.startProduction(new GtkImageConsumer(this, source));
475: }
476: }
477:
478: public void finalize()
479: {
480: if (isLoaded)
481: {
482: synchronized(pixbufLock)
483: {
484: freePixbuf();
485: }
486: }
487: }
488:
489:
492: public int checkImage (ImageObserver observer)
493: {
494: if (addObserver(observer))
495: {
496: if (errorLoading == true)
497: return ImageObserver.ERROR;
498: else
499: return 0;
500: }
501:
502: return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
503: }
504:
505:
506:
507:
508:
511: private void deliver()
512: {
513: int flags = ImageObserver.HEIGHT |
514: ImageObserver.WIDTH |
515: ImageObserver.PROPERTIES |
516: ImageObserver.ALLBITS;
517:
518: if (observers != null)
519: for(int i=0; i < observers.size(); i++)
520: ((ImageObserver)observers.elementAt(i)).imageUpdate(this, flags, 0, 0,
521: width, height);
522:
523: observers = null;
524: }
525:
526:
530: private boolean addObserver(ImageObserver observer)
531: {
532: if (!isLoaded)
533: {
534: if(observer != null)
535: if (!observers.contains (observer))
536: observers.addElement (observer);
537: return true;
538: }
539: return false;
540: }
541: }