javafx-embed-swing/src/javafx/embed/swing/SwingFXUtils.java

Print this page




   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.embed.swing;
  27 
  28 import java.awt.AlphaComposite;

  29 import java.awt.Graphics2D;

  30 import java.awt.image.BufferedImage;


  31 import java.nio.IntBuffer;




  32 import javafx.scene.image.Image;
  33 import javafx.scene.image.PixelFormat;
  34 import javafx.scene.image.PixelReader;
  35 import javafx.scene.image.PixelWriter;
  36 import javafx.scene.image.WritableImage;
  37 import javafx.scene.image.WritablePixelFormat;




  38 import sun.awt.image.IntegerComponentRaster;
  39 
  40 /**
  41  * This class provides utility methods for converting data types between
  42  * Swing/AWT and JavaFX formats.
  43  */
  44 public class SwingFXUtils {
  45     private SwingFXUtils() {} // no instances
  46 
  47     /**
  48      * Snapshots the specified {@link BufferedImage} and stores a copy of
  49      * its pixels into a JavaFX {@link Image} object, creating a new
  50      * object if needed.
  51      * The returned {@code Image} will be a static snapshot of the state
  52      * of the pixels in the {@code BufferedImage} at the time the method
  53      * completes.  Further changes to the {@code BufferedImage} will not
  54      * be reflected in the {@code Image}.
  55      * <p>
  56      * The optional JavaFX {@link WritableImage} parameter may be reused
  57      * to store the copy of the pixels.


 163             } else if (iw < bw || ih < bh) {
 164                 Graphics2D g2d = bimg.createGraphics();
 165                 g2d.setComposite(AlphaComposite.Clear);
 166                 g2d.fillRect(0, 0, bw, bh);
 167                 g2d.dispose();
 168             }
 169         }
 170         if (bimg == null) {
 171             bimg = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_ARGB_PRE);
 172         }
 173         IntegerComponentRaster icr = (IntegerComponentRaster) bimg.getRaster();
 174         int offset = icr.getDataOffset(0);
 175         int scan = icr.getScanlineStride();
 176         int data[] = icr.getDataStorage();
 177         WritablePixelFormat<IntBuffer> pf = (bimg.isAlphaPremultiplied() ?
 178                                              PixelFormat.getIntArgbPreInstance() :
 179                                              PixelFormat.getIntArgbInstance());
 180         pr.getPixels(0, 0, iw, ih, pf, data, offset, scan);
 181         return bimg;
 182     }




































































 183 }


   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.embed.swing;
  27 
  28 import java.awt.AlphaComposite;
  29 import java.awt.EventQueue;
  30 import java.awt.Graphics2D;
  31 import java.awt.SecondaryLoop;
  32 import java.awt.image.BufferedImage;
  33 import java.lang.reflect.InvocationTargetException;
  34 import java.lang.reflect.Method;
  35 import java.nio.IntBuffer;
  36 import java.security.AccessController;
  37 import java.security.PrivilegedAction;
  38 import java.util.concurrent.atomic.AtomicBoolean;
  39 import javafx.application.Platform;
  40 import javafx.scene.image.Image;
  41 import javafx.scene.image.PixelFormat;
  42 import javafx.scene.image.PixelReader;
  43 import javafx.scene.image.PixelWriter;
  44 import javafx.scene.image.WritableImage;
  45 import javafx.scene.image.WritablePixelFormat;
  46 import com.sun.javafx.application.PlatformImpl;
  47 import com.sun.javafx.tk.Toolkit;
  48 import sun.awt.AWTAccessor;
  49 import sun.awt.FwDispatcher;
  50 import sun.awt.image.IntegerComponentRaster;
  51 
  52 /**
  53  * This class provides utility methods for converting data types between
  54  * Swing/AWT and JavaFX formats.
  55  */
  56 public class SwingFXUtils {
  57     private SwingFXUtils() {} // no instances
  58 
  59     /**
  60      * Snapshots the specified {@link BufferedImage} and stores a copy of
  61      * its pixels into a JavaFX {@link Image} object, creating a new
  62      * object if needed.
  63      * The returned {@code Image} will be a static snapshot of the state
  64      * of the pixels in the {@code BufferedImage} at the time the method
  65      * completes.  Further changes to the {@code BufferedImage} will not
  66      * be reflected in the {@code Image}.
  67      * <p>
  68      * The optional JavaFX {@link WritableImage} parameter may be reused
  69      * to store the copy of the pixels.


 175             } else if (iw < bw || ih < bh) {
 176                 Graphics2D g2d = bimg.createGraphics();
 177                 g2d.setComposite(AlphaComposite.Clear);
 178                 g2d.fillRect(0, 0, bw, bh);
 179                 g2d.dispose();
 180             }
 181         }
 182         if (bimg == null) {
 183             bimg = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_ARGB_PRE);
 184         }
 185         IntegerComponentRaster icr = (IntegerComponentRaster) bimg.getRaster();
 186         int offset = icr.getDataOffset(0);
 187         int scan = icr.getScanlineStride();
 188         int data[] = icr.getDataStorage();
 189         WritablePixelFormat<IntBuffer> pf = (bimg.isAlphaPremultiplied() ?
 190                                              PixelFormat.getIntArgbPreInstance() :
 191                                              PixelFormat.getIntArgbInstance());
 192         pr.getPixels(0, 0, iw, ih, pf, data, offset, scan);
 193         return bimg;
 194     }
 195 
 196     /**
 197      * If called from the FX Application Thread
 198      * invokes a runnable directly blocking the calling code
 199      * Otherwise
 200      * uses Platform.runLater without blocking
 201      */
 202     static void runOnFxThread(Runnable runnable) {
 203         if (Platform.isFxApplicationThread()) {
 204             runnable.run();
 205         } else {
 206             Platform.runLater(runnable);
 207         }
 208     }
 209 
 210     private static class FwSecondaryLoop implements SecondaryLoop {
 211 
 212         private final AtomicBoolean isRunning = new AtomicBoolean(false);
 213 
 214         @Override public boolean enter() {
 215             if (isRunning.compareAndSet(false, true)) {
 216                 PlatformImpl.runAndWait(new Runnable() {
 217                     @Override public void run() {
 218                         Toolkit.getToolkit().enterNestedEventLoop(FwSecondaryLoop.this);
 219                     }
 220                 });
 221                 return true;
 222             }
 223             return false;
 224         }
 225 
 226         @Override public boolean exit() {
 227             if (isRunning.compareAndSet(true, false)) {
 228                 PlatformImpl.runAndWait(new Runnable() {
 229                     @Override public void run() {
 230                         Toolkit.getToolkit().exitNestedEventLoop(FwSecondaryLoop.this, null);
 231                     }
 232                 });
 233                 return true;
 234             }
 235             return false;
 236         }
 237     }
 238 
 239     private static class FXDispatcher implements FwDispatcher {
 240         @Override public boolean isDispatchThread() {
 241             return Platform.isFxApplicationThread();
 242         }
 243 
 244         @Override public void scheduleDispatch(Runnable runnable) {
 245             runOnFxThread(runnable);
 246         }
 247 
 248         @Override public SecondaryLoop createSecondaryLoop() {
 249             return new FwSecondaryLoop();
 250         }
 251     }
 252 
 253     //Called with reflection from PlatformImpl to avoid dependency
 254     public static void installFwEventQueue() {
 255         EventQueue eq = AccessController.doPrivileged(
 256                 new PrivilegedAction<EventQueue>() {
 257                     @Override public EventQueue run() {
 258                         return java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
 259                     }
 260                 });
 261         AWTAccessor.getEventQueueAccessor().setFwDispatcher(eq, new FXDispatcher());
 262     }
 263 }