javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/qt/org/eclipse/swt/internal/qt/graphics/Image.java
changeset 78 71ad690e91f5
parent 21 2a9601315dfc
child 80 d6dafc5d983f
equal deleted inserted replaced
72:1f0034e370aa 78:71ad690e91f5
    10  *******************************************************************************/
    10  *******************************************************************************/
    11 package org.eclipse.swt.internal.qt.graphics;
    11 package org.eclipse.swt.internal.qt.graphics;
    12 
    12 
    13 
    13 
    14 import org.eclipse.swt.graphics.ImageData;
    14 import org.eclipse.swt.graphics.ImageData;
       
    15 import org.eclipse.swt.widgets.Display;
       
    16 import org.eclipse.swt.widgets.Internal_PackageSupport;
    15 
    17 
    16 public final class Image {
    18 public final class Image {
    17 
    19 
    18     /**
    20     /**
    19      * Specifies no transformation.
    21      * Specifies no transformation.
   126     // bound as rendering target by GraphicsContext
   128     // bound as rendering target by GraphicsContext
   127     private boolean isBound = false;
   129     private boolean isBound = false;
   128     // GraphicsContext bound to this image
   130     // GraphicsContext bound to this image
   129     private GraphicsContext boundingGc = null;
   131     private GraphicsContext boundingGc = null;
   130 
   132 
       
   133     // Image manages copies of itself for command buffering of drawImage and drawRegion. 
       
   134     private Image commandBufferCopy;
       
   135     private int commandBufferCopyRefs;
       
   136     private boolean commandBufferCopyDirty;
       
   137 
       
   138     // A copy-constructed Image remembers what it's a copy of
       
   139     private Image whatAmIACopyOf;
       
   140 
       
   141     private Image() {
       
   142     }
       
   143     
   131     /**
   144     /**
   132      * Constructs new image with given native image handle.
   145      * Constructs new image with given native image handle.
   133      *
   146      *
   134      * @param imgHandle The handle of valid native image
   147      * @param imgHandle The handle of valid native image
   135      * @throws OutOfMemoryError if imgHandlde is invalid
   148      * @throws OutOfMemoryError if imgHandlde is invalid
   136      */
   149      */
   137     Image(int imgHandle) {
   150     Image(int imgHandle) {
   138     	Utils.validateUiThread();
   151         Utils.validateUiThread();
   139         // validate handle
   152         // validate handle
   140         if(imgHandle == 0) {
   153         if(imgHandle == 0) {
   141             throw new OutOfMemoryError();
   154             throw new OutOfMemoryError();
   142         }
   155         }
   143         // store handle & get dimensions
   156         // store handle & get dimensions
   216     public Image(Image sourceImage, int x, int y, int width, int height) {
   229     public Image(Image sourceImage, int x, int y, int width, int height) {
   217         // validate sourceImage
   230         // validate sourceImage
   218         if (sourceImage == null) {
   231         if (sourceImage == null) {
   219             throw new NullPointerException("img is null");
   232             throw new NullPointerException("img is null");
   220         }
   233         }
   221         // Construct image in native side and store the handle
   234         createCopy(sourceImage, x, y, width, height);
   222         handle = OS.image_create(sourceImage.handle, x, y, width, height); // may throw outOfMemoryError
       
   223         // set dimensions
       
   224         updateSize();
       
   225     }
   235     }
   226 
   236 
   227     /**
   237     /**
   228      * Creates a new image from given ImageData
   238      * Creates a new image from given ImageData
   229      * @param imageData
   239      * @param imageData
   267      *
   277      *
   268      * If this instance is being disposed before gc has released it, the
   278      * If this instance is being disposed before gc has released it, the
   269      * releaseTarget() of binding gc is called automatically.
   279      * releaseTarget() of binding gc is called automatically.
   270      */
   280      */
   271     public void dispose() {
   281     public void dispose() {
   272     	Utils.validateUiThread();
   282         Utils.validateUiThread();
   273         if (handle != 0 || !disposed) {
   283         if (handle != 0 || !disposed) {
   274             // If this instance is being disposed while
   284             // If this instance is being disposed while
   275             // gc is still bound, release binding before disposing.
   285             // gc is still bound, release binding before disposing.
   276             if(isBound) {
   286             if(isBound) {
   277                 isBound = false;
   287                 isBound = false;
   283 
   293 
   284             // Delete window surface from cache in case
   294             // Delete window surface from cache in case
   285             // it is created for this instance
   295             // it is created for this instance
   286             SurfaceCache.getInstance().deleteSurface(this);
   296             SurfaceCache.getInstance().deleteSurface(this);
   287 
   297 
       
   298             whatAmIACopyOf = null;
       
   299 
   288             // dispose native peer
   300             // dispose native peer
   289             OS.image_dispose(handle);
   301             OS.image_dispose(handle);
   290             handle = 0;
   302             handle = 0;
   291             pixmapHandle = 0;
   303             pixmapHandle = 0;
   292             disposed = true;
   304             disposed = true;
   306      * Gets the format of the image.
   318      * Gets the format of the image.
   307      *
   319      *
   308      * @return image format
   320      * @return image format
   309      */
   321      */
   310     public int getFormat() {
   322     public int getFormat() {
   311     	checkState();
   323         checkState();
   312     	if (pixelFormat == FORMAT_IMG_NONE) {
   324         if (pixelFormat == FORMAT_IMG_NONE) {
   313     		pixelFormat = OS.image_getFormat(handle);
   325             pixelFormat = OS.image_getFormat(handle);
   314     	}
   326         }
   315         return pixelFormat;
   327         return pixelFormat;
   316     }
   328     }
   317     /**
   329     /**
   318      * Gets the height of the image in pixels.
   330      * Gets the height of the image in pixels.
   319      *
   331      *
   591      * Returns native side handle.
   603      * Returns native side handle.
   592      * @return the native handle.
   604      * @return the native handle.
   593      */
   605      */
   594     public int getHandle()
   606     public int getHandle()
   595     {
   607     {
   596     	checkState();
   608         checkState();
   597         return handle;
   609         return handle;
   598     }
   610     }
   599 
   611 
   600     /**
   612     /**
   601      * Returns native side QPixmap handle.
   613      * Returns native side QPixmap handle.
   602      * @return the native QPixmap handle.
   614      * @return the native QPixmap handle.
   603      */
   615      */
   604     synchronized public int getNativePixmapHandle()
   616     synchronized public int getNativePixmapHandle()
   605     {
   617     {
   606     	checkState();
   618         checkState();
   607         if(pixmapHandle == 0)
   619         if(pixmapHandle == 0)
   608         {
   620         {
   609             // In the current implementation this will return
   621             // In the current implementation this will return
   610             // pointer to the already existing QPixmap (which
   622             // pointer to the already existing QPixmap (which
   611             // will be destroyed with the object), so the
   623             // will be destroyed with the object), so the
   619     /**
   631     /**
   620      * Creates <code>ImageData</code> objects
   632      * Creates <code>ImageData</code> objects
   621      * @return New object
   633      * @return New object
   622      */
   634      */
   623     public ImageData getImageData() {
   635     public ImageData getImageData() {
   624     	checkState();
   636         checkState();
   625         return OS.image_getImageData(handle);
   637         return OS.image_getImageData(handle);
   626     }
   638     }
   627 
   639 
   628     /**
   640     /**
   629      * Private helper to check the state of the current instance.
   641      * Private helper to check the state of the current instance.
   630      */
   642      */
   631     private void checkState() {
   643     private void checkState() {
   632     	Utils.validateUiThread();
   644         Utils.validateUiThread();
   633         if(disposed) {
   645         if(disposed) {
   634             throw new IllegalStateException("Image already disposed");
   646             throw new IllegalStateException("Image already disposed");
   635         }
   647         }
   636     }
   648     }
   637 
   649 
   655             throw new IllegalArgumentException("imageData is null");
   667             throw new IllegalArgumentException("imageData is null");
   656         }
   668         }
   657         int imageHandle = OS.image_create(imageData);
   669         int imageHandle = OS.image_create(imageData);
   658         return new Image(imageHandle);
   670         return new Image(imageHandle);
   659     }
   671     }
       
   672     
       
   673     /**
       
   674      * Constructs new image with given native QPixmap handle.
       
   675      * @param pixmapHandle Handle of native QPixmap.
       
   676      * @return Instance of loaded image.
       
   677      */
       
   678     public static Image createImageFromPixmap(int pixmapHandle) {
       
   679         // input validation
       
   680         if(pixmapHandle <= 0) {
       
   681             throw new IllegalArgumentException("Invalid pixmap handle");
       
   682         }
       
   683         // Construct an ge in native side and store the handle
       
   684         int handle = OS.image_create(pixmapHandle);
       
   685         return new Image(handle);
       
   686     }
       
   687 
       
   688     /**
       
   689      * Obtains a shallow copy of this Image to be placed in the command buffer.
       
   690      * The returned copy must be marked as free by calling freeCommandBufferCopy
       
   691      * when it's no longer needed.
       
   692      * 
       
   693      * @return The copy
       
   694      */
       
   695     Image getCommandBufferCopy() {
       
   696         if(commandBufferCopyDirty) {
       
   697             return copyInUIThread();
       
   698         }
       
   699         if(commandBufferCopy == null) {
       
   700             commandBufferCopyDirty = false;
       
   701             commandBufferCopy = copyInUIThread();
       
   702             commandBufferCopyRefs = 0;
       
   703         }
       
   704         commandBufferCopyRefs++;
       
   705         return commandBufferCopy;
       
   706     }
       
   707 
       
   708     /**
       
   709      * Marks a copy returned from getCommandBufferCopy as free.
       
   710      * 
       
   711      * @param image
       
   712      *            The image returned from getShallowCopy.
       
   713      */
       
   714     void freeCommandBufferCopy() {
       
   715         if(disposed) {
       
   716             throw new RuntimeException("Image referenced by command buffer has been disposed");
       
   717         }
       
   718         if(whatAmIACopyOf == null) {
       
   719             throw new RuntimeException("Image not a copy");
       
   720         }
       
   721         whatAmIACopyOf.freeCommandBufferCopyOfMe(this);
       
   722     }
       
   723     
       
   724     /**
       
   725      * Tells to the Image that it has been modified and any copies returned from
       
   726      * getShallowCopy() have thus become deep copies.
       
   727      */
       
   728     void pixelDataModified() {
       
   729         if(commandBufferCopy != null) {
       
   730             commandBufferCopyDirty = true;
       
   731         }
       
   732     }
       
   733     
       
   734     /*
       
   735      * Copy-construction
       
   736      */
       
   737     private void createCopy(Image sourceImage, int x, int y, int width, int height) {
       
   738         // Construct image in native side and store the handle
       
   739         handle = OS.image_create(sourceImage.handle, x, y, width, height); // may throw outOfMemoryError
       
   740         // set dimensions
       
   741         updateSize();
       
   742         whatAmIACopyOf = sourceImage;
       
   743     }
       
   744 
       
   745     /*
       
   746      * Called on the Image when a copy it has returned from getCommandBufferCopy
       
   747      * is being freed by a call to freeCommandBufferCopy. The Image may be
       
   748      * disposed at this point while the copy is not.
       
   749      */
       
   750     private void freeCommandBufferCopyOfMe(Image copy) {
       
   751         if(copy != commandBufferCopy) {
       
   752             throw new RuntimeException("Copy doesn't exist, freed multiple times?");
       
   753         } else {
       
   754             commandBufferCopyRefs--;
       
   755             if(commandBufferCopyRefs <= 0) {
       
   756                 commandBufferCopy.dispose();
       
   757                 commandBufferCopy = null;
       
   758             }
       
   759         }
       
   760     }
       
   761     
       
   762     /*
       
   763      * Creates a shallow copy of the Image in the UI thread. 
       
   764      */
       
   765     private Image copyInUIThread() {
       
   766         Display d = Internal_PackageSupport.getDisplayInstance();
       
   767         final Image copy = new Image();
       
   768         if(d != null) {
       
   769             d.syncExec(new Runnable() {
       
   770                 public void run() {
       
   771                     copy.createCopy(Image.this, 0, 0, 0, 0);
       
   772                 }
       
   773             });
       
   774         }
       
   775         if(copy.handle == 0) {
       
   776             return null;
       
   777         }
       
   778         return copy;
       
   779     }
   660 }
   780 }