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