Source for gnu.java.awt.peer.qt.QtVolatileImage

   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:    */
  86:   public native void clear();
  87: 
  88:   /**
  89:    * Returns a copy of the pixel data as a java array.
  90:    */
  91:   private native int[] getPixels();
  92: 
  93:   /**
  94:    * Allocates a QImage
  95:    */
  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:    */
 111:   private native void freeImage();
 112: 
 113:   /**
 114:    * Blit a QImage
 115:    */
 116:   public native void blit(QtImage i);
 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:    */
 122:   private native void createScaledImage(QtVolatileImage src, int hints);
 123: 
 124:   /**
 125:    * Draws the image optionally composited.
 126:    */
 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:    */
 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:    */
 142:   private native void drawPixelsTransformed (QtGraphics gc, QMatrix transform);
 143: 
 144:   /**
 145:    * Draws the image scaled flipped and optionally composited.
 146:    */
 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:    */
 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:    */
 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: 
 183:   public void finalize()
 184:   {
 185:     dispose();
 186:   }
 187: 
 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: 
 199:   public int getWidth (ImageObserver observer)
 200:   {
 201:     return getWidth();
 202:   }
 203: 
 204:   public int getHeight (ImageObserver observer)
 205:   {
 206:     return getHeight();
 207:   }
 208: 
 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:    */
 218:   public ImageProducer getSource ()
 219:   {
 220:     return new MemoryImageSource(width, height, nativeModel, getPixels(),
 221:                                  0, width);
 222:   }
 223: 
 224:   void putPainter(QtImageGraphics g)
 225:   {
 226:     if( painters == null )
 227:       painters = new WeakHashMap();
 228:     painters.put( g, "dummy" );
 229:   }
 230: 
 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:    */
 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:    */
 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:    */
 264:   public void flush ()
 265:   {
 266:     // FIXME ?
 267:   }
 268: 
 269:   /**
 270:    * Returns the image status, used by QtToolkit
 271:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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: 
 384:   public native void copyArea(int x, int y, int width, int height,
 385:                               int dx, int dy);
 386: 
 387:   //******************** VolatileImage stuff ********************
 388: 
 389:   public boolean contentsLost()
 390:   {
 391:     return false;
 392:   }
 393: 
 394:   public Graphics2D createGraphics()
 395:   {
 396:     QtImageGraphics g = new QtImageGraphics(this);
 397:     putPainter( g );
 398:     return g;
 399:   }
 400: 
 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: }