--- old/src/share/classes/sun/awt/image/OffScreenImage.java 2014-05-13 21:17:47.000000000 +0400 +++ new/src/share/classes/sun/awt/image/OffScreenImage.java 2014-05-13 21:17:47.000000000 +0400 @@ -1,5 +1,5 @@ /* - * 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 @@ -31,13 +31,17 @@ 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 @@ -49,7 +53,21 @@ 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. @@ -63,7 +81,115 @@ 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(); } @@ -112,4 +238,62 @@ } 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; + } + } + }