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