1 /*
   2  * Copyright (c) 2000, 2008, 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.AlphaComposite;
  29 import java.awt.Color;
  30 import java.awt.Component;
  31 import java.awt.Font;
  32 import java.awt.Graphics2D;
  33 import java.awt.GraphicsConfiguration;
  34 import java.awt.ImageCapabilities;
  35 import java.awt.Transparency;
  36 import java.awt.image.BufferedImage;
  37 import java.awt.image.ImageObserver;
  38 import java.awt.image.VolatileImage;
  39 import sun.java2d.SunGraphics2D;
  40 import sun.java2d.SurfaceManagerFactory;
  41 import sun.java2d.DestSurfaceProvider;
  42 import sun.java2d.Surface;
  43 import static sun.java2d.pipe.hw.AccelSurface.*;
  44 
  45 /**
  46  * This class is the base implementation of the VolatileImage
  47  * abstract class.  The class implements most of the standard Image
  48  * methods (width, height, etc.) but delegates all surface management
  49  * issues to a platform-specific VolatileSurfaceManager.  When a new instance
  50  * of SunVolatileImage is created, it automatically creates an
  51  * appropriate VolatileSurfaceManager for the GraphicsConfiguration
  52  * under which this SunVolatileImage was created.
  53  */
  54 public class SunVolatileImage extends VolatileImage
  55     implements DestSurfaceProvider
  56 {
  57 
  58     protected VolatileSurfaceManager volSurfaceManager;
  59     protected Component comp;
  60     private GraphicsConfiguration graphicsConfig;
  61     private Font defaultFont;
  62     private int width, height;
  63     private int forcedAccelSurfaceType;
  64 
  65     protected SunVolatileImage(Component comp,
  66                                GraphicsConfiguration graphicsConfig,
  67                                int width, int height, Object context,
  68                                int transparency, ImageCapabilities caps,
  69                                int accType)
  70     {
  71         this.comp = comp;
  72         this.graphicsConfig = graphicsConfig;
  73         if (width <= 0 || height <= 0) {
  74             throw new IllegalArgumentException("Width (" + width + ")" +
  75                               " and height (" + height + ") cannot be <= 0");
  76         }
  77         this.width = width;
  78         this.height = height;
  79         this.forcedAccelSurfaceType = accType;
  80         if (!(transparency == Transparency.OPAQUE ||
  81             transparency == Transparency.BITMASK ||
  82             transparency == Transparency.TRANSLUCENT))
  83         {
  84             throw new IllegalArgumentException("Unknown transparency type:" +
  85                                                transparency);
  86         }
  87         this.transparency = transparency;
  88         this.volSurfaceManager = createSurfaceManager(context, caps);
  89         SurfaceManager.setManager(this, volSurfaceManager);
  90 
  91         // post-construction initialization of the surface manager
  92         volSurfaceManager.initialize();
  93         // clear the background
  94         volSurfaceManager.initContents();
  95     }
  96 
  97     private SunVolatileImage(Component comp,
  98                              GraphicsConfiguration graphicsConfig,
  99                              int width, int height, Object context,
 100                              ImageCapabilities caps)
 101     {
 102         this(comp, graphicsConfig,
 103              width, height, context, Transparency.OPAQUE, caps, UNDEFINED);
 104     }
 105 
 106     public SunVolatileImage(Component comp, int width, int height) {
 107         this(comp, width, height, null);
 108     }
 109 
 110     public SunVolatileImage(Component comp,
 111                             int width, int height, Object context)
 112     {
 113         this(comp, comp.getGraphicsConfiguration(),
 114              width, height, context, null);
 115     }
 116 
 117     public SunVolatileImage(GraphicsConfiguration graphicsConfig,
 118                             int width, int height, int transparency,
 119                             ImageCapabilities caps)
 120     {
 121         this(null, graphicsConfig, width, height, null, transparency,
 122              caps, UNDEFINED);
 123     }
 124 
 125     public int getWidth() {
 126         return width;
 127     }
 128 
 129     public int getHeight() {
 130         return height;
 131     }
 132 
 133     public GraphicsConfiguration getGraphicsConfig() {
 134         return graphicsConfig;
 135     }
 136 
 137     public void updateGraphicsConfig() {
 138         // If this VImage is associated with a Component, get an updated
 139         // graphicsConfig from that component.  Otherwise, keep the one
 140         // that we were created with
 141         if (comp != null) {
 142             GraphicsConfiguration gc = comp.getGraphicsConfiguration();
 143             if (gc != null) {
 144                 // Could potentially be null in some failure situations;
 145                 // better to keep the old non-null value around than to
 146                 // set graphicsConfig to null
 147                 graphicsConfig = gc;
 148             }
 149         }
 150     }
 151 
 152     public Component getComponent() {
 153         return comp;
 154     }
 155 
 156     public int getForcedAccelSurfaceType() {
 157         return forcedAccelSurfaceType;
 158     }
 159 
 160     protected VolatileSurfaceManager createSurfaceManager(Object context,
 161                                                           ImageCapabilities caps)
 162     {
 163         /**
 164          * Platform-specific SurfaceManagerFactories will return a
 165          * manager suited to acceleration on each platform.  But if
 166          * the user is asking for a VolatileImage from a BufferedImageGC,
 167          * then we need to return the appropriate unaccelerated manager.
 168          * Note: this could change in the future; if some platform would
 169          * like to accelerate BIGC volatile images, then this special-casing
 170          * of the BIGC graphicsConfig should live in platform-specific
 171          * code instead.
 172          * We do the same for a Printer Device, and if user requested an
 173          * unaccelerated VolatileImage by passing the capabilities object.
 174          */
 175         if (graphicsConfig instanceof BufferedImageGraphicsConfig ||
 176             graphicsConfig instanceof sun.print.PrinterGraphicsConfig ||
 177             (caps != null && !caps.isAccelerated()))
 178         {
 179             return new BufImgVolatileSurfaceManager(this, context);
 180         }
 181         SurfaceManagerFactory smf = SurfaceManagerFactory.getInstance();
 182         return smf.createVolatileManager(this, context);
 183     }
 184 
 185     private Color getForeground() {
 186         if (comp != null) {
 187             return comp.getForeground();
 188         } else {
 189             return Color.black;
 190         }
 191     }
 192 
 193     private Color getBackground() {
 194         if (comp != null) {
 195             return comp.getBackground();
 196         } else {
 197             return Color.white;
 198         }
 199     }
 200 
 201     private Font getFont() {
 202         if (comp != null) {
 203             return comp.getFont();
 204         } else {
 205             if (defaultFont == null) {
 206                 defaultFont = new Font("Dialog", Font.PLAIN, 12);
 207             }
 208             return defaultFont;
 209         }
 210     }
 211 
 212     public Graphics2D createGraphics() {
 213         return new SunGraphics2D(volSurfaceManager.getPrimarySurfaceData(),
 214                                  getForeground(),
 215                                  getBackground(),
 216                                  getFont());
 217     }
 218 
 219     // Image method implementations
 220     public Object getProperty(String name, ImageObserver observer) {
 221         if (name == null) {
 222             throw new NullPointerException("null property name is not allowed");
 223         }
 224         return java.awt.Image.UndefinedProperty;
 225     }
 226 
 227     public int getWidth(ImageObserver observer) {
 228         return getWidth();
 229     }
 230 
 231     public int getHeight(ImageObserver observer) {
 232         return getHeight();
 233     }
 234 
 235     /**
 236      * This method creates a BufferedImage intended for use as a "snapshot"
 237      * or a backup surface.
 238      */
 239     public BufferedImage getBackupImage() {
 240         return getBackupImage(1, 1);
 241     }
 242 
 243     /**
 244      * This method creates a BufferedImage intended for use as a "snapshot"
 245      * or a backup surface with the given horizontal and vertical scale factors.
 246      */
 247     public BufferedImage getBackupImage(double scaleX, double scaleY) {
 248         int w = (int) Math.ceil(getWidth() * scaleX);
 249         int h = (int) Math.ceil(getHeight() * scaleY);
 250         return graphicsConfig.createCompatibleImage(w, h, getTransparency());
 251     }
 252 
 253     public BufferedImage getSnapshot() {
 254         BufferedImage bi = getBackupImage();
 255         Graphics2D g = bi.createGraphics();
 256         g.setComposite(AlphaComposite.Src);
 257         g.drawImage(this, 0, 0, null);
 258         g.dispose();
 259         return bi;
 260     }
 261 
 262     public int validate(GraphicsConfiguration gc) {
 263         return volSurfaceManager.validate(gc);
 264     }
 265 
 266     public boolean contentsLost() {
 267         return volSurfaceManager.contentsLost();
 268     }
 269 
 270     public ImageCapabilities getCapabilities() {
 271         return volSurfaceManager.getCapabilities(graphicsConfig);
 272     }
 273 
 274     /**
 275      * {@inheritDoc}
 276      *
 277      * @see sun.java2d.DestSurfaceProvider#getDestSurface
 278      */
 279     @Override
 280     public Surface getDestSurface() {
 281         return volSurfaceManager.getPrimarySurfaceData();
 282     }
 283 }