1 /*
   2  * Copyright (c) 2006, 2018, 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 package sun.awt;
  26 import java.awt.*;
  27 import java.awt.color.*;
  28 import java.awt.geom.AffineTransform;
  29 import java.awt.image.*;
  30 import sun.awt.image.ToolkitImage;
  31 import sun.awt.image.ImageRepresentation;
  32 import java.util.Arrays;
  33 import sun.java2d.pipe.Region;
  34 
  35 public class IconInfo {
  36     /**
  37      * Representation of image as an int array.
  38      * It's used on platforms where icon data
  39      * is expected to be in 32-bit format.
  40      */
  41     private int[] intIconData;
  42     /**
  43      * Representation of image as an long array.
  44      * It's used on platforms where icon data
  45      * is expected to be in 64-bit format.
  46      */
  47     private long[] longIconData;
  48     /**
  49      * Icon image.
  50      */
  51     private Image image;
  52     /**
  53      * Width of icon image. Being set in constructor.
  54      */
  55     private final int width;
  56     /**
  57      * Height of icon image. Being set in constructor.
  58      */
  59     private final int height;
  60     /**
  61      * Width of scaled icon image. Can be set in setScaledDimension.
  62      */
  63     private int scaledWidth;
  64     /**
  65      * Height of scaled icon image. Can be set in setScaledDimension.
  66      */
  67     private int scaledHeight;
  68     /**
  69      * Length of raw data. Being set in constructor / setScaledDimension.
  70      */
  71     private int rawLength;
  72 
  73     public IconInfo(int[] intIconData) {
  74         this.intIconData =
  75             (null == intIconData) ? null : Arrays.copyOf(intIconData, intIconData.length);
  76         this.width = intIconData[0];
  77         this.height = intIconData[1];
  78         this.scaledWidth = width;
  79         this.scaledHeight = height;
  80         this.rawLength = width * height + 2;
  81     }
  82 
  83     public IconInfo(long[] longIconData) {
  84         this.longIconData =
  85         (null == longIconData) ? null : Arrays.copyOf(longIconData, longIconData.length);
  86         this.width = (int)longIconData[0];
  87         this.height = (int)longIconData[1];
  88         this.scaledWidth = width;
  89         this.scaledHeight = height;
  90         this.rawLength = width * height + 2;
  91     }
  92 
  93     public IconInfo(Image image) {
  94         this.image = image;
  95         if (image instanceof ToolkitImage) {
  96             ImageRepresentation ir = ((ToolkitImage)image).getImageRep();
  97             ir.reconstruct(ImageObserver.ALLBITS);
  98             this.width = ir.getWidth();
  99             this.height = ir.getHeight();
 100         } else {
 101             this.width = image.getWidth(null);
 102             this.height = image.getHeight(null);
 103         }
 104         this.scaledWidth = width;
 105         this.scaledHeight = height;
 106         this.rawLength = getScaledRawLength(width, height);
 107     }
 108 
 109     /*
 110      * It sets size of scaled icon.
 111      */
 112     public void setScaledSize(int width, int height) {
 113         this.scaledWidth = width;
 114         this.scaledHeight = height;
 115         this.rawLength = getScaledRawLength(width, height);
 116     }
 117 
 118     /*
 119     * returns scaled raw length.
 120      */
 121     private int getScaledRawLength(int w, int h) {
 122         int[] scaledWidthAndHeight = getScaledWidthAndHeight(w, h);
 123         return scaledWidthAndHeight[0] * scaledWidthAndHeight[1] + 2;
 124     }
 125 
 126     /*
 127     * returns the scaled width and height.
 128      */
 129     private static int[] getScaledWidthAndHeight(int width, int height) {
 130         AffineTransform tx = GraphicsEnvironment.getLocalGraphicsEnvironment().
 131                 getDefaultScreenDevice().getDefaultConfiguration().
 132                 getDefaultTransform();
 133         int w = Region.clipScale(width, tx.getScaleX());
 134         int h = Region.clipScale(height, tx.getScaleY());
 135         return new int[]{w, h};
 136     }
 137 
 138     public boolean isValid() {
 139         return (width > 0 && height > 0);
 140     }
 141 
 142     public int getWidth() {
 143         return width;
 144     }
 145 
 146     public int getHeight() {
 147         return height;
 148     }
 149 
 150     public String toString() {
 151         return "IconInfo[w=" + width + ",h=" + height + ",sw=" + scaledWidth + ",sh=" + scaledHeight + "]";
 152     }
 153 
 154     public int getRawLength() {
 155         return rawLength;
 156     }
 157 
 158     public int[] getIntData() {
 159         if (this.intIconData == null) {
 160             if (this.longIconData != null) {
 161                 this.intIconData = longArrayToIntArray(longIconData);
 162             } else if (this.image != null) {
 163                 this.intIconData = imageToIntArray(this.image, scaledWidth, scaledHeight);
 164             }
 165         }
 166         return this.intIconData;
 167     }
 168 
 169     public long[] getLongData() {
 170         if (this.longIconData == null) {
 171             if (this.intIconData != null) {
 172                 this.longIconData = intArrayToLongArray(this.intIconData);
 173             } else if (this.image != null) {
 174                 int[] intIconData = imageToIntArray(this.image, scaledWidth, scaledHeight);
 175                 this.longIconData = intArrayToLongArray(intIconData);
 176             }
 177         }
 178         return this.longIconData;
 179     }
 180 
 181     public Image getImage() {
 182         if (this.image == null) {
 183             if (this.intIconData != null) {
 184                 this.image = intArrayToImage(this.intIconData);
 185             } else if (this.longIconData != null) {
 186                 int[] intIconData = longArrayToIntArray(this.longIconData);
 187                 this.image = intArrayToImage(intIconData);
 188             }
 189         }
 190         return this.image;
 191     }
 192 
 193     private static int[] longArrayToIntArray(long[] longData) {
 194         int[] intData = new int[longData.length];
 195         for (int i = 0; i < longData.length; i++) {
 196             // Such a conversion is valid since the
 197             // original data (see
 198             // make/sun/xawt/ToBin.java) were ints
 199             intData[i] = (int)longData[i];
 200         }
 201         return intData;
 202     }
 203 
 204     private static long[] intArrayToLongArray(int[] intData) {
 205         long[] longData = new long[intData.length];
 206         for (int i = 0; i < intData.length; i++) {
 207             longData[i] = intData[i];
 208         }
 209         return longData;
 210     }
 211 
 212     static Image intArrayToImage(int[] raw) {
 213         ColorModel cm =
 214             new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32,
 215                                  0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
 216                                  false, DataBuffer.TYPE_INT);
 217         DataBuffer buffer = new DataBufferInt(raw, raw.length-2, 2);
 218         WritableRaster raster =
 219             Raster.createPackedRaster(buffer, raw[0], raw[1],
 220                                       raw[0],
 221                                       new int[] {0x00ff0000, 0x0000ff00,
 222                                                  0x000000ff, 0xff000000},
 223                                       null);
 224         BufferedImage im = new BufferedImage(cm, raster, false, null);
 225         return im;
 226     }
 227 
 228     /*
 229      * Returns array of integers which holds data for the image.
 230      * It scales the image if necessary.
 231      */
 232     static int[] imageToIntArray(Image image, int width, int height) {
 233         if (width <= 0 || height <= 0) {
 234             return null;
 235         }
 236         ColorModel cm =
 237             new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32,
 238                                  0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
 239                                  false, DataBuffer.TYPE_INT);
 240         int[] scaledWidthAndHeight = getScaledWidthAndHeight(width, height);
 241         width = scaledWidthAndHeight[0];
 242         height = scaledWidthAndHeight[1];
 243         DataBufferInt buffer = new DataBufferInt(width * height);
 244         WritableRaster raster =
 245             Raster.createPackedRaster(buffer, width, height,
 246                                       width,
 247                                       new int[] {0x00ff0000, 0x0000ff00,
 248                                                  0x000000ff, 0xff000000},
 249                                       null);
 250         BufferedImage im = new BufferedImage(cm, raster, false, null);
 251         Graphics g = im.getGraphics();
 252         g.drawImage(image, 0, 0, width, height, null);
 253         g.dispose();
 254         int[] data = buffer.getData();
 255         int[] raw = new int[width * height + 2];
 256         raw[0] = width;
 257         raw[1] = height;
 258         System.arraycopy(data, 0, raw, 2, width * height);
 259         return raw;
 260     }
 261 
 262 }