1 /* QtVolatileImage.java --
2    Copyright (C)  2005, 2006  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
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.
10 
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.
15 
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.
20 
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.
25 
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. */
37 
38 package gnu.java.awt.peer.qt;
39 
40 import java.awt.Graphics;
41 import java.awt.Graphics2D;
42 import java.awt.Color;
43 import java.awt.Image;
44 import java.awt.ImageCapabilities;
45 import java.awt.GraphicsConfiguration;
46 import java.awt.image.BufferedImage;
47 import java.awt.image.ColorModel;
48 import java.awt.image.DirectColorModel;
49 import java.awt.image.MemoryImageSource;
50 import java.awt.image.ImageObserver;
51 import java.awt.image.ImageProducer;
52 import java.awt.image.VolatileImage;
53 import java.util.Hashtable;
54 import java.util.WeakHashMap;
55 
56 /**
57  * QtVolatileImage - wraps a QImage
58  *
59  */
60 public class QtVolatileImage extends VolatileImage
61 {
62   int width = -1, height = -1;
63 
64   /**
65    * Properties.
66    */
67   Hashtable props;
68 
69   /**
70    * Pointer to the QImage
71    */
72   long nativeObject;
73 
74   /*
75    * The 32-bit AARRGGBB format the  uses.
76    */
77   static ColorModel nativeModel = new DirectColorModel(32,
78                                                        0x00FF0000,
79                                                        0x0000FF00,
80                                                        0x000000FF,
81                                                        0xFF000000);
82 
83   /**
84    * Clears the image to RGBA 0
85    */
clear()86   public native void clear();
87 
88   /**
89    * Returns a copy of the pixel data as a java array.
90    */
getPixels()91   private native int[] getPixels();
92 
93   /**
94    * Allocates a QImage
95    */
createImage()96   private native void createImage();
97 
98   /**
99    * HashMap of Graphics objects painting on this Image.
100    */
101   WeakHashMap painters;
102 
103   /**
104    * Flags if this image is to be destroyed.
105    */
106   boolean killFlag;
107 
108   /**
109    * Frees the above.
110    */
freeImage()111   private native void freeImage();
112 
113   /**
114    * Blit a QImage
115    */
blit(QtImage i)116   public native void blit(QtImage i);
blit(QtImage i, int x, int y, int w, int h)117   public native void blit(QtImage i, int x, int y, int w, int h);
118 
119   /**
120    * Sets the image to scaled copy of src image. hints are rendering hints.
121    */
createScaledImage(QtVolatileImage src, int hints)122   private native void createScaledImage(QtVolatileImage src, int hints);
123 
124   /**
125    * Draws the image optionally composited.
126    */
drawPixels(QtGraphics gc, int bg_red, int bg_green, int bg_blue, int x, int y, boolean composite)127   private native void drawPixels (QtGraphics gc,
128                                   int bg_red, int bg_green, int bg_blue,
129                                   int x, int y,
130                                   boolean composite);
131   /**
132    * Draws the image, optionally scaled and composited.
133    */
drawPixelsScaled(QtGraphics gc, int bg_red, int bg_green, int bg_blue, int x, int y, int width, int height, boolean composite)134   private native void drawPixelsScaled (QtGraphics gc,
135                                         int bg_red, int bg_green, int bg_blue,
136                                         int x, int y, int width, int height,
137                                         boolean composite);
138 
139   /**
140    * Draws the image transformed.
141    */
drawPixelsTransformed(QtGraphics gc, QMatrix transform)142   private native void drawPixelsTransformed (QtGraphics gc, QMatrix transform);
143 
144   /**
145    * Draws the image scaled flipped and optionally composited.
146    */
drawPixelsScaledFlipped(QtGraphics gc, int bg_red, int bg_green, int bg_blue, boolean flipX, boolean flipY, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight, boolean composite)147   native void drawPixelsScaledFlipped (QtGraphics gc,
148                                        int bg_red, int bg_green,
149                                        int bg_blue,
150                                        boolean flipX, boolean flipY,
151                                        int srcX, int srcY,
152                                        int srcWidth, int srcHeight,
153                                        int dstX, int dstY,
154                                        int dstWidth, int dstHeight,
155                                        boolean composite);
156 
157   /**
158    * Constructs an empty QtVolatileImage.
159    */
QtVolatileImage(int width, int height)160   public QtVolatileImage (int width, int height)
161   {
162     this.width = width;
163     this.height = height;
164     props = new Hashtable();
165     createImage();
166     clear();
167   }
168 
169   /**
170    * Constructs a scaled version of the src bitmap, using Qt
171    */
QtVolatileImage(QtVolatileImage src, int width, int height, int hints)172   private QtVolatileImage (QtVolatileImage src, int width, int height,
173                            int hints)
174   {
175     this.width = width;
176     this.height = height;
177     props = new Hashtable();
178 
179     createScaledImage(src, hints);
180   }
181 
182 
finalize()183   public void finalize()
184   {
185     dispose();
186   }
187 
dispose()188   public void dispose()
189   {
190     if( painters == null || painters.isEmpty() )
191       freeImage();
192     else
193       killFlag = true; // can't destroy image yet.
194     // Do so when all painters are gone.
195   }
196 
197   // java.awt.Image methods ////////////////////////////////////////////////
198 
getWidth(ImageObserver observer)199   public int getWidth (ImageObserver observer)
200   {
201     return getWidth();
202   }
203 
getHeight(ImageObserver observer)204   public int getHeight (ImageObserver observer)
205   {
206     return getHeight();
207   }
208 
getProperty(String name, ImageObserver observer)209   public Object getProperty (String name, ImageObserver observer)
210   {
211     Object value = props.get (name);
212     return (value == null) ? UndefinedProperty : value;
213   }
214 
215   /**
216    * Returns the source of this image.
217    */
getSource()218   public ImageProducer getSource ()
219   {
220     return new MemoryImageSource(width, height, nativeModel, getPixels(),
221                                  0, width);
222   }
223 
putPainter(QtImageGraphics g)224   void putPainter(QtImageGraphics g)
225   {
226     if( painters == null )
227       painters = new WeakHashMap();
228     painters.put( g, "dummy" );
229   }
230 
removePainter(QtImageGraphics g)231   void removePainter(QtImageGraphics g)
232   {
233     painters.remove( g );
234     if( killFlag && painters.isEmpty() )
235       freeImage();
236   }
237 
238   /**
239    * Creates a Graphics context for this image.
240    */
getGraphics()241   public Graphics getGraphics ()
242   {
243     QtImageGraphics g = new QtImageGraphics( this );
244     putPainter( g );
245     return g;
246   }
247 
248   /**
249    * Returns a scaled instance of this image.
250    */
getScaledInstance(int width, int height, int hints)251   public Image getScaledInstance(int width,
252                                  int height,
253                                  int hints)
254   {
255     if (width <= 0 || height <= 0)
256       throw new IllegalArgumentException("Width and height of scaled bitmap"+
257                                          "must be >= 0");
258 
259     return new QtVolatileImage(this, width, height, hints);
260   }
261 
262   /**
263    */
flush()264   public void flush ()
265   {
266     // FIXME ?
267   }
268 
269   /**
270    * Returns the image status, used by QtToolkit
271    */
checkImage(ImageObserver observer)272   public int checkImage (ImageObserver observer)
273   {
274     return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
275   }
276 
277   // Drawing methods ////////////////////////////////////////////////
278 
279   /**
280    * Draws an image with eventual scaling/transforming.
281    */
drawImage(QtGraphics g, QMatrix matrix, ImageObserver observer)282   public boolean drawImage (QtGraphics g, QMatrix matrix,
283                             ImageObserver observer)
284   {
285     drawPixelsTransformed (g, matrix);
286     return true;
287   }
288 
289   /**
290    * Draws an image to the QtGraphics context, at (x,y) with optional
291    * compositing with a background color.
292    */
drawImage(QtGraphics g, int x, int y, Color bgcolor, ImageObserver observer)293   public boolean drawImage (QtGraphics g, int x, int y,
294                             Color bgcolor, ImageObserver observer)
295   {
296     if(bgcolor != null)
297       drawPixels(g, bgcolor.getRed (), bgcolor.getGreen (),
298                  bgcolor.getBlue (), x, y, true);
299     else
300       drawPixels(g, 0, 0, 0, x, y, false);
301 
302     return true;
303   }
304 
305   /**
306    * Draws an image to the QtGraphics context, at (x,y) scaled to
307    * width and height, with optional compositing with a background color.
308    */
drawImage(QtGraphics g, int x, int y, int width, int height, Color bgcolor, ImageObserver observer)309   public boolean drawImage (QtGraphics g, int x, int y, int width, int height,
310                             Color bgcolor, ImageObserver observer)
311   {
312     if(bgcolor != null)
313       drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
314                        bgcolor.getBlue (), x, y, width, height, true);
315     else
316       drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
317 
318     return true;
319   }
320 
321   /**
322    * Draws an image with eventual scaling/transforming.
323    */
drawImage(QtGraphics g, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer)324   public boolean drawImage (QtGraphics g, int dx1, int dy1, int dx2, int dy2,
325                             int sx1, int sy1, int sx2, int sy2,
326                             Color bgcolor, ImageObserver observer)
327   {
328     boolean flipX = (dx1 > dx2)^(sx1 > sx2);
329     boolean flipY = (dy1 > dy2)^(sy1 > sy2);
330     int dstWidth = Math.abs (dx2 - dx1);
331     int dstHeight = Math.abs (dy2 - dy1);
332     int srcWidth = Math.abs (sx2 - sx1);
333     int srcHeight = Math.abs (sy2 - sy1);
334     int srcX = (sx1 < sx2) ? sx1 : sx2;
335     int srcY = (sy1 < sy2) ? sy1 : sy2;
336     int dstX = (dx1 < dx2) ? dx1 : dx2;
337     int dstY = (dy1 < dy2) ? dy1 : dy2;
338 
339     // Clipping. This requires the dst to be scaled as well,
340     if (srcWidth > width)
341       {
342         dstWidth = (int)((double)dstWidth*((double)width/(double)srcWidth));
343         srcWidth = width - srcX;
344       }
345 
346     if (srcHeight > height)
347       {
348         dstHeight = (int)((double)dstHeight*((double)height/(double)srcHeight));
349         srcHeight = height - srcY;
350       }
351 
352     if (srcWidth + srcX > width)
353       {
354         dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth);
355         srcWidth = width - srcX;
356       }
357 
358     if (srcHeight + srcY > height)
359       {
360         dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight);
361         srcHeight = height - srcY;
362       }
363 
364     if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0)
365       return true;
366 
367     if(bgcolor != null)
368       drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
369                                bgcolor.getBlue (),
370                                flipX, flipY,
371                                srcX, srcY,
372                                srcWidth, srcHeight,
373                                dstX,  dstY,
374                                dstWidth, dstHeight,
375                                true);
376     else
377       drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
378                                srcX, srcY, srcWidth, srcHeight,
379                                dstX,  dstY, dstWidth, dstHeight,
380                                false);
381     return true;
382   }
383 
copyArea(int x, int y, int width, int height, int dx, int dy)384   public native void copyArea(int x, int y, int width, int height,
385                               int dx, int dy);
386 
387   //******************** VolatileImage stuff ********************
388 
contentsLost()389   public boolean contentsLost()
390   {
391     return false;
392   }
393 
createGraphics()394   public Graphics2D createGraphics()
395   {
396     QtImageGraphics g = new QtImageGraphics(this);
397     putPainter( g );
398     return g;
399   }
400 
getCapabilities()401   public ImageCapabilities getCapabilities()
402   {
403     return new ImageCapabilities(false)
404       {
405         public boolean isTrueVolatile()
406         {
407           return false;
408         }
409       };
410   }
411 
412   public int getHeight()
413   {
414     return height;
415   }
416 
417   public BufferedImage getSnapshot()
418   {
419     BufferedImage bi = new BufferedImage(width, height,
420                                          BufferedImage.TYPE_INT_ARGB_PRE);
421     bi.setRGB( 0, 0, width, height, getPixels(), 0, width);
422     return bi;
423   }
424 
425   public int getWidth()
426   {
427     return width;
428   }
429 
430   public int validate(GraphicsConfiguration gc)
431   {
432     return IMAGE_OK;
433   }
434 }
435