3333import static javafx .scene .web .WebEvent .STATUS_CHANGED ;
3434import static javafx .scene .web .WebEvent .VISIBILITY_CHANGED ;
3535
36- import com .sun .javafx .tk .Toolkit ;
3736import com .sun .webkit .UIClient ;
3837import com .sun .webkit .WebPage ;
3938import com .sun .webkit .graphics .WCImage ;
4039import com .sun .webkit .graphics .WCRectangle ;
41- import java .awt .AlphaComposite ;
42- import java .awt .Graphics2D ;
43- import java .awt .image .BufferedImage ;
44- import java .awt .image .DataBufferInt ;
45- import java .awt .image .SampleModel ;
46- import java .awt .image .SinglePixelPackedSampleModel ;
4740import java .io .File ;
4841import java .io .IOException ;
4942import java .io .UnsupportedEncodingException ;
5043import java .nio .ByteBuffer ;
51- import java .nio .IntBuffer ;
5244import java .security .AccessControlContext ;
5345import java .security .AccessController ;
5446import java .security .PrivilegedAction ;
5850import java .util .Map ;
5951import javafx .event .EventHandler ;
6052import javafx .geometry .Rectangle2D ;
61- import javafx .scene .image .Image ;
62- import javafx .scene .image .PixelFormat ;
63- import javafx .scene .image .PixelReader ;
64- import javafx .scene .image .WritablePixelFormat ;
6553import javafx .scene .input .ClipboardContent ;
6654import javafx .scene .input .DataFormat ;
6755import javafx .scene .input .Dragboard ;
@@ -342,7 +330,7 @@ private static DataFormat getDataFormat(String mimeType) {
342330 //never happens
343331 }
344332 }
345- if (image != null ) {
333+ if (image != null && ! image . isNull () ) {
346334 ByteBuffer dragImageOffset = ByteBuffer .allocate (8 );
347335 dragImageOffset .rewind ();
348336 dragImageOffset .putInt (imageOffsetX );
@@ -364,26 +352,18 @@ private static DataFormat getDataFormat(String mimeType) {
364352 //QuantumClipboard.putContent have to be rewritten in Glass manner
365353 //with postponed data requests (DelayedCallback data object).
366354 if (isImageSource ) {
367- Object platformImage = image .getWidth () > 0 && image .getHeight () > 0 ?
368- image .getPlatformImage () : null ;
369355 String fileExtension = image .getFileExtension ();
370- if (platformImage != null ) {
371- try {
372- File temp = File .createTempFile ("jfx" , "." + fileExtension );
373- temp .deleteOnExit ();
374- ImageIO .write (
375- toBufferedImage (Toolkit .getImageAccessor ().fromPlatformImage (
376- Toolkit .getToolkit ().loadPlatformImage (
377- platformImage
378- )
379- )),
380- fileExtension ,
381- temp );
382- content .put (DataFormat .FILES , Arrays .asList (temp ));
383- } catch (IOException | SecurityException e ) {
384- //That is ok. It was just an attempt.
385- //e.printStackTrace();
386- }
356+ try {
357+ File temp = File .createTempFile ("jfx" , "." + fileExtension );
358+ temp .deleteOnExit ();
359+ ImageIO .write (
360+ image .toBufferedImage (),
361+ fileExtension ,
362+ temp );
363+ content .put (DataFormat .FILES , Arrays .asList (temp ));
364+ } catch (IOException | SecurityException e ) {
365+ //That is ok. It was just an attempt.
366+ //e.printStackTrace();
387367 }
388368 }
389369 }
@@ -403,143 +383,4 @@ private static DataFormat getDataFormat(String mimeType) {
403383 return accessor .getView () != null && content != null ;
404384 }
405385
406- private static int
407- getBestBufferedImageType (PixelFormat <?> fxFormat , BufferedImage bimg ,
408- boolean isOpaque )
409- {
410- if (bimg != null ) {
411- int bimgType = bimg .getType ();
412- if (bimgType == BufferedImage .TYPE_INT_ARGB ||
413- bimgType == BufferedImage .TYPE_INT_ARGB_PRE ||
414- (isOpaque &&
415- (bimgType == BufferedImage .TYPE_INT_BGR ||
416- bimgType == BufferedImage .TYPE_INT_RGB )))
417- {
418- // We will allow the caller to give us a BufferedImage
419- // that has an alpha channel, but we might not otherwise
420- // construct one ourselves.
421- // We will also allow them to choose their own premultiply
422- // type which may not match the image.
423- // If left to our own devices we might choose a more specific
424- // format as indicated by the choices below.
425- return bimgType ;
426- }
427- }
428- switch (fxFormat .getType ()) {
429- default :
430- case BYTE_BGRA_PRE :
431- case INT_ARGB_PRE :
432- return BufferedImage .TYPE_INT_ARGB_PRE ;
433- case BYTE_BGRA :
434- case INT_ARGB :
435- return BufferedImage .TYPE_INT_ARGB ;
436- case BYTE_RGB :
437- return BufferedImage .TYPE_INT_RGB ;
438- case BYTE_INDEXED :
439- return (fxFormat .isPremultiplied ()
440- ? BufferedImage .TYPE_INT_ARGB_PRE
441- : BufferedImage .TYPE_INT_ARGB );
442- }
443- }
444-
445- private static WritablePixelFormat <IntBuffer >
446- getAssociatedPixelFormat (BufferedImage bimg )
447- {
448- switch (bimg .getType ()) {
449- // We lie here for xRGB, but we vetted that the src data was opaque
450- // so we can ignore the alpha. We use ArgbPre instead of Argb
451- // just to get a loop that does not have divides in it if the
452- // PixelReader happens to not know the data is opaque.
453- case BufferedImage .TYPE_INT_RGB :
454- case BufferedImage .TYPE_INT_ARGB_PRE :
455- return PixelFormat .getIntArgbPreInstance ();
456- case BufferedImage .TYPE_INT_ARGB :
457- return PixelFormat .getIntArgbInstance ();
458- default :
459- // Should not happen...
460- throw new InternalError ("Failed to validate BufferedImage type" );
461- }
462- }
463-
464- private static boolean checkFXImageOpaque (PixelReader pr , int iw , int ih ) {
465- for (int x = 0 ; x < iw ; x ++) {
466- for (int y = 0 ; y < ih ; y ++) {
467- Color color = pr .getColor (x ,y );
468- if (color .getOpacity () != 1.0 ) {
469- return false ;
470- }
471- }
472- }
473- return true ;
474- }
475-
476- private static BufferedImage fromFXImage (Image img , BufferedImage bimg ) {
477- PixelReader pr = img .getPixelReader ();
478- if (pr == null ) {
479- return null ;
480- }
481- int iw = (int ) img .getWidth ();
482- int ih = (int ) img .getHeight ();
483- PixelFormat <?> fxFormat = pr .getPixelFormat ();
484- boolean srcPixelsAreOpaque = false ;
485- switch (fxFormat .getType ()) {
486- case INT_ARGB_PRE :
487- case INT_ARGB :
488- case BYTE_BGRA_PRE :
489- case BYTE_BGRA :
490- // Check fx image opacity only if
491- // supplied BufferedImage is without alpha channel
492- if (bimg != null &&
493- (bimg .getType () == BufferedImage .TYPE_INT_BGR ||
494- bimg .getType () == BufferedImage .TYPE_INT_RGB )) {
495- srcPixelsAreOpaque = checkFXImageOpaque (pr , iw , ih );
496- }
497- break ;
498- case BYTE_RGB :
499- srcPixelsAreOpaque = true ;
500- break ;
501- }
502- int prefBimgType = getBestBufferedImageType (pr .getPixelFormat (), bimg , srcPixelsAreOpaque );
503- if (bimg != null ) {
504- int bw = bimg .getWidth ();
505- int bh = bimg .getHeight ();
506- if (bw < iw || bh < ih || bimg .getType () != prefBimgType ) {
507- bimg = null ;
508- } else if (iw < bw || ih < bh ) {
509- Graphics2D g2d = bimg .createGraphics ();
510- g2d .setComposite (AlphaComposite .Clear );
511- g2d .fillRect (0 , 0 , bw , bh );
512- g2d .dispose ();
513- }
514- }
515- if (bimg == null ) {
516- bimg = new BufferedImage (iw , ih , prefBimgType );
517- }
518- DataBufferInt db = (DataBufferInt )bimg .getRaster ().getDataBuffer ();
519- int data [] = db .getData ();
520- int offset = bimg .getRaster ().getDataBuffer ().getOffset ();
521- int scan = 0 ;
522- SampleModel sm = bimg .getRaster ().getSampleModel ();
523- if (sm instanceof SinglePixelPackedSampleModel ) {
524- scan = ((SinglePixelPackedSampleModel )sm ).getScanlineStride ();
525- }
526-
527- WritablePixelFormat <IntBuffer > pf = getAssociatedPixelFormat (bimg );
528- pr .getPixels (0 , 0 , iw , ih , pf , data , offset , scan );
529- return bimg ;
530- }
531-
532- // Method to implement the following via reflection:
533- // SwingFXUtils.fromFXImage(img, null)
534- public static BufferedImage toBufferedImage (Image img ) {
535- try {
536- return fromFXImage (img , null );
537- } catch (Exception ex ) {
538- ex .printStackTrace (System .err );
539- }
540-
541- // return null upon any exception
542- return null ;
543- }
544-
545386}
0 commit comments