Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / gnu / java / awt / peer / gtk / GtkImage.java
blob82a346304eaa358de0af642f40994e2fdcfe2d1e
1 /* GtkImage.java
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package gnu.java.awt.peer.gtk;
41 import java.awt.Graphics;
42 import java.awt.Color;
43 import java.awt.Image;
44 import java.awt.image.ColorModel;
45 import java.awt.image.DirectColorModel;
46 import java.awt.image.MemoryImageSource;
47 import java.awt.image.ImageConsumer;
48 import java.awt.image.ImageObserver;
49 import java.awt.image.ImageProducer;
50 import java.io.File;
51 import java.io.IOException;
52 import java.util.Hashtable;
53 import java.util.Vector;
54 import java.io.ByteArrayOutputStream;
55 import java.io.BufferedInputStream;
56 import java.net.URL;
57 import gnu.classpath.Pointer;
59 /**
60 * GtkImage - wraps a GdkPixbuf or GdkPixmap.
62 * The constructor GtkImage(int, int) creates an 'off-screen' GdkPixmap,
63 * this can be drawn to (it's a GdkDrawable), and correspondingly, you can
64 * create a GdkGraphics object for it.
66 * This corresponds to the Image implementation returned by
67 * Component.createImage(int, int).
69 * A GdkPixbuf is 'on-screen' and the gdk cannot draw to it,
70 * this is used for the other constructors (and other createImage methods), and
71 * corresponds to the Image implementations returned by the Toolkit.createImage
72 * methods, and is basically immutable.
74 * @author Sven de Marothy
76 public class GtkImage extends Image
78 int width = -1, height = -1;
80 /**
81 * Properties.
83 Hashtable props;
85 /**
86 * Loaded or not flag, for asynchronous compatibility.
88 boolean isLoaded;
90 /**
91 * Pointer to the GdkPixbuf
93 Pointer pixmap;
95 /**
96 * Observer queue.
98 Vector observers;
101 * If offScreen is set, a GdkBitmap is wrapped and not a Pixbuf.
103 boolean offScreen;
106 * Error flag for loading.
108 boolean errorLoading;
111 * Original source, if created from an ImageProducer.
113 ImageProducer source;
116 * The 32-bit AABBGGRR format the GDK uses.
118 static ColorModel nativeModel = new DirectColorModel(32,
119 0x000000FF,
120 0x0000FF00,
121 0x00FF0000,
122 0xFF000000);
125 * Returns a copy of the pixel data as a java array.
127 private native int[] getPixels();
130 * Sets the pixel data from a java array.
132 private native void setPixels(int[] pixels);
135 * Loads an image using gdk-pixbuf from a file.
137 private native boolean loadPixbuf(String name);
140 * Loads an image using gdk-pixbuf from data.
142 private native boolean loadImageFromData(byte[] data);
145 * Allocates a Gtk Pixbuf or pixmap
147 private native void createPixmap();
150 * Frees the above.
152 private native void freePixmap();
155 * Sets the pixmap to scaled copy of src image. hints are rendering hints.
157 private native void createScaledPixmap(GtkImage src, int hints);
160 * Draws the image, optionally scaled and composited.
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);
168 * Draws the image, optionally scaled flipped and composited.
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);
181 * Constructs a GtkImage from an ImageProducer. Asynchronity is handled in
182 * the following manner:
183 * A GtkImageConsumer gets the image data, and calls setImage() when
184 * completely finished. The GtkImage is not considered loaded until the
185 * GtkImageConsumer is completely finished. We go for all "all or nothing".
187 public GtkImage (ImageProducer producer)
189 isLoaded = false;
190 observers = new Vector();
191 source = producer;
192 errorLoading = false;
193 source.startProduction(new GtkImageConsumer(this, source));
194 offScreen = false;
198 * Constructs a blank GtkImage. This is called when
199 * GtkToolkit.createImage (String) is called with an empty string
200 * argument (""). A blank image is loaded immediately upon
201 * construction and has width -1 and height -1.
203 public GtkImage ()
205 isLoaded = true;
206 observers = null;
207 offScreen = false;
208 props = new Hashtable();
209 errorLoading = false;
213 * Constructs a GtkImage by loading a given file.
215 * @throws IllegalArgumentException if the image could not be loaded.
217 public GtkImage (String filename)
219 File f = new File(filename);
222 if (loadPixbuf(f.getCanonicalPath()) != true)
223 throw new IllegalArgumentException("Couldn't load image: "+filename);
225 catch(IOException e)
227 throw new IllegalArgumentException("Couldn't load image: "+filename);
230 isLoaded = true;
231 observers = null;
232 offScreen = false;
233 props = new Hashtable();
237 * Constructs a GtkImage from a byte array of an image file.
239 * @throws IllegalArgumentException if the image could not be
240 * loaded.
242 public GtkImage (byte[] data)
244 if (loadImageFromData (data) != true)
245 throw new IllegalArgumentException ("Couldn't load image.");
247 isLoaded = true;
248 observers = null;
249 offScreen = false;
250 props = new Hashtable();
251 errorLoading = false;
255 * Constructs a GtkImage from a URL. May result in an error image.
257 public GtkImage (URL url)
259 isLoaded = false;
260 observers = new Vector();
261 errorLoading = false;
262 if( url == null)
263 return;
264 ByteArrayOutputStream baos = new ByteArrayOutputStream (5000);
267 BufferedInputStream bis = new BufferedInputStream (url.openStream());
269 byte[] buf = new byte[5000];
270 int n = 0;
272 while ((n = bis.read(buf)) != -1)
273 baos.write(buf, 0, n);
274 bis.close();
276 catch(IOException e)
278 throw new IllegalArgumentException ("Couldn't load image.");
280 if (loadImageFromData (baos.toByteArray()) != true)
281 throw new IllegalArgumentException ("Couldn't load image.");
283 isLoaded = true;
284 observers = null;
285 props = new Hashtable();
289 * Constructs an empty GtkImage.
291 public GtkImage (int width, int height)
293 this.width = width;
294 this.height = height;
295 props = new Hashtable();
296 isLoaded = true;
297 observers = null;
298 offScreen = true;
299 createPixmap();
303 * Constructs a scaled version of the src bitmap, using the GDK.
305 private GtkImage (GtkImage src, int width, int height, int hints)
307 this.width = width;
308 this.height = height;
309 props = new Hashtable();
310 isLoaded = true;
311 observers = null;
312 offScreen = false;
314 // Use the GDK scaling method.
315 createScaledPixmap(src, hints);
319 * Package private constructor to create a GtkImage from a given
320 * PixBuf pointer.
322 GtkImage (Pointer pixbuf)
324 pixmap = pixbuf;
325 createFromPixbuf();
326 isLoaded = true;
327 observers = null;
328 offScreen = false;
329 props = new Hashtable();
333 * Native helper function for constructor that takes a pixbuf Pointer.
335 private native void createFromPixbuf();
338 * Callback from the image consumer.
340 public void setImage(int width, int height,
341 int[] pixels, Hashtable properties)
343 this.width = width;
344 this.height = height;
345 props = (properties != null) ? properties : new Hashtable();
347 if (width <= 0 || height <= 0 || pixels == null)
349 errorLoading = true;
350 return;
353 isLoaded = true;
354 deliver();
355 createPixmap();
356 setPixels(pixels);
359 // java.awt.Image methods ////////////////////////////////////////////////
361 public synchronized int getWidth (ImageObserver observer)
363 if (addObserver(observer))
364 return -1;
366 return width;
369 public synchronized int getHeight (ImageObserver observer)
371 if (addObserver(observer))
372 return -1;
374 return height;
377 public synchronized Object getProperty (String name, ImageObserver observer)
379 if (addObserver(observer))
380 return UndefinedProperty;
382 Object value = props.get (name);
383 return (value == null) ? UndefinedProperty : value;
387 * Returns the source of this image.
389 public ImageProducer getSource ()
391 if (!isLoaded)
392 return null;
393 return new MemoryImageSource(width, height, nativeModel, getPixels(),
394 0, width);
398 * Creates a GdkGraphics context for this pixmap.
400 public Graphics getGraphics ()
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.");
412 * Returns a scaled instance of this pixmap.
414 public Image getScaledInstance(int width,
415 int height,
416 int hints)
418 if (width <= 0 || height <= 0)
419 throw new IllegalArgumentException("Width and height of scaled bitmap"+
420 "must be >= 0");
422 return new GtkImage(this, width, height, hints);
426 * If the image is loaded and comes from an ImageProducer,
427 * regenerate the image from there.
429 * I have no idea if this is ever actually used. Since GtkImage can't be
430 * instantiated directly, how is the user to know if it was created from
431 * an ImageProducer or not?
433 public synchronized void flush ()
435 if (isLoaded && source != null)
437 observers = new Vector();
438 isLoaded = false;
439 freePixmap();
440 source.startProduction(new GtkImageConsumer(this, source));
444 public void finalize()
446 if (isLoaded)
447 freePixmap();
451 * Returns the image status, used by GtkToolkit
453 public int checkImage (ImageObserver observer)
455 if (addObserver(observer))
457 if (errorLoading == true)
458 return ImageObserver.ERROR;
459 else
460 return 0;
463 return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
466 // Drawing methods ////////////////////////////////////////////////
469 * Draws an image with eventual scaling/transforming.
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)
475 if (addObserver(observer))
476 return false;
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;
489 // Clipping. This requires the dst to be scaled as well,
490 if (srcWidth > width)
492 dstWidth = (int)((double)dstWidth*((double)width/(double)srcWidth));
493 srcWidth = width - srcX;
496 if (srcHeight > height)
498 dstHeight = (int)((double)dstHeight*((double)height/(double)srcHeight));
499 srcHeight = height - srcY;
502 if (srcWidth + srcX > width)
504 dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth);
505 srcWidth = width - srcX;
508 if (srcHeight + srcY > height)
510 dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight);
511 srcHeight = height - srcY;
514 if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0)
515 return true;
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;
535 * Draws an image to the GdkGraphics context, at (x,y) scaled to
536 * width and height, with optional compositing with a background color.
538 public boolean drawImage (GdkGraphics g, int x, int y, int width, int height,
539 Color bgcolor, ImageObserver observer)
541 if (addObserver(observer))
542 return false;
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);
550 return true;
553 // Private methods ////////////////////////////////////////////////
556 * Delivers notifications to all queued observers.
558 private void deliver()
560 int flags = ImageObserver.HEIGHT |
561 ImageObserver.WIDTH |
562 ImageObserver.PROPERTIES |
563 ImageObserver.ALLBITS;
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);
570 observers = null;
574 * Adds an observer, if we need to.
575 * @return true if an observer was added.
577 private boolean addObserver(ImageObserver observer)
579 if (!isLoaded)
581 if(observer != null)
582 if (!observers.contains (observer))
583 observers.addElement (observer);
584 return true;
586 return false;