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)
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
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
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. */
38 package gnu
.java
.awt
.peer
.qt
;
40 import java
.awt
.Graphics
;
41 import java
.awt
.Color
;
42 import java
.awt
.Image
;
43 import java
.awt
.image
.ColorModel
;
44 import java
.awt
.image
.DirectColorModel
;
45 import java
.awt
.image
.MemoryImageSource
;
46 import java
.awt
.image
.ImageConsumer
;
47 import java
.awt
.image
.ImageObserver
;
48 import java
.awt
.image
.ImageProducer
;
50 import java
.io
.IOException
;
51 import java
.io
.ByteArrayOutputStream
;
52 import java
.io
.BufferedInputStream
;
54 import java
.util
.Hashtable
;
55 import java
.util
.WeakHashMap
;
56 import java
.util
.Vector
;
59 * QtImage - wraps a QImage
62 public class QtImage
extends Image
64 int width
= -1, height
= -1;
72 * Loaded or not flag, for asynchronous compatibility.
77 * Pointer to the QImage
87 * Error flag for loading.
92 * Original source, if created from an ImageProducer.
97 * The 32-bit AARRGGBB format the uses.
99 static ColorModel nativeModel
= new DirectColorModel(32,
105 * HashMap of Graphics objects painting on this Image.
107 WeakHashMap painters
;
110 * Flags if this image is to be destroyed.
115 * Clears the image to RGBA 0
117 public native void clear();
120 * Returns a copy of the pixel data as a java array.
122 private native int[] getPixels();
125 * Sets the pixel data from a java array.
127 private native void setPixels(int[] pixels
);
132 private native boolean loadImage(String name
);
135 * Loads an image from data.
137 private native boolean loadImageFromData(byte[] data
);
142 private native void createImage();
147 private synchronized native void freeImage();
150 * Sets the image to scaled copy of src image. hints are rendering hints.
152 private native void createScaledImage(QtImage src
, int hints
);
155 * Draws the image optionally composited.
157 native void drawPixels (QtGraphics gc
,
158 int bg_red
, int bg_green
, int bg_blue
,
162 * Draws the image, optionally scaled and composited.
164 private native void drawPixelsScaled (QtGraphics gc
,
165 int bg_red
, int bg_green
, int bg_blue
,
166 int x
, int y
, int width
, int height
,
170 * Draws the image transformed.
172 private native void drawPixelsTransformed (QtGraphics gc
, QMatrix transform
);
175 * Draws the image scaled flipped and optionally composited.
177 native void drawPixelsScaledFlipped (QtGraphics gc
,
178 int bg_red
, int bg_green
,
180 boolean flipX
, boolean flipY
,
182 int srcWidth
, int srcHeight
,
184 int dstWidth
, int dstHeight
,
188 * Creates the image from an ImageProducer. May result in an error image.
190 public QtImage (ImageProducer producer
)
194 observers
= new Vector();
196 errorLoading
= false;
197 if( producer
!= null )
198 source
.startProduction(new QtImageConsumer(this, source
));
202 * Creates the image from a URL. May result in an error image.
204 public QtImage (URL url
)
208 observers
= new Vector();
209 errorLoading
= false;
212 ByteArrayOutputStream baos
= new ByteArrayOutputStream( 5000 );
215 BufferedInputStream bis
= new BufferedInputStream(url
.openStream());
217 byte[] buf
= new byte[5000];
220 while ( (n
= bis
.read( buf
)) != -1 )
221 baos
.write(buf
, 0, n
);
226 throw new IllegalArgumentException("Couldn't load image.");
228 if ( loadImageFromData( baos
.toByteArray() ) != true )
229 throw new IllegalArgumentException("Couldn't load image.");
233 props
= new Hashtable();
237 * Constructs a QtImage by loading a given file.
239 * @throws IllegalArgumentException if the image could not be loaded.
241 public QtImage (String filename
)
244 File f
= new File(filename
);
246 props
= new Hashtable();
249 String fn
= f
.getCanonicalPath();
250 if (loadImage( fn
) != true)
263 errorLoading
= false;
268 * Constructs a QtImage from a byte array of an image file.
270 * @throws IllegalArgumentException if the image could not be loaded.
272 public QtImage (byte[] data
)
274 if (loadImageFromData(data
) != true)
275 throw new IllegalArgumentException("Couldn't load image.");
280 errorLoading
= false;
281 props
= new Hashtable();
285 * Constructs an empty QtImage.
287 public QtImage (int width
, int height
)
290 this.height
= height
;
291 props
= new Hashtable();
295 errorLoading
= false;
301 * Constructs a scaled version of the src bitmap, using Qt
303 private QtImage (QtImage src
, int width
, int height
, int hints
)
306 this.height
= height
;
307 props
= new Hashtable();
311 errorLoading
= false;
313 createScaledImage(src
, hints
);
317 * Callback from the image consumer.
319 public void setImage(int width
, int height
,
320 int[] pixels
, Hashtable properties
)
323 this.height
= height
;
324 props
= (properties
!= null) ? properties
: new Hashtable();
326 if (width
<= 0 || height
<= 0 || pixels
== null)
338 // java.awt.Image methods ////////////////////////////////////////////////
340 public int getWidth (ImageObserver observer
)
342 if (addObserver(observer
))
348 public int getHeight (ImageObserver observer
)
350 if (addObserver(observer
))
356 public Object
getProperty (String name
, ImageObserver observer
)
358 if (addObserver(observer
))
359 return UndefinedProperty
;
361 Object value
= props
.get (name
);
362 return (value
== null) ? UndefinedProperty
: value
;
366 * Returns the source of this image.
368 public ImageProducer
getSource ()
372 return new MemoryImageSource(width
, height
, nativeModel
, getPixels(),
376 void putPainter(QtImageGraphics g
)
378 if( painters
== null )
379 painters
= new WeakHashMap();
380 painters
.put( g
, "dummy" );
383 void removePainter(QtImageGraphics g
)
385 painters
.remove( g
);
386 if( killFlag
&& painters
.isEmpty() )
391 * Creates a Graphics context for this image.
393 public Graphics
getGraphics ()
395 if (!isLoaded
|| killFlag
)
398 return new QtImageGraphics(this);
402 * Creates a Graphics context for this image.
404 Graphics
getDirectGraphics(QtComponentPeer peer
)
409 return new QtImageDirectGraphics(this, peer
);
413 * Returns a scaled instance of this image.
415 public Image
getScaledInstance(int width
,
419 if (width
<= 0 || height
<= 0)
420 throw new IllegalArgumentException("Width and height of scaled bitmap"+
423 return new QtImage(this, width
, height
, hints
);
427 * If the image is loaded and comes from an ImageProducer,
428 * regenerate the image from there.
430 * I have no idea if this is ever actually used. Since QtImage can't be
431 * instantiated directly, how is the user to know if it was created from
432 * an ImageProducer or not?
434 public synchronized void flush ()
436 if (isLoaded
&& source
!= null)
438 observers
= new Vector();
441 source
.startProduction(new QtImageConsumer(this, source
));
445 public void finalize()
450 public void dispose()
454 if( painters
== null || painters
.isEmpty() )
457 killFlag
= true; // can't destroy image yet.
458 // Do so when all painters are gone.
463 * Returns the image status, used by QtToolkit
465 public int checkImage (ImageObserver observer
)
467 if (addObserver(observer
))
469 if (errorLoading
== true)
470 return ImageObserver
.ERROR
;
475 return ImageObserver
.ALLBITS
| ImageObserver
.WIDTH
| ImageObserver
.HEIGHT
;
478 // Drawing methods ////////////////////////////////////////////////
481 * Draws an image with eventual scaling/transforming.
483 public boolean drawImage (QtGraphics g
, QMatrix matrix
,
484 ImageObserver observer
)
486 if (addObserver(observer
))
489 drawPixelsTransformed (g
, matrix
);
495 * Draws an image to the QtGraphics context, at (x,y) with optional
496 * compositing with a background color.
498 public boolean drawImage (QtGraphics g
, int x
, int y
,
499 Color bgcolor
, ImageObserver observer
)
501 if (addObserver(observer
))
505 drawPixels(g
, bgcolor
.getRed (), bgcolor
.getGreen (),
506 bgcolor
.getBlue (), x
, y
, true);
508 drawPixels(g
, 0, 0, 0, x
, y
, false);
514 * Draws an image to the QtGraphics context, at (x,y) scaled to
515 * width and height, with optional compositing with a background color.
517 public boolean drawImage (QtGraphics g
, int x
, int y
, int width
, int height
,
518 Color bgcolor
, ImageObserver observer
)
520 if (addObserver(observer
))
524 drawPixelsScaled(g
, bgcolor
.getRed (), bgcolor
.getGreen (),
525 bgcolor
.getBlue (), x
, y
, width
, height
, true);
527 drawPixelsScaled(g
, 0, 0, 0, x
, y
, width
, height
, false);
533 * Draws an image with eventual scaling/transforming.
535 public boolean drawImage (QtGraphics g
, int dx1
, int dy1
, int dx2
, int dy2
,
536 int sx1
, int sy1
, int sx2
, int sy2
,
537 Color bgcolor
, ImageObserver observer
)
539 if (addObserver(observer
))
542 boolean flipX
= (dx1
> dx2
)^
(sx1
> sx2
);
543 boolean flipY
= (dy1
> dy2
)^
(sy1
> sy2
);
544 int dstWidth
= Math
.abs (dx2
- dx1
);
545 int dstHeight
= Math
.abs (dy2
- dy1
);
546 int srcWidth
= Math
.abs (sx2
- sx1
);
547 int srcHeight
= Math
.abs (sy2
- sy1
);
548 int srcX
= (sx1
< sx2
) ? sx1
: sx2
;
549 int srcY
= (sy1
< sy2
) ? sy1
: sy2
;
550 int dstX
= (dx1
< dx2
) ? dx1
: dx2
;
551 int dstY
= (dy1
< dy2
) ? dy1
: dy2
;
553 // Clipping. This requires the dst to be scaled as well,
554 if (srcWidth
> width
)
556 dstWidth
= (int)((double)dstWidth
*((double)width
/(double)srcWidth
));
557 srcWidth
= width
- srcX
;
560 if (srcHeight
> height
)
562 dstHeight
= (int)((double)dstHeight
*((double)height
/(double)srcHeight
));
563 srcHeight
= height
- srcY
;
566 if (srcWidth
+ srcX
> width
)
568 dstWidth
= (int)((double)dstWidth
* (double)(width
- srcX
)/(double)srcWidth
);
569 srcWidth
= width
- srcX
;
572 if (srcHeight
+ srcY
> height
)
574 dstHeight
= (int)((double)dstHeight
* (double)(width
- srcY
)/(double)srcHeight
);
575 srcHeight
= height
- srcY
;
578 if ( srcWidth
<= 0 || srcHeight
<= 0 || dstWidth
<= 0 || dstHeight
<= 0)
582 drawPixelsScaledFlipped (g
, bgcolor
.getRed (), bgcolor
.getGreen (),
591 drawPixelsScaledFlipped (g
, 0, 0, 0, flipX
, flipY
,
592 srcX
, srcY
, srcWidth
, srcHeight
,
593 dstX
, dstY
, dstWidth
, dstHeight
,
598 public native void copyArea(int x
, int y
, int width
, int height
,
601 // Private methods ////////////////////////////////////////////////
604 * Delivers notifications to all queued observers.
606 private void deliver()
608 int flags
= ImageObserver
.HEIGHT
|
609 ImageObserver
.WIDTH
|
610 ImageObserver
.PROPERTIES
|
611 ImageObserver
.ALLBITS
;
613 if (observers
!= null)
614 for(int i
=0; i
< observers
.size(); i
++)
615 ((ImageObserver
)observers
.elementAt(i
)).
616 imageUpdate(this, flags
, 0, 0, width
, height
);
622 * Adds an observer, if we need to.
623 * @return true if an observer was added.
625 private boolean addObserver(ImageObserver observer
)
630 if (!observers
.contains (observer
))
631 observers
.addElement (observer
);
637 public String
toString()
639 return "QtImage [isLoaded="+isLoaded
+", width="+width
+", height="+height