1 /*
   2  * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   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 sun.awt.image;
  27 
  28 import java.awt.AWTException;
  29 import java.awt.Component;
  30 import java.awt.Graphics2D;
  31 import java.awt.GraphicsConfiguration;
  32 import java.awt.GraphicsDevice;
  33 import java.awt.ImageCapabilities;
  34 import java.awt.Rectangle;
  35 import java.awt.Transparency;
  36 import java.awt.geom.AffineTransform;
  37 import java.awt.image.BufferedImage;
  38 import java.awt.image.ColorModel;
  39 import java.awt.image.DirectColorModel;
  40 import java.awt.image.Raster;
  41 import java.awt.image.VolatileImage;
  42 import java.awt.image.WritableRaster;
  43 
  44 public class BufferedImageGraphicsConfig
  45     extends GraphicsConfiguration
  46 {
  47     private static final int numconfigs = BufferedImage.TYPE_BYTE_BINARY;
  48     private static BufferedImageGraphicsConfig standardConfigs[] =
  49         new BufferedImageGraphicsConfig[numconfigs];
  50     private static BufferedImageGraphicsConfig scaledConfigs[] =
  51         new BufferedImageGraphicsConfig[numconfigs];
  52 
  53     public static BufferedImageGraphicsConfig getConfig(BufferedImage bImg) {
  54         return getConfig(bImg, 1, 1);
  55     }
  56 
  57     public static BufferedImageGraphicsConfig getConfig(BufferedImage bImg,
  58                                                         double scaleX,
  59                                                         double scaleY)
  60     {
  61         BufferedImageGraphicsConfig ret;
  62         int type = bImg.getType();
  63 
  64         BufferedImageGraphicsConfig[] configs = (scaleX == 1 && scaleY == 1)
  65                 ? standardConfigs : scaledConfigs;
  66 
  67         if (type > 0 && type < numconfigs) {
  68             ret = configs[type];
  69             if (ret != null && ret.scaleX == scaleX && ret.scaleY == scaleY) {
  70                 return ret;
  71             }
  72         }
  73         ret = new BufferedImageGraphicsConfig(bImg, null);
  74         if (type > 0 && type < numconfigs) {
  75             configs[type] = ret;
  76         }
  77         return ret;
  78     }
  79 
  80     GraphicsDevice gd;
  81     ColorModel model;
  82     Raster raster;
  83     private final double scaleX;
  84     private final double scaleY;
  85 
  86     public BufferedImageGraphicsConfig(BufferedImage bufImg, Component comp) {
  87         this(bufImg, comp, 1, 1);
  88     }
  89 
  90     public BufferedImageGraphicsConfig(BufferedImage bufImg, Component comp,
  91                                        double scaleX, double scaleY)
  92     {
  93         if (comp == null) {
  94             this.gd = new BufferedImageDevice(this);
  95         } else {
  96             Graphics2D g2d = (Graphics2D)comp.getGraphics();
  97             this.gd = g2d.getDeviceConfiguration().getDevice();
  98         }
  99         this.model = bufImg.getColorModel();
 100         this.raster = bufImg.getRaster().createCompatibleWritableRaster(1, 1);
 101         this.scaleX = scaleX;
 102         this.scaleY = scaleY;
 103     }
 104 
 105     /**
 106      * Return the graphics device associated with this configuration.
 107      */
 108     public GraphicsDevice getDevice() {
 109         return gd;
 110     }
 111 
 112     /**
 113      * Returns a BufferedImage with channel layout and color model
 114      * compatible with this graphics configuration.  This method
 115      * has nothing to do with memory-mapping
 116      * a device.  This BufferedImage has
 117      * a layout and color model
 118      * that is closest to this native device configuration and thus
 119      * can be optimally blitted to this device.
 120      */
 121     public BufferedImage createCompatibleImage(int width, int height) {
 122         WritableRaster wr = raster.createCompatibleWritableRaster(width, height);
 123         return new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
 124     }
 125 
 126     /**
 127      * Returns the color model associated with this configuration.
 128      */
 129     public ColorModel getColorModel() {
 130         return model;
 131     }
 132 
 133     /**
 134      * Returns the color model associated with this configuration that
 135      * supports the specified transparency.
 136      */
 137     public ColorModel getColorModel(int transparency) {
 138 
 139         if (model.getTransparency() == transparency) {
 140             return model;
 141         }
 142         switch (transparency) {
 143         case Transparency.OPAQUE:
 144             return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
 145         case Transparency.BITMASK:
 146             return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
 147         case Transparency.TRANSLUCENT:
 148             return ColorModel.getRGBdefault();
 149         default:
 150             return null;
 151         }
 152     }
 153 
 154     /**
 155      * Returns the default Transform for this configuration.  This
 156      * Transform is typically the Identity transform for most normal
 157      * screens.  Device coordinates for screen and printer devices will
 158      * have the origin in the upper left-hand corner of the target region of
 159      * the device, with X coordinates
 160      * increasing to the right and Y coordinates increasing downwards.
 161      * For image buffers, this Transform will be the Identity transform.
 162      */
 163     public AffineTransform getDefaultTransform() {
 164         return AffineTransform.getScaleInstance(scaleX, scaleY);
 165     }
 166 
 167     /**
 168      *
 169      * Returns a Transform that can be composed with the default Transform
 170      * of a Graphics2D so that 72 units in user space will equal 1 inch
 171      * in device space.
 172      * Given a Graphics2D, g, one can reset the transformation to create
 173      * such a mapping by using the following pseudocode:
 174      * <pre>
 175      *      GraphicsConfiguration gc = g.getGraphicsConfiguration();
 176      *
 177      *      g.setTransform(gc.getDefaultTransform());
 178      *      g.transform(gc.getNormalizingTransform());
 179      * </pre>
 180      * Note that sometimes this Transform will be identity (e.g. for
 181      * printers or metafile output) and that this Transform is only
 182      * as accurate as the information supplied by the underlying system.
 183      * For image buffers, this Transform will be the Identity transform,
 184      * since there is no valid distance measurement.
 185      */
 186     public AffineTransform getNormalizingTransform() {
 187         return new AffineTransform();
 188     }
 189 
 190     public Rectangle getBounds() {
 191         return new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
 192     }
 193 }