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 
IconInfo(int[] intIconData)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 
IconInfo(long[] longIconData)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 
IconInfo(Image image)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      */
setScaledSize(int width, int height)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      */
getScaledRawLength(int w, int h)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      */
getScaledWidthAndHeight(int width, int height)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 
isValid()138     public boolean isValid() {
139         return (width > 0 && height > 0);
140     }
141 
getWidth()142     public int getWidth() {
143         return width;
144     }
145 
getHeight()146     public int getHeight() {
147         return height;
148     }
149 
toString()150     public String toString() {
151         return "IconInfo[w=" + width + ",h=" + height + ",sw=" + scaledWidth + ",sh=" + scaledHeight + "]";
152     }
153 
getRawLength()154     public int getRawLength() {
155         return rawLength;
156     }
157 
getIntData()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 
getLongData()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 
getImage()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 
longArrayToIntArray(long[] longData)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 
intArrayToLongArray(int[] intData)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 
intArrayToImage(int[] raw)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      */
imageToIntArray(Image image, int width, int height)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 }
263