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: import ;
57: import ;
58:
59:
76: public class GtkImage extends Image
77: {
78: int width = -1, height = -1;
79:
80:
83: Hashtable props;
84:
85:
88: boolean isLoaded;
89:
90:
93: Pointer pixmap;
94:
95:
98: Vector observers;
99:
100:
103: boolean offScreen;
104:
105:
108: boolean errorLoading;
109:
110:
113: ImageProducer source;
114:
115:
118: static ColorModel nativeModel = new DirectColorModel(32,
119: 0x000000FF,
120: 0x0000FF00,
121: 0x00FF0000,
122: 0xFF000000);
123:
124:
127: private native int[] getPixels();
128:
129:
132: private native void setPixels(int[] pixels);
133:
134:
137: private native boolean loadPixbuf(String name);
138:
139:
142: private native boolean loadImageFromData(byte[] data);
143:
144:
147: private native void createPixmap();
148:
149:
152: private native void freePixmap();
153:
154:
157: private native void createScaledPixmap(GtkImage src, int hints);
158:
159:
162: private native void drawPixelsScaled (GdkGraphics gc,
163: int bg_red, int bg_green, int bg_blue,
164: int x, int y, int width, int height,
165: boolean composite);
166:
167:
170: private native void drawPixelsScaledFlipped (GdkGraphics gc,
171: int bg_red, int bg_green,
172: int bg_blue,
173: boolean flipX, boolean flipY,
174: int srcX, int srcY,
175: int srcWidth, int srcHeight,
176: int dstX, int dstY,
177: int dstWidth, int dstHeight,
178: boolean composite);
179:
180:
187: public GtkImage (ImageProducer producer)
188: {
189: isLoaded = false;
190: observers = new Vector();
191: source = producer;
192: errorLoading = false;
193: source.startProduction(new GtkImageConsumer(this, source));
194: offScreen = false;
195: }
196:
197:
203: public GtkImage ()
204: {
205: isLoaded = true;
206: observers = null;
207: offScreen = false;
208: props = new Hashtable();
209: errorLoading = false;
210: }
211:
212:
217: public GtkImage (String filename)
218: {
219: File f = new File(filename);
220: try
221: {
222: if (loadPixbuf(f.getCanonicalPath()) != true)
223: throw new IllegalArgumentException("Couldn't load image: "+filename);
224: }
225: catch(IOException e)
226: {
227: throw new IllegalArgumentException("Couldn't load image: "+filename);
228: }
229:
230: isLoaded = true;
231: observers = null;
232: offScreen = false;
233: props = new Hashtable();
234: }
235:
236:
242: public GtkImage (byte[] data)
243: {
244: if (loadImageFromData (data) != true)
245: throw new IllegalArgumentException ("Couldn't load image.");
246:
247: isLoaded = true;
248: observers = null;
249: offScreen = false;
250: props = new Hashtable();
251: errorLoading = false;
252: }
253:
254:
257: public GtkImage (URL url)
258: {
259: isLoaded = false;
260: observers = new Vector();
261: errorLoading = false;
262: if( url == null)
263: return;
264: ByteArrayOutputStream baos = new ByteArrayOutputStream (5000);
265: try
266: {
267: BufferedInputStream bis = new BufferedInputStream (url.openStream());
268:
269: byte[] buf = new byte[5000];
270: int n = 0;
271:
272: while ((n = bis.read(buf)) != -1)
273: baos.write(buf, 0, n);
274: bis.close();
275: }
276: catch(IOException e)
277: {
278: throw new IllegalArgumentException ("Couldn't load image.");
279: }
280: if (loadImageFromData (baos.toByteArray()) != true)
281: throw new IllegalArgumentException ("Couldn't load image.");
282:
283: isLoaded = true;
284: observers = null;
285: props = new Hashtable();
286: }
287:
288:
291: public GtkImage (int width, int height)
292: {
293: this.width = width;
294: this.height = height;
295: props = new Hashtable();
296: isLoaded = true;
297: observers = null;
298: offScreen = true;
299: createPixmap();
300: }
301:
302:
305: private GtkImage (GtkImage src, int width, int height, int hints)
306: {
307: this.width = width;
308: this.height = height;
309: props = new Hashtable();
310: isLoaded = true;
311: observers = null;
312: offScreen = false;
313:
314:
315: createScaledPixmap(src, hints);
316: }
317:
318:
322: GtkImage (Pointer pixbuf)
323: {
324: pixmap = pixbuf;
325: createFromPixbuf();
326: isLoaded = true;
327: observers = null;
328: offScreen = false;
329: props = new Hashtable();
330: }
331:
332:
335: private native void createFromPixbuf();
336:
337:
340: public void setImage(int width, int height,
341: int[] pixels, Hashtable properties)
342: {
343: this.width = width;
344: this.height = height;
345: props = (properties != null) ? properties : new Hashtable();
346:
347: if (width <= 0 || height <= 0 || pixels == null)
348: {
349: errorLoading = true;
350: return;
351: }
352:
353: isLoaded = true;
354: deliver();
355: createPixmap();
356: setPixels(pixels);
357: }
358:
359:
360:
361: public synchronized int getWidth (ImageObserver observer)
362: {
363: if (addObserver(observer))
364: return -1;
365:
366: return width;
367: }
368:
369: public synchronized int getHeight (ImageObserver observer)
370: {
371: if (addObserver(observer))
372: return -1;
373:
374: return height;
375: }
376:
377: public synchronized Object getProperty (String name, ImageObserver observer)
378: {
379: if (addObserver(observer))
380: return UndefinedProperty;
381:
382: Object value = props.get (name);
383: return (value == null) ? UndefinedProperty : value;
384: }
385:
386:
389: public ImageProducer getSource ()
390: {
391: if (!isLoaded)
392: return null;
393: return new MemoryImageSource(width, height, nativeModel, getPixels(),
394: 0, width);
395: }
396:
397:
400: public Graphics getGraphics ()
401: {
402: if (!isLoaded)
403: return null;
404: if (offScreen)
405: return new GdkGraphics(this);
406: else
407: throw new IllegalAccessError("This method only works for off-screen"
408: +" Images.");
409: }
410:
411:
414: public Image getScaledInstance(int width,
415: int height,
416: int hints)
417: {
418: if (width <= 0 || height <= 0)
419: throw new IllegalArgumentException("Width and height of scaled bitmap"+
420: "must be >= 0");
421:
422: return new GtkImage(this, width, height, hints);
423: }
424:
425:
433: public synchronized void flush ()
434: {
435: if (isLoaded && source != null)
436: {
437: observers = new Vector();
438: isLoaded = false;
439: freePixmap();
440: source.startProduction(new GtkImageConsumer(this, source));
441: }
442: }
443:
444: public void finalize()
445: {
446: if (isLoaded)
447: freePixmap();
448: }
449:
450:
453: public int checkImage (ImageObserver observer)
454: {
455: if (addObserver(observer))
456: {
457: if (errorLoading == true)
458: return ImageObserver.ERROR;
459: else
460: return 0;
461: }
462:
463: return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
464: }
465:
466:
467:
468:
471: public boolean drawImage (GdkGraphics g, int dx1, int dy1, int dx2, int dy2,
472: int sx1, int sy1, int sx2, int sy2,
473: Color bgcolor, ImageObserver observer)
474: {
475: if (addObserver(observer))
476: return false;
477:
478: boolean flipX = (dx1 > dx2)^(sx1 > sx2);
479: boolean flipY = (dy1 > dy2)^(sy1 > sy2);
480: int dstWidth = Math.abs (dx2 - dx1);
481: int dstHeight = Math.abs (dy2 - dy1);
482: int srcWidth = Math.abs (sx2 - sx1);
483: int srcHeight = Math.abs (sy2 - sy1);
484: int srcX = (sx1 < sx2) ? sx1 : sx2;
485: int srcY = (sy1 < sy2) ? sy1 : sy2;
486: int dstX = (dx1 < dx2) ? dx1 : dx2;
487: int dstY = (dy1 < dy2) ? dy1 : dy2;
488:
489:
490: if (srcWidth > width)
491: {
492: dstWidth = (int)((double)dstWidth*((double)width/(double)srcWidth));
493: srcWidth = width - srcX;
494: }
495:
496: if (srcHeight > height)
497: {
498: dstHeight = (int)((double)dstHeight*((double)height/(double)srcHeight));
499: srcHeight = height - srcY;
500: }
501:
502: if (srcWidth + srcX > width)
503: {
504: dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth);
505: srcWidth = width - srcX;
506: }
507:
508: if (srcHeight + srcY > height)
509: {
510: dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight);
511: srcHeight = height - srcY;
512: }
513:
514: if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0)
515: return true;
516:
517: if(bgcolor != null)
518: drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
519: bgcolor.getBlue (),
520: flipX, flipY,
521: srcX, srcY,
522: srcWidth, srcHeight,
523: dstX, dstY,
524: dstWidth, dstHeight,
525: true);
526: else
527: drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
528: srcX, srcY, srcWidth, srcHeight,
529: dstX, dstY, dstWidth, dstHeight,
530: false);
531: return true;
532: }
533:
534:
538: public boolean drawImage (GdkGraphics g, int x, int y, int width, int height,
539: Color bgcolor, ImageObserver observer)
540: {
541: if (addObserver(observer))
542: return false;
543:
544: if(bgcolor != null)
545: drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
546: bgcolor.getBlue (), x, y, width, height, true);
547: else
548: drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
549:
550: return true;
551: }
552:
553:
554:
555:
558: private void deliver()
559: {
560: int flags = ImageObserver.HEIGHT |
561: ImageObserver.WIDTH |
562: ImageObserver.PROPERTIES |
563: ImageObserver.ALLBITS;
564:
565: if (observers != null)
566: for(int i=0; i < observers.size(); i++)
567: ((ImageObserver)observers.elementAt(i)).
568: imageUpdate(this, flags, 0, 0, width, height);
569:
570: observers = null;
571: }
572:
573:
577: private boolean addObserver(ImageObserver observer)
578: {
579: if (!isLoaded)
580: {
581: if(observer != null)
582: if (!observers.contains (observer))
583: observers.addElement (observer);
584: return true;
585: }
586: return false;
587: }
588: }