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

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