src/share/classes/sun/awt/image/OffScreenImage.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -29,17 +29,21 @@
 import java.awt.Color;
 import java.awt.SystemColor;
 import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsEnvironment;
+import java.awt.Rectangle;
 import java.awt.image.BufferedImage;
 import java.awt.image.ImageProducer;
 import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.ImageObserver;
 import java.awt.image.WritableRaster;
 import sun.java2d.SunGraphics2D;
-import sun.java2d.SurfaceData;
+import sun.java2d.loops.SurfaceType;
 
 /**
  * This is a special variant of BufferedImage that keeps a reference to
  * a Component.  The Component's foreground and background colors and
  * default font are used as the defaults for this image.

@@ -48,10 +52,24 @@
 
     protected Component c;
     private OffScreenImageSource osis;
     private Font defaultFont;
 
+    // The layout size of the image.
+    private int width;
+    private int height;
+    
+    // The scale factor which determines the physical size of the raster.
+    private int scale = 1;
+    
+    // Affects the value returned by the size methods.
+    // When {@code true}, the returned size value matches
+    // the layout size of the image, otherwise the returned
+    // size value matches the physical size of the raster,
+    // which is determined by the scale factor.
+    private boolean returnLayoutSize;
+    
     /**
      * Constructs an OffScreenImage given a color model and tile,
      * for offscreen rendering to be used with a given component.
      * The component is used to obtain the foreground color, background
      * color and font.

@@ -62,10 +80,118 @@
         super(cm, raster, isRasterPremultiplied, null);
         this.c = c;
         initSurface(raster.getWidth(), raster.getHeight());
     }
 
+    private OffScreenImage(Component c, ColorModel cm, WritableRaster raster,
+                           boolean isRasterPremultiplied,
+                           int width, int height,
+                           int scale)
+    {
+        this(c, cm, raster, isRasterPremultiplied);
+        this.width = width;
+        this.height = height;
+        this.scale = scale;
+    }
+    
+    /**
+     * Constructs an OffScreenImage with the {@code scale} factor.
+     * The scale determines the physical size of the raster, compared
+     * to the layout {@code width/height} size of the image.
+     */
+    public OffScreenImage(Component c, int width, int height,
+                          int imageType,
+                          int scale)
+    {
+         super(width * scale, height * scale, imageType);
+         this.c = c;
+         this.width = width;
+         this.height = height;
+         this.scale = scale;
+    }  
+    
+    /**
+     * Constructs an OffScreenImage with the {@code scale} factor.
+     * The scale determines the physical size of the raster, compared
+     * to the layout {@code width/height} size of the image.
+     */
+    public static OffScreenImage create(Component c, GraphicsConfiguration gc,
+                                        int width, int height,
+                                        int transparency,
+                                        int scale)
+    {
+        ColorModel cm = gc.getColorModel(transparency);
+        WritableRaster wr = cm.createCompatibleWritableRaster(width * scale, height * scale);
+        return new OffScreenImage(c, cm, wr, cm.isAlphaPremultiplied(),
+                                  width, height, scale);        
+    }
+    
+    /**
+     * Sets whether the {@code getWidth/Height} methods should
+     * return the layout or physical size of the image.
+     * @param value 
+     */
+    public void setReturnLayoutSize(boolean value) {
+        returnLayoutSize = value;
+    }
+    
+    /**
+     * Gets whether the {@code getWidth/Height} methods should
+     * return the layout or physical size of the image.
+     * @param value 
+     */
+    public boolean isReturnLayoutSize() {
+        return returnLayoutSize;
+    }
+    
+    @Override
+    public int getWidth() {
+        return returnLayoutSize ? width : super.getWidth();
+    }
+    
+    @Override
+    public int getWidth(ImageObserver o) {
+        return getWidth();
+    }
+    
+    @Override
+    public int getHeight() {
+        return returnLayoutSize ? height : super.getHeight();
+    }
+    
+    @Override
+    public int getHeight(ImageObserver o) {
+        return getHeight();
+    }
+    
+    /**
+     * Gets the layout width of the image.
+     * 
+     * @return the layout width of the image
+     */
+    public int getLayoutWidth() {
+        return width;
+    }
+    
+    /**
+     * Gets the layout height of the image.
+     * 
+     * @return the layout height of the image
+     */
+    public int getLayoutHeight() {
+        return height;
+    }
+    
+    /**
+     * Gets the scale factor used to scale the image on HiDPI devices
+     * 
+     * @return the HiDPI scale factor
+     */
+    public int getHiDPIScale() {
+        return scale;
+    }
+    
     public Graphics getGraphics() {
         return createGraphics();
     }
 
     public Graphics2D createGraphics() {

@@ -110,6 +236,64 @@
         if (osis == null) {
             osis = new OffScreenImageSource(this);
         }
         return osis;
     }
+    
+    /**
+     * Creates a scaled OffScreenImage.
+     */
+    public class GraphicsConfig extends BufferedImageGraphicsConfig {
+        public GraphicsConfig() {
+            super(OffScreenImage.this, null);
+        }
+        
+        public BufferedImage createCompatibleHiDPIImage(int width, int height, int transparency) {
+            return OffScreenImage.create(null, this,
+                                         width, height,
+                                         transparency,
+                                         OffScreenImage.this.getHiDPIScale());
+        }
+    }
+    
+    /**
+     * Returns correct physical bounds and the scale factor.
+     */
+    public class SurfaceData extends BufImgSurfaceData {
+        public SurfaceData(DataBuffer db, SurfaceType sType) {
+            super(db, OffScreenImage.this, sType);
+        }
+        
+        @Override
+        public Rectangle getBounds() {
+            return new Rectangle(OffScreenImage.this.getRaster().getWidth(),
+                                 OffScreenImage.this.getRaster().getHeight());
+        }
+        
+        @Override
+        public int getDefaultScale() {
+            return OffScreenImage.this.getHiDPIScale();
+        }
+    }
+    
+    /**
+     * Backed by a scaled OffScreenImage.
+     */
+    public static class VolatileImage extends SunVolatileImage {
+        public VolatileImage(OffScreenImage.GraphicsConfig graphicsConfig,
+                             int width, int height,
+                             int transparency)
+        {
+            super(graphicsConfig, width, height, transparency, null);
+        }
+        
+        @Override
+        public BufferedImage getBackupImage() {
+            OffScreenImage img = (OffScreenImage)
+                ((OffScreenImage.GraphicsConfig)getGraphicsConfig()).
+                createCompatibleHiDPIImage(getWidth(), getHeight(), transparency);
+            img.setReturnLayoutSize(true);
+            return img;
+        }
+    }
+    
 }