KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > graphics > Image


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.graphics;
12
13
14 import org.eclipse.swt.internal.gdip.*;
15 import org.eclipse.swt.internal.win32.*;
16 import org.eclipse.swt.*;
17
18 import java.io.*;
19
20 /**
21  * Instances of this class are graphics which have been prepared
22  * for display on a specific device. That is, they are ready
23  * to paint using methods such as <code>GC.drawImage()</code>
24  * and display on widgets with, for example, <code>Button.setImage()</code>.
25  * <p>
26  * If loaded from a file format that supports it, an
27  * <code>Image</code> may have transparency, meaning that certain
28  * pixels are specified as being transparent when drawn. Examples
29  * of file formats that support transparency are GIF and PNG.
30  * </p><p>
31  * There are two primary ways to use <code>Images</code>.
32  * The first is to load a graphic file from disk and create an
33  * <code>Image</code> from it. This is done using an <code>Image</code>
34  * constructor, for example:
35  * <pre>
36  * Image i = new Image(device, "C:\\graphic.bmp");
37  * </pre>
38  * A graphic file may contain a color table specifying which
39  * colors the image was intended to possess. In the above example,
40  * these colors will be mapped to the closest available color in
41  * SWT. It is possible to get more control over the mapping of
42  * colors as the image is being created, using code of the form:
43  * <pre>
44  * ImageData data = new ImageData("C:\\graphic.bmp");
45  * RGB[] rgbs = data.getRGBs();
46  * // At this point, rgbs contains specifications of all
47  * // the colors contained within this image. You may
48  * // allocate as many of these colors as you wish by
49  * // using the Color constructor Color(RGB), then
50  * // create the image:
51  * Image i = new Image(device, data);
52  * </pre>
53  * <p>
54  * Applications which require even greater control over the image
55  * loading process should use the support provided in class
56  * <code>ImageLoader</code>.
57  * </p><p>
58  * Application code must explicitly invoke the <code>Image.dispose()</code>
59  * method to release the operating system resources managed by each instance
60  * when those instances are no longer required.
61  * </p>
62  *
63  * @see Color
64  * @see ImageData
65  * @see ImageLoader
66  */

67
68 public final class Image extends Resource implements Drawable {
69     
70     /**
71      * specifies whether the receiver is a bitmap or an icon
72      * (one of <code>SWT.BITMAP</code>, <code>SWT.ICON</code>)
73      * <p>
74      * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
75      * public API. It is marked public only so that it can be shared
76      * within the packages provided by SWT. It is not available on all
77      * platforms and should never be accessed from application code.
78      * </p>
79      */

80     public int type;
81     
82     /**
83      * the handle to the OS image resource
84      * (Warning: This field is platform dependent)
85      * <p>
86      * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
87      * public API. It is marked public only so that it can be shared
88      * within the packages provided by SWT. It is not available on all
89      * platforms and should never be accessed from application code.
90      * </p>
91      */

92     public int handle;
93     
94     /**
95      * specifies the transparent pixel
96      */

97     int transparentPixel = -1;
98     
99     /**
100      * the GC which is drawing on the image
101      */

102     GC memGC;
103     
104     /**
105      * the alpha data for the image
106      */

107     byte[] alphaData;
108     
109     /**
110      * the global alpha value to be used for every pixel
111      */

112     int alpha = -1;
113     
114     /**
115      * the image data used to create this image if it is a
116      * icon. Used only in WinCE
117      */

118     ImageData data;
119     
120     /**
121      * width of the image
122      */

123     int width = -1;
124     
125     /**
126      * height of the image
127      */

128     int height = -1;
129     
130     /**
131      * specifies the default scanline padding
132      */

133     static final int DEFAULT_SCANLINE_PAD = 4;
134
135 /**
136  * Prevents uninitialized instances from being created outside the package.
137  */

138 Image () {
139 }
140
141 /**
142  * Constructs an empty instance of this class with the
143  * specified width and height. The result may be drawn upon
144  * by creating a GC and using any of its drawing operations,
145  * as shown in the following example:
146  * <pre>
147  * Image i = new Image(device, width, height);
148  * GC gc = new GC(i);
149  * gc.drawRectangle(0, 0, 50, 50);
150  * gc.dispose();
151  * </pre>
152  * <p>
153  * Note: Some platforms may have a limitation on the size
154  * of image that can be created (size depends on width, height,
155  * and depth). For example, Windows 95, 98, and ME do not allow
156  * images larger than 16M.
157  * </p>
158  *
159  * @param device the device on which to create the image
160  * @param width the width of the new image
161  * @param height the height of the new image
162  *
163  * @exception IllegalArgumentException <ul>
164  * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
165  * <li>ERROR_INVALID_ARGUMENT - if either the width or height is negative or zero</li>
166  * </ul>
167  * @exception SWTError <ul>
168  * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
169  * </ul>
170  */

171 public Image(Device device, int width, int height) {
172     if (device == null) device = Device.getDevice();
173     if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
174     init(device, width, height);
175     if (device.tracking) device.new_Object(this);
176 }
177
178 /**
179  * Constructs a new instance of this class based on the
180  * provided image, with an appearance that varies depending
181  * on the value of the flag. The possible flag values are:
182  * <dl>
183  * <dt><b>IMAGE_COPY</b></dt>
184  * <dd>the result is an identical copy of srcImage</dd>
185  * <dt><b>IMAGE_DISABLE</b></dt>
186  * <dd>the result is a copy of srcImage which has a <em>disabled</em> look</dd>
187  * <dt><b>IMAGE_GRAY</b></dt>
188  * <dd>the result is a copy of srcImage which has a <em>gray scale</em> look</dd>
189  * </dl>
190  *
191  * @param device the device on which to create the image
192  * @param srcImage the image to use as the source
193  * @param flag the style, either <code>IMAGE_COPY</code>, <code>IMAGE_DISABLE</code> or <code>IMAGE_GRAY</code>
194  *
195  * @exception IllegalArgumentException <ul>
196  * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
197  * <li>ERROR_NULL_ARGUMENT - if srcImage is null</li>
198  * <li>ERROR_INVALID_ARGUMENT - if the flag is not one of <code>IMAGE_COPY</code>, <code>IMAGE_DISABLE</code> or <code>IMAGE_GRAY</code></li>
199  * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
200  * </ul>
201  * @exception SWTException <ul>
202  * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon, or is otherwise in an invalid state</li>
203  * <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the image is not supported</li>
204  * </ul>
205  * @exception SWTError <ul>
206  * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
207  * </ul>
208  */

209 public Image(Device device, Image srcImage, int flag) {
210     if (device == null) device = Device.getDevice();
211     if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
212     this.device = device;
213     if (srcImage == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
214     if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
215     Rectangle rect = srcImage.getBounds();
216     switch (flag) {
217         case SWT.IMAGE_COPY: {
218             this.type = srcImage.type;
219             switch (type) {
220                 case SWT.BITMAP:
221                     /* Get the HDC for the device */
222                     int hDC = device.internal_new_GC(null);
223                     
224                     /* Copy the bitmap */
225                     int hdcSource = OS.CreateCompatibleDC(hDC);
226                     int hdcDest = OS.CreateCompatibleDC(hDC);
227                     int hOldSrc = OS.SelectObject(hdcSource, srcImage.handle);
228                     BITMAP bm = new BITMAP();
229                     OS.GetObject(srcImage.handle, BITMAP.sizeof, bm);
230                     handle = OS.CreateCompatibleBitmap(hdcSource, rect.width, bm.bmBits != 0 ? -rect.height : rect.height);
231                     if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
232                     int hOldDest = OS.SelectObject(hdcDest, handle);
233                     OS.BitBlt(hdcDest, 0, 0, rect.width, rect.height, hdcSource, 0, 0, OS.SRCCOPY);
234                     OS.SelectObject(hdcSource, hOldSrc);
235                     OS.SelectObject(hdcDest, hOldDest);
236                     OS.DeleteDC(hdcSource);
237                     OS.DeleteDC(hdcDest);
238
239                     /* Release the HDC for the device */
240                     device.internal_dispose_GC(hDC, null);
241
242                     transparentPixel = srcImage.transparentPixel;
243                     alpha = srcImage.alpha;
244                     if (srcImage.alphaData != null) {
245                         alphaData = new byte[srcImage.alphaData.length];
246                         System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length);
247                     }
248                     break;
249                 case SWT.ICON:
250                     if (OS.IsWinCE) {
251                         init(device, srcImage.data);
252                     } else {
253                         handle = OS.CopyImage(srcImage.handle, OS.IMAGE_ICON, rect.width, rect.height, 0);
254                         if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
255                     }
256                     break;
257                 default:
258                     SWT.error(SWT.ERROR_INVALID_IMAGE);
259             }
260             if (device.tracking) device.new_Object(this);
261             return;
262         }
263         case SWT.IMAGE_DISABLE: {
264             ImageData data = srcImage.getImageData();
265             PaletteData palette = data.palette;
266             RGB[] rgbs = new RGB[3];
267             rgbs[0] = device.getSystemColor(SWT.COLOR_BLACK).getRGB();
268             rgbs[1] = device.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW).getRGB();
269             rgbs[2] = device.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).getRGB();
270             ImageData newData = new ImageData(rect.width, rect.height, 8, new PaletteData(rgbs));
271             newData.alpha = data.alpha;
272             newData.alphaData = data.alphaData;
273             newData.maskData = data.maskData;
274             newData.maskPad = data.maskPad;
275             if (data.transparentPixel != -1) newData.transparentPixel = 0;
276
277             /* Convert the pixels. */
278             int[] scanline = new int[rect.width];
279             int[] maskScanline = null;
280             ImageData mask = null;
281             if (data.maskData != null) mask = data.getTransparencyMask();
282             if (mask != null) maskScanline = new int[rect.width];
283             int redMask = palette.redMask;
284             int greenMask = palette.greenMask;
285             int blueMask = palette.blueMask;
286             int redShift = palette.redShift;
287             int greenShift = palette.greenShift;
288             int blueShift = palette.blueShift;
289             for (int y=0; y<rect.height; y++) {
290                 int offset = y * newData.bytesPerLine;
291                 data.getPixels(0, y, rect.width, scanline, 0);
292                 if (mask != null) mask.getPixels(0, y, rect.width, maskScanline, 0);
293                 for (int x=0; x<rect.width; x++) {
294                     int pixel = scanline[x];
295                     if (!((data.transparentPixel != -1 && pixel == data.transparentPixel) || (mask != null && maskScanline[x] == 0))) {
296                         int red, green, blue;
297                         if (palette.isDirect) {
298                             red = pixel & redMask;
299                             red = (redShift < 0) ? red >>> -redShift : red << redShift;
300                             green = pixel & greenMask;
301                             green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
302                             blue = pixel & blueMask;
303                             blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
304                         } else {
305                             red = palette.colors[pixel].red;
306                             green = palette.colors[pixel].green;
307                             blue = palette.colors[pixel].blue;
308                         }
309                         int intensity = red * red + green * green + blue * blue;
310                         if (intensity < 98304) {
311                             newData.data[offset] = (byte)1;
312                         } else {
313                             newData.data[offset] = (byte)2;
314                         }
315                     }
316                     offset++;
317                 }
318             }
319             init (device, newData);
320             if (device.tracking) device.new_Object(this);
321             return;
322         }
323         case SWT.IMAGE_GRAY: {
324             ImageData data = srcImage.getImageData();
325             PaletteData palette = data.palette;
326             ImageData newData = data;
327             if (!palette.isDirect) {
328                 /* Convert the palette entries to gray. */
329                 RGB [] rgbs = palette.getRGBs();
330                 for (int i=0; i<rgbs.length; i++) {
331                     if (data.transparentPixel != i) {
332                         RGB color = rgbs [i];
333                         int red = color.red;
334                         int green = color.green;
335                         int blue = color.blue;
336                         int intensity = (red+red+green+green+green+green+green+blue) >> 3;
337                         color.red = color.green = color.blue = intensity;
338                     }
339                 }
340                 newData.palette = new PaletteData(rgbs);
341             } else {
342                 /* Create a 8 bit depth image data with a gray palette. */
343                 RGB[] rgbs = new RGB[256];
344                 for (int i=0; i<rgbs.length; i++) {
345                     rgbs[i] = new RGB(i, i, i);
346                 }
347                 newData = new ImageData(rect.width, rect.height, 8, new PaletteData(rgbs));
348                 newData.alpha = data.alpha;
349                 newData.alphaData = data.alphaData;
350                 newData.maskData = data.maskData;
351                 newData.maskPad = data.maskPad;
352                 if (data.transparentPixel != -1) newData.transparentPixel = 254;
353
354                 /* Convert the pixels. */
355                 int[] scanline = new int[rect.width];
356                 int redMask = palette.redMask;
357                 int greenMask = palette.greenMask;
358                 int blueMask = palette.blueMask;
359                 int redShift = palette.redShift;
360                 int greenShift = palette.greenShift;
361                 int blueShift = palette.blueShift;
362                 for (int y=0; y<rect.height; y++) {
363                     int offset = y * newData.bytesPerLine;
364                     data.getPixels(0, y, rect.width, scanline, 0);
365                     for (int x=0; x<rect.width; x++) {
366                         int pixel = scanline[x];
367                         if (pixel != data.transparentPixel) {
368                             int red = pixel & redMask;
369                             red = (redShift < 0) ? red >>> -redShift : red << redShift;
370                             int green = pixel & greenMask;
371                             green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
372                             int blue = pixel & blueMask;
373                             blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
374                             int intensity = (red+red+green+green+green+green+green+blue) >> 3;
375                             if (newData.transparentPixel == intensity) intensity = 255;
376                             newData.data[offset] = (byte)intensity;
377                         } else {
378                             newData.data[offset] = (byte)254;
379                         }
380                         offset++;
381                     }
382                 }
383             }
384             init (device, newData);
385             if (device.tracking) device.new_Object(this);
386             return;
387         }
388         default:
389             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
390     }
391 }
392
393 /**
394  * Constructs an empty instance of this class with the
395  * width and height of the specified rectangle. The result
396  * may be drawn upon by creating a GC and using any of its
397  * drawing operations, as shown in the following example:
398  * <pre>
399  * Image i = new Image(device, boundsRectangle);
400  * GC gc = new GC(i);
401  * gc.drawRectangle(0, 0, 50, 50);
402  * gc.dispose();
403  * </pre>
404  * <p>
405  * Note: Some platforms may have a limitation on the size
406  * of image that can be created (size depends on width, height,
407  * and depth). For example, Windows 95, 98, and ME do not allow
408  * images larger than 16M.
409  * </p>
410  *
411  * @param device the device on which to create the image
412  * @param bounds a rectangle specifying the image's width and height (must not be null)
413  *
414  * @exception IllegalArgumentException <ul>
415  * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
416  * <li>ERROR_NULL_ARGUMENT - if the bounds rectangle is null</li>
417  * <li>ERROR_INVALID_ARGUMENT - if either the rectangle's width or height is negative</li>
418  * </ul>
419  * @exception SWTError <ul>
420  * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
421  * </ul>
422  */

423 public Image(Device device, Rectangle bounds) {
424     if (device == null) device = Device.getDevice();
425     if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
426     if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
427     init(device, bounds.width, bounds.height);
428     if (device.tracking) device.new_Object(this);
429 }
430
431 /**
432  * Constructs an instance of this class from the given
433  * <code>ImageData</code>.
434  *
435  * @param device the device on which to create the image
436  * @param data the image data to create the image from (must not be null)
437  *
438  * @exception IllegalArgumentException <ul>
439  * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
440  * <li>ERROR_NULL_ARGUMENT - if the image data is null</li>
441  * </ul>
442  * @exception SWTException <ul>
443  * <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the ImageData is not supported</li>
444  * </ul>
445  * @exception SWTError <ul>
446  * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
447  * </ul>
448  */

449 public Image(Device device, ImageData data) {
450     if (device == null) device = Device.getDevice();
451     if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
452     init(device, data);
453     if (device.tracking) device.new_Object(this);
454 }
455
456 /**
457  * Constructs an instance of this class, whose type is
458  * <code>SWT.ICON</code>, from the two given <code>ImageData</code>
459  * objects. The two images must be the same size. Pixel transparency
460  * in either image will be ignored.
461  * <p>
462  * The mask image should contain white wherever the icon is to be visible,
463  * and black wherever the icon is to be transparent. In addition,
464  * the source image should contain black wherever the icon is to be
465  * transparent.
466  * </p>
467  *
468  * @param device the device on which to create the icon
469  * @param source the color data for the icon
470  * @param mask the mask data for the icon
471  *
472  * @exception IllegalArgumentException <ul>
473  * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
474  * <li>ERROR_NULL_ARGUMENT - if either the source or mask is null </li>
475  * <li>ERROR_INVALID_ARGUMENT - if source and mask are different sizes</li>
476  * </ul>
477  * @exception SWTError <ul>
478  * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
479  * </ul>
480  */

481 public Image(Device device, ImageData source, ImageData mask) {
482     if (device == null) device = Device.getDevice();
483     if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
484     if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
485     if (mask == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
486     if (source.width != mask.width || source.height != mask.height) {
487         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
488     }
489     mask = ImageData.convertMask(mask);
490     init(device, this, source, mask);
491     if (device.tracking) device.new_Object(this);
492 }
493
494 /**
495  * Constructs an instance of this class by loading its representation
496  * from the specified input stream. Throws an error if an error
497  * occurs while loading the image, or if the result is an image
498  * of an unsupported type. Application code is still responsible
499  * for closing the input stream.
500  * <p>
501  * This constructor is provided for convenience when loading a single
502  * image only. If the stream contains multiple images, only the first
503  * one will be loaded. To load multiple images, use
504  * <code>ImageLoader.load()</code>.
505  * </p><p>
506  * This constructor may be used to load a resource as follows:
507  * </p>
508  * <pre>
509  * static Image loadImage (Display display, Class clazz, String string) {
510  * InputStream stream = clazz.getResourceAsStream (string);
511  * if (stream == null) return null;
512  * Image image = null;
513  * try {
514  * image = new Image (display, stream);
515  * } catch (SWTException ex) {
516  * } finally {
517  * try {
518  * stream.close ();
519  * } catch (IOException ex) {}
520  * }
521  * return image;
522  * }
523  * </pre>
524  *
525  * @param device the device on which to create the image
526  * @param stream the input stream to load the image from
527  *
528  * @exception IllegalArgumentException <ul>
529  * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
530  * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
531  * </ul>
532  * @exception SWTException <ul>
533  * <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
534  * <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data </li>
535  * <li>ERROR_UNSUPPORTED_DEPTH - if the image stream describes an image with an unsupported depth</li>
536  * <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
537  * </ul>
538  * @exception SWTError <ul>
539  * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
540  * </ul>
541  */

542 public Image (Device device, InputStream stream) {
543     if (device == null) device = Device.getDevice();
544     if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
545     init(device, new ImageData(stream));
546     if (device.tracking) device.new_Object(this);
547 }
548
549 /**
550  * Constructs an instance of this class by loading its representation
551  * from the file with the specified name. Throws an error if an error
552  * occurs while loading the image, or if the result is an image
553  * of an unsupported type.
554  * <p>
555  * This constructor is provided for convenience when loading
556  * a single image only. If the specified file contains
557  * multiple images, only the first one will be used.
558  *
559  * @param device the device on which to create the image
560  * @param filename the name of the file to load the image from
561  *
562  * @exception IllegalArgumentException <ul>
563  * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
564  * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
565  * </ul>
566  * @exception SWTException <ul>
567  * <li>ERROR_IO - if an IO error occurs while reading from the file</li>
568  * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li>
569  * <li>ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth</li>
570  * <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
571  * </ul>
572  * @exception SWTError <ul>
573  * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
574  * </ul>
575  */

576 public Image (Device device, String JavaDoc filename) {
577     if (device == null) device = Device.getDevice();
578     if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
579     if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
580     this.device = device;
581     try {
582         device.checkGDIP();
583         int length = filename.length();
584         char[] chars = new char[length+1];
585         filename.getChars(0, length, chars, 0);
586         int bitmap = Gdip.Bitmap_new(chars, false);
587         if (bitmap != 0) {
588             int error = SWT.ERROR_NO_HANDLES;
589             int status = Gdip.Image_GetLastStatus(bitmap);
590             if (status == 0) {
591                 if (filename.toLowerCase().endsWith(".ico")) {
592                     this.type = SWT.ICON;
593                     int[] hicon = new int[1];
594                     Gdip.Bitmap_GetHICON(bitmap, hicon);
595                     this.handle = hicon[0];
596                 } else {
597                     this.type = SWT.BITMAP;
598                     int width = Gdip.Image_GetWidth(bitmap);
599                     int height = Gdip.Image_GetHeight(bitmap);
600                     int pixelFormat = Gdip.Image_GetPixelFormat(bitmap);
601                     switch (pixelFormat) {
602                         case Gdip.PixelFormat16bppRGB555:
603                         case Gdip.PixelFormat16bppRGB565:
604                             this.handle = createDIB(width, height, 16);
605                             break;
606                         case Gdip.PixelFormat24bppRGB:
607                             this.handle = createDIB(width, height, 24);
608                             break;
609                         case Gdip.PixelFormat32bppRGB:
610                         // These will loose either precision or transparency
611
case Gdip.PixelFormat16bppGrayScale:
612                         case Gdip.PixelFormat48bppRGB:
613                         case Gdip.PixelFormat32bppPARGB:
614                         case Gdip.PixelFormat64bppARGB:
615                         case Gdip.PixelFormat64bppPARGB:
616                             this.handle = createDIB(width, height, 32);
617                             break;
618                     }
619                     if (this.handle != 0) {
620                         /*
621                         * This performs better than getting the bits with Bitmap.LockBits(),
622                         * but it cannot be used when there is transparency.
623                         */

624                         int hDC = device.internal_new_GC(null);
625                         int srcHDC = OS.CreateCompatibleDC(hDC);
626                         int oldSrcBitmap = OS.SelectObject(srcHDC, this.handle);
627                         int graphics = Gdip.Graphics_new(srcHDC);
628                         if (graphics != 0) {
629                             Rect rect = new Rect();
630                             rect.Width = width;
631                             rect.Height = height;
632                             status = Gdip.Graphics_DrawImage(graphics, bitmap, rect, 0, 0, width, height, Gdip.UnitPixel, 0, 0, 0);
633                             if (status != 0) {
634                                 error = SWT.ERROR_INVALID_IMAGE;
635                                 OS.DeleteObject(handle);
636                                 this.handle = 0;
637                             }
638                             Gdip.Graphics_delete(graphics);
639                         }
640                         OS.SelectObject(srcHDC, oldSrcBitmap);
641                         OS.DeleteDC(srcHDC);
642                         device.internal_dispose_GC(hDC, null);
643                     } else {
644                         int lockedBitmapData = Gdip.BitmapData_new();
645                         if (lockedBitmapData != 0) {
646                             Gdip.Bitmap_LockBits(bitmap, 0, 0, pixelFormat, lockedBitmapData);
647                             BitmapData bitmapData = new BitmapData();
648                             Gdip.MoveMemory(bitmapData, lockedBitmapData);
649                             int stride = bitmapData.Stride;
650                             int pixels = bitmapData.Scan0;
651                             int depth = 0, scanlinePad = 4, transparentPixel = -1;
652                             switch (bitmapData.PixelFormat) {
653                                 case Gdip.PixelFormat1bppIndexed: depth = 1; break;
654                                 case Gdip.PixelFormat4bppIndexed: depth = 4; break;
655                                 case Gdip.PixelFormat8bppIndexed: depth = 8; break;
656                                 case Gdip.PixelFormat16bppARGB1555:
657                                 case Gdip.PixelFormat16bppRGB555:
658                                 case Gdip.PixelFormat16bppRGB565: depth = 16; break;
659                                 case Gdip.PixelFormat24bppRGB: depth = 24; break;
660                                 case Gdip.PixelFormat32bppRGB:
661                                 case Gdip.PixelFormat32bppARGB: depth = 32; break;
662                             }
663                             if (depth != 0) {
664                                 PaletteData paletteData = null;
665                                 switch (bitmapData.PixelFormat) {
666                                     case Gdip.PixelFormat1bppIndexed:
667                                     case Gdip.PixelFormat4bppIndexed:
668                                     case Gdip.PixelFormat8bppIndexed:
669                                         int paletteSize = Gdip.Image_GetPaletteSize(bitmap);
670                                         int hHeap = OS.GetProcessHeap();
671                                         int palette = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, paletteSize);
672                                         if (palette == 0) SWT.error(SWT.ERROR_NO_HANDLES);
673                                         Gdip.Image_GetPalette(bitmap, palette, paletteSize);
674                                         ColorPalette colorPalette = new ColorPalette();
675                                         Gdip.MoveMemory(colorPalette, palette, ColorPalette.sizeof);
676                                         int[] entries = new int[colorPalette.Count];
677                                         OS.MoveMemory(entries, palette + 8, entries.length * 4);
678                                         OS.HeapFree(hHeap, 0, palette);
679                                         RGB[] rgbs = new RGB[colorPalette.Count];
680                                         paletteData = new PaletteData(rgbs);
681                                         for (int i = 0; i < entries.length; i++) {
682                                             if (((entries[i] >> 24) & 0xFF) == 0 && (colorPalette.Flags & Gdip.PaletteFlagsHasAlpha) != 0) {
683                                                 transparentPixel = i;
684                                             }
685                                             rgbs[i] = new RGB(((entries[i] & 0xFF0000) >> 16), ((entries[i] & 0xFF00) >> 8), ((entries[i] & 0xFF) >> 0));
686                                         }
687                                         break;
688                                     case Gdip.PixelFormat16bppARGB1555:
689                                     case Gdip.PixelFormat16bppRGB555: paletteData = new PaletteData(0x7C00, 0x3E0, 0x1F); break;
690                                     case Gdip.PixelFormat16bppRGB565: paletteData = new PaletteData(0xF800, 0x7E0, 0x1F); break;
691                                     case Gdip.PixelFormat24bppRGB: paletteData = new PaletteData(0xFF, 0xFF00, 0xFF0000); break;
692                                     case Gdip.PixelFormat32bppRGB:
693                                     case Gdip.PixelFormat32bppARGB: paletteData = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); break;
694                                 }
695                                 byte[] data = new byte[stride * height], alphaData = null;
696                                 OS.MoveMemory(data, pixels, data.length);
697                                 switch (bitmapData.PixelFormat) {
698                                     case Gdip.PixelFormat16bppARGB1555:
699                                         alphaData = new byte[width * height];
700                                         for (int i = 1, j = 0; i < data.length; i += 2, j++) {
701                                             alphaData[j] = (byte)((data[i] & 0x80) != 0 ? 255 : 0);
702                                         }
703                                         break;
704                                     case Gdip.PixelFormat32bppARGB:
705                                         alphaData = new byte[width * height];
706                                         for (int i = 3, j = 0; i < data.length; i += 4, j++) {
707                                             alphaData[j] = data[i];
708                                         }
709                                         break;
710                                 }
711                                 Gdip.Bitmap_UnlockBits(bitmap, lockedBitmapData);
712                                 Gdip.BitmapData_delete(lockedBitmapData);
713                                 ImageData img = new ImageData(width, height, depth, paletteData, scanlinePad, data);
714                                 img.transparentPixel = transparentPixel;
715                                 img.alphaData = alphaData;
716                                 init(device, img);
717                             }
718                         }
719                     }
720                 }
721             }
722             Gdip.Bitmap_delete(bitmap);
723             if (status == 0) {
724                 if (this.handle == 0) SWT.error(error);
725                 return;
726             }
727         }
728     } catch (SWTException e) {}
729     init(device, new ImageData(filename));
730     if(device.tracking) device.new_Object(this);
731 }
732
733 /**
734  * Create a DIB from a DDB without using GetDIBits. Note that
735  * the DDB should not be selected into a HDC.
736  */

737 int createDIBFromDDB(int hDC, int hBitmap, int width, int height) {
738     
739     /* Determine the DDB depth */
740     int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
741     int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
742     int depth = bits * planes;
743     
744     /* Determine the DIB palette */
745     boolean isDirect = depth > 8;
746     RGB[] rgbs = null;
747     if (!isDirect) {
748         int numColors = 1 << depth;
749         byte[] logPalette = new byte[4 * numColors];
750         OS.GetPaletteEntries(device.hPalette, 0, numColors, logPalette);
751         rgbs = new RGB[numColors];
752         for (int i = 0; i < numColors; i++) {
753             rgbs[i] = new RGB(logPalette[i] & 0xFF, logPalette[i + 1] & 0xFF, logPalette[i + 2] & 0xFF);
754         }
755     }
756     
757     boolean useBitfields = OS.IsWinCE && (depth == 16 || depth == 32);
758     BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
759     bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
760     bmiHeader.biWidth = width;
761     bmiHeader.biHeight = -height;
762     bmiHeader.biPlanes = 1;
763     bmiHeader.biBitCount = (short)depth;
764     if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS;
765     else bmiHeader.biCompression = OS.BI_RGB;
766     byte[] bmi;
767     if (isDirect) bmi = new byte[BITMAPINFOHEADER.sizeof + (useBitfields ? 12 : 0)];
768     else bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4];
769     OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
770
771     /* Set the rgb colors into the bitmap info */
772     int offset = BITMAPINFOHEADER.sizeof;
773     if (isDirect) {
774         if (useBitfields) {
775             int redMask = 0;
776             int greenMask = 0;
777             int blueMask = 0;
778             switch (depth) {
779                 case 16:
780                     redMask = 0x7C00;
781                     greenMask = 0x3E0;
782                     blueMask = 0x1F;
783                     /* little endian */
784                     bmi[offset] = (byte)((redMask & 0xFF) >> 0);
785                     bmi[offset + 1] = (byte)((redMask & 0xFF00) >> 8);
786                     bmi[offset + 2] = (byte)((redMask & 0xFF0000) >> 16);
787                     bmi[offset + 3] = (byte)((redMask & 0xFF000000) >> 24);
788                     bmi[offset + 4] = (byte)((greenMask & 0xFF) >> 0);
789                     bmi[offset + 5] = (byte)((greenMask & 0xFF00) >> 8);
790                     bmi[offset + 6] = (byte)((greenMask & 0xFF0000) >> 16);
791                     bmi[offset + 7] = (byte)((greenMask & 0xFF000000) >> 24);
792                     bmi[offset + 8] = (byte)((blueMask & 0xFF) >> 0);
793                     bmi[offset + 9] = (byte)((blueMask & 0xFF00) >> 8);
794                     bmi[offset + 10] = (byte)((blueMask & 0xFF0000) >> 16);
795                     bmi[offset + 11] = (byte)((blueMask & 0xFF000000) >> 24);
796                     break;
797                 case 32:
798                     redMask = 0xFF00;
799                     greenMask = 0xFF0000;
800                     blueMask = 0xFF000000;
801                     /* big endian */
802                     bmi[offset] = (byte)((redMask & 0xFF000000) >> 24);
803                     bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16);
804                     bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8);
805                     bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0);
806                     bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24);
807                     bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16);
808                     bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8);
809                     bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0);
810                     bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24);
811                     bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16);
812                     bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8);
813                     bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0);
814                     break;
815                 default:
816                     SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
817             }
818         }
819     } else {
820         for (int j = 0; j < rgbs.length; j++) {
821             bmi[offset] = (byte)rgbs[j].blue;
822             bmi[offset + 1] = (byte)rgbs[j].green;
823             bmi[offset + 2] = (byte)rgbs[j].red;
824             bmi[offset + 3] = 0;
825             offset += 4;
826         }
827     }
828     int[] pBits = new int[1];
829     int hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
830     if (hDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
831     
832     /* Bitblt DDB into DIB */
833     int hdcSource = OS.CreateCompatibleDC(hDC);
834     int hdcDest = OS.CreateCompatibleDC(hDC);
835     int hOldSrc = OS.SelectObject(hdcSource, hBitmap);
836     int hOldDest = OS.SelectObject(hdcDest, hDib);
837     OS.BitBlt(hdcDest, 0, 0, width, height, hdcSource, 0, 0, OS.SRCCOPY);
838     OS.SelectObject(hdcSource, hOldSrc);
839     OS.SelectObject(hdcDest, hOldDest);
840     OS.DeleteDC(hdcSource);
841     OS.DeleteDC(hdcDest);
842     
843     return hDib;
844 }
845
846 int[] createGdipImage() {
847     switch (type) {
848         case SWT.BITMAP: {
849             if (alpha != -1 || alphaData != null || transparentPixel != -1) {
850                 BITMAP bm = new BITMAP();
851                 OS.GetObject(handle, BITMAP.sizeof, bm);
852                 int imgWidth = bm.bmWidth;
853                 int imgHeight = bm.bmHeight;
854                 int hDC = device.internal_new_GC(null);
855                 int srcHdc = OS.CreateCompatibleDC(hDC);
856                 int oldSrcBitmap = OS.SelectObject(srcHdc, handle);
857                 int memHdc = OS.CreateCompatibleDC(hDC);
858                 int memDib = createDIB(imgWidth, imgHeight, 32);
859                 if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
860                 int oldMemBitmap = OS.SelectObject(memHdc, memDib);
861                 BITMAP dibBM = new BITMAP();
862                 OS.GetObject(memDib, BITMAP.sizeof, dibBM);
863                 int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
864                 OS.BitBlt(memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
865                 byte red = 0, green = 0, blue = 0;
866                 if (transparentPixel != -1) {
867                     if (bm.bmBitsPixel <= 8) {
868                         byte[] color = new byte[4];
869                         OS.GetDIBColorTable(srcHdc, transparentPixel, 1, color);
870                         blue = color[0];
871                         green = color[1];
872                         red = color[2];
873                     } else {
874                         switch (bm.bmBitsPixel) {
875                             case 16:
876                                 int blueMask = 0x1F;
877                                 int blueShift = ImageData.getChannelShift(blueMask);
878                                 byte[] blues = ImageData.ANY_TO_EIGHT[ImageData.getChannelWidth(blueMask, blueShift)];
879                                 blue = blues[(transparentPixel & blueMask) >> blueShift];
880                                 int greenMask = 0x3E0;
881                                 int greenShift = ImageData.getChannelShift(greenMask);
882                                 byte[] greens = ImageData.ANY_TO_EIGHT[ImageData.getChannelWidth(greenMask, greenShift)];
883                                 green = greens[(transparentPixel & greenMask) >> greenShift];
884                                 int redMask = 0x7C00;
885                                 int redShift = ImageData.getChannelShift(redMask);
886                                 byte[] reds = ImageData.ANY_TO_EIGHT[ImageData.getChannelWidth(redMask, redShift)];
887                                 red = reds[(transparentPixel & redMask) >> redShift];
888                                 break;
889                             case 24:
890                                 blue = (byte)((transparentPixel & 0xFF0000) >> 16);
891                                 green = (byte)((transparentPixel & 0xFF00) >> 8);
892                                 red = (byte)(transparentPixel & 0xFF);
893                                 break;
894                             case 32:
895                                 blue = (byte)((transparentPixel & 0xFF000000) >>> 24);
896                                 green = (byte)((transparentPixel & 0xFF0000) >> 16);
897                                 red = (byte)((transparentPixel & 0xFF00) >> 8);
898                                 break;
899                         }
900                     }
901                 }
902                 OS.SelectObject(srcHdc, oldSrcBitmap);
903                 OS.SelectObject(memHdc, oldMemBitmap);
904                 OS.DeleteObject(srcHdc);
905                 OS.DeleteObject(memHdc);
906                 byte[] srcData = new byte[sizeInBytes];
907                 OS.MoveMemory(srcData, dibBM.bmBits, sizeInBytes);
908                 OS.DeleteObject(memDib);
909                 device.internal_dispose_GC(hDC, null);
910                 if (alpha != -1) {
911                     for (int y = 0, dp = 0; y < imgHeight; ++y) {
912                         for (int x = 0; x < imgWidth; ++x) {
913                             srcData[dp + 3] = (byte)alpha;
914                             dp += 4;
915                         }
916                     }
917                 } else if (alphaData != null) {
918                     for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
919                         for (int x = 0; x < imgWidth; ++x) {
920                             srcData[dp + 3] = alphaData[ap++];
921                             dp += 4;
922                         }
923                     }
924                 } else if (transparentPixel != -1) {
925                     for (int y = 0, dp = 0; y < imgHeight; ++y) {
926                         for (int x = 0; x < imgWidth; ++x) {
927                             if (srcData[dp] == blue && srcData[dp + 1] == green && srcData[dp + 2] == red) {
928                                 srcData[dp + 3] = (byte)0;
929                             } else {
930                                 srcData[dp + 3] = (byte)0xFF;
931                             }
932                             dp += 4;
933                         }
934                     }
935                 }
936                 int hHeap = OS.GetProcessHeap();
937                 int pixels = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, srcData.length);
938                 if (pixels == 0) SWT.error(SWT.ERROR_NO_HANDLES);
939                 OS.MoveMemory(pixels, srcData, sizeInBytes);
940                 return new int[]{Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, Gdip.PixelFormat32bppARGB, pixels), pixels};
941             }
942             return new int[]{Gdip.Bitmap_new(handle, 0), 0};
943         }
944         case SWT.ICON: {
945             /*
946             * Bug in GDI+. Creating a new GDI+ Bitmap from a HICON segment faults
947             * when the icon width is bigger than the icon height. The fix is to
948             * detect this and create a PixelFormat32bppARGB image instead.
949             */

950             ICONINFO iconInfo = new ICONINFO();
951             if (OS.IsWinCE) {
952                 GetIconInfo(this, iconInfo);
953             } else {
954                 OS.GetIconInfo(handle, iconInfo);
955             }
956             int hBitmap = iconInfo.hbmColor;
957             if (hBitmap == 0) hBitmap = iconInfo.hbmMask;
958             BITMAP bm = new BITMAP();
959             OS.GetObject(hBitmap, BITMAP.sizeof, bm);
960             int imgWidth = bm.bmWidth;
961             int imgHeight = hBitmap == iconInfo.hbmMask ? bm.bmHeight / 2 : bm.bmHeight;
962             int img = 0, pixels = 0;
963             if (imgWidth > imgHeight) {
964                 int hDC = device.internal_new_GC(null);
965                 int srcHdc = OS.CreateCompatibleDC(hDC);
966                 int oldSrcBitmap = OS.SelectObject(srcHdc, hBitmap);
967                 int memHdc = OS.CreateCompatibleDC(hDC);
968                 int memDib = createDIB(imgWidth, imgHeight, 32);
969                 if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
970                 int oldMemBitmap = OS.SelectObject(memHdc, memDib);
971                 BITMAP dibBM = new BITMAP();
972                 OS.GetObject(memDib, BITMAP.sizeof, dibBM);
973                 OS.BitBlt(memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, hBitmap == iconInfo.hbmMask ? imgHeight : 0, OS.SRCCOPY);
974                 OS.SelectObject(memHdc, oldMemBitmap);
975                 OS.DeleteObject(memHdc);
976                 byte[] srcData = new byte[dibBM.bmWidthBytes * dibBM.bmHeight];
977                 OS.MoveMemory(srcData, dibBM.bmBits, srcData.length);
978                 OS.DeleteObject(memDib);
979                 OS.SelectObject(srcHdc, iconInfo.hbmMask);
980                 for (int y = 0, dp = 0; y < imgHeight; ++y) {
981                     for (int x = 0; x < imgWidth; ++x) {
982                         if (OS.GetPixel(srcHdc, x, y) != 0) {
983                             srcData[dp + 3] = (byte)0;
984                         } else {
985                             srcData[dp + 3] = (byte)0xFF;
986                         }
987                         dp += 4;
988                     }
989                 }
990                 OS.SelectObject(srcHdc, oldSrcBitmap);
991                 OS.DeleteObject(srcHdc);
992                 device.internal_dispose_GC(hDC, null);
993                 int hHeap = OS.GetProcessHeap();
994                 pixels = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, srcData.length);
995                 if (pixels == 0) SWT.error(SWT.ERROR_NO_HANDLES);
996                 OS.MoveMemory(pixels, srcData, srcData.length);
997                 img = Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, Gdip.PixelFormat32bppARGB, pixels);
998             } else {
999                 img = Gdip.Bitmap_new(handle);
1000            }
1001            if (iconInfo.hbmColor != 0) OS.DeleteObject(iconInfo.hbmColor);
1002            if (iconInfo.hbmMask != 0) OS.DeleteObject(iconInfo.hbmMask);
1003            return new int[]{img, pixels};
1004        }
1005        default: SWT.error(SWT.ERROR_INVALID_IMAGE);
1006    }
1007    return null;
1008}
1009
1010/**
1011 * Disposes of the operating system resources associated with
1012 * the image. Applications must dispose of all images which
1013 * they allocate.
1014 */

1015public void dispose () {
1016    if (handle == 0) return;
1017    if (device.isDisposed()) return;
1018    if (memGC != null) memGC.dispose();
1019    if (type == SWT.ICON) {
1020        if (OS.IsWinCE) data = null;
1021        OS.DestroyIcon (handle);
1022    } else {
1023        OS.DeleteObject (handle);
1024    }
1025    handle = 0;
1026    memGC = null;
1027    if (device.tracking) device.dispose_Object(this);
1028    device = null;
1029}
1030
1031/**
1032 * Compares the argument to the receiver, and returns true
1033 * if they represent the <em>same</em> object using a class
1034 * specific comparison.
1035 *
1036 * @param object the object to compare with this object
1037 * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
1038 *
1039 * @see #hashCode
1040 */

1041public boolean equals (Object JavaDoc object) {
1042    if (object == this) return true;
1043    if (!(object instanceof Image)) return false;
1044    Image image = (Image) object;
1045    return device == image.device && handle == image.handle;
1046}
1047
1048/**
1049 * Returns the color to which to map the transparent pixel, or null if
1050 * the receiver has no transparent pixel.
1051 * <p>
1052 * There are certain uses of Images that do not support transparency
1053 * (for example, setting an image into a button or label). In these cases,
1054 * it may be desired to simulate transparency by using the background
1055 * color of the widget to paint the transparent pixels of the image.
1056 * Use this method to check which color will be used in these cases
1057 * in place of transparency. This value may be set with setBackground().
1058 * <p>
1059 *
1060 * @return the background color of the image, or null if there is no transparency in the image
1061 *
1062 * @exception SWTException <ul>
1063 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1064 * </ul>
1065 */

1066public Color getBackground() {
1067    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1068    if (transparentPixel == -1) return null;
1069
1070    /* Get the HDC for the device */
1071    int hDC = device.internal_new_GC(null);
1072    
1073    /* Compute the background color */
1074    BITMAP bm = new BITMAP();
1075    OS.GetObject(handle, BITMAP.sizeof, bm);
1076    int hdcMem = OS.CreateCompatibleDC(hDC);
1077    int hOldObject = OS.SelectObject(hdcMem, handle);
1078    int red = 0, green = 0, blue = 0;
1079    if (bm.bmBitsPixel <= 8) {
1080        if (OS.IsWinCE) {
1081            byte[] pBits = new byte[1];
1082            OS.MoveMemory(pBits, bm.bmBits, 1);
1083            byte oldValue = pBits[0];
1084            int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF;
1085            pBits[0] = (byte)((transparentPixel << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask));
1086            OS.MoveMemory(bm.bmBits, pBits, 1);
1087            int color = OS.GetPixel(hdcMem, 0, 0);
1088            pBits[0] = oldValue;
1089            OS.MoveMemory(bm.bmBits, pBits, 1);
1090            blue = (color & 0xFF0000) >> 16;
1091            green = (color & 0xFF00) >> 8;
1092            red = color & 0xFF;
1093        } else {
1094            byte[] color = new byte[4];
1095            OS.GetDIBColorTable(hdcMem, transparentPixel, 1, color);
1096            blue = color[0] & 0xFF;
1097            green = color[1] & 0xFF;
1098            red = color[2] & 0xFF;
1099        }
1100    } else {
1101        switch (bm.bmBitsPixel) {
1102            case 16:
1103                blue = (transparentPixel & 0x1F) << 3;
1104                green = (transparentPixel & 0x3E0) >> 2;
1105                red = (transparentPixel & 0x7C00) >> 7;
1106                break;
1107            case 24:
1108                blue = (transparentPixel & 0xFF0000) >> 16;
1109                green = (transparentPixel & 0xFF00) >> 8;
1110                red = transparentPixel & 0xFF;
1111                break;
1112            case 32:
1113                blue = (transparentPixel & 0xFF000000) >>> 24;
1114                green = (transparentPixel & 0xFF0000) >> 16;
1115                red = (transparentPixel & 0xFF00) >> 8;
1116                break;
1117            default:
1118                return null;
1119        }
1120    }
1121    OS.SelectObject(hdcMem, hOldObject);
1122    OS.DeleteDC(hdcMem);
1123    
1124    /* Release the HDC for the device */
1125    device.internal_dispose_GC(hDC, null);
1126    return Color.win32_new(device, (blue << 16) | (green << 8) | red);
1127}
1128
1129/**
1130 * Returns the bounds of the receiver. The rectangle will always
1131 * have x and y values of 0, and the width and height of the
1132 * image.
1133 *
1134 * @return a rectangle specifying the image's bounds
1135 *
1136 * @exception SWTException <ul>
1137 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1138 * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
1139 * </ul>
1140 */

1141public Rectangle getBounds() {
1142    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1143    if (width != -1 && height != -1) {
1144        return new Rectangle(0, 0, width, height);
1145    }
1146    switch (type) {
1147        case SWT.BITMAP:
1148            BITMAP bm = new BITMAP();
1149            OS.GetObject(handle, BITMAP.sizeof, bm);
1150            return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight);
1151        case SWT.ICON:
1152            if (OS.IsWinCE) {
1153                return new Rectangle(0, 0, width = data.width, height = data.height);
1154            } else {
1155                ICONINFO info = new ICONINFO();
1156                OS.GetIconInfo(handle, info);
1157                int hBitmap = info.hbmColor;
1158                if (hBitmap == 0) hBitmap = info.hbmMask;
1159                bm = new BITMAP();
1160                OS.GetObject(hBitmap, BITMAP.sizeof, bm);
1161                if (hBitmap == info.hbmMask) bm.bmHeight /= 2;
1162                if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor);
1163                if (info.hbmMask != 0) OS.DeleteObject(info.hbmMask);
1164                return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight);
1165            }
1166        default:
1167            SWT.error(SWT.ERROR_INVALID_IMAGE);
1168            return null;
1169    }
1170}
1171
1172/**
1173 * Returns an <code>ImageData</code> based on the receiver
1174 * Modifications made to this <code>ImageData</code> will not
1175 * affect the Image.
1176 *
1177 * @return an <code>ImageData</code> containing the image's data and attributes
1178 *
1179 * @exception SWTException <ul>
1180 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1181 * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
1182 * </ul>
1183 *
1184 * @see ImageData
1185 */

1186public ImageData getImageData() {
1187    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1188    BITMAP bm;
1189    int depth, width, height;
1190    switch (type) {
1191        case SWT.ICON: {
1192            if (OS.IsWinCE) return data;
1193            ICONINFO info = new ICONINFO();
1194            if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
1195            OS.GetIconInfo(handle, info);
1196            /* Get the basic BITMAP information */
1197            int hBitmap = info.hbmColor;
1198            if (hBitmap == 0) hBitmap = info.hbmMask;
1199            bm = new BITMAP();
1200            OS.GetObject(hBitmap, BITMAP.sizeof, bm);
1201            depth = bm.bmPlanes * bm.bmBitsPixel;
1202            width = bm.bmWidth;
1203            if (hBitmap == info.hbmMask) bm.bmHeight /= 2;
1204            height = bm.bmHeight;
1205            int numColors = 0;
1206            if (depth <= 8) numColors = 1 << depth;
1207            /* Create the BITMAPINFO */
1208            BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
1209            bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
1210            bmiHeader.biWidth = width;
1211            bmiHeader.biHeight = -height;
1212            bmiHeader.biPlanes = 1;
1213            bmiHeader.biBitCount = (short)depth;
1214            bmiHeader.biCompression = OS.BI_RGB;
1215            byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
1216            OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
1217            
1218            /* Get the HDC for the device */
1219            int hDC = device.internal_new_GC(null);
1220    
1221            /* Create the DC and select the bitmap */
1222            int hBitmapDC = OS.CreateCompatibleDC(hDC);
1223            int hOldBitmap = OS.SelectObject(hBitmapDC, hBitmap);
1224            /* Select the palette if necessary */
1225            int oldPalette = 0;
1226            if (depth <= 8) {
1227                int hPalette = device.hPalette;
1228                if (hPalette != 0) {
1229                    oldPalette = OS.SelectPalette(hBitmapDC, hPalette, false);
1230                    OS.RealizePalette(hBitmapDC);
1231                }
1232            }
1233            /* Find the size of the image and allocate data */
1234            int imageSize;
1235            /* Call with null lpBits to get the image size */
1236            if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
1237            OS.GetDIBits(hBitmapDC, hBitmap, 0, height, 0, bmi, OS.DIB_RGB_COLORS);
1238            OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
1239            imageSize = bmiHeader.biSizeImage;
1240            byte[] data = new byte[imageSize];
1241            /* Get the bitmap data */
1242            int hHeap = OS.GetProcessHeap();
1243            int lpvBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
1244            if (lpvBits == 0) SWT.error(SWT.ERROR_NO_HANDLES);
1245            if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
1246            OS.GetDIBits(hBitmapDC, hBitmap, 0, height, lpvBits, bmi, OS.DIB_RGB_COLORS);
1247            OS.MoveMemory(data, lpvBits, imageSize);
1248            /* Calculate the palette */
1249            PaletteData palette = null;
1250            if (depth <= 8) {
1251                RGB[] rgbs = new RGB[numColors];
1252                int srcIndex = 40;
1253                for (int i = 0; i < numColors; i++) {
1254                    rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF);
1255                    srcIndex += 4;
1256                }
1257                palette = new PaletteData(rgbs);
1258            } else if (depth == 16) {
1259                palette = new PaletteData(0x7C00, 0x3E0, 0x1F);
1260            } else if (depth == 24) {
1261                palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
1262            } else if (depth == 32) {
1263                palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
1264            } else {
1265                SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
1266            }
1267
1268            /* Do the mask */
1269            byte [] maskData = null;
1270            if (info.hbmColor == 0) {
1271                /* Do the bottom half of the mask */
1272                maskData = new byte[imageSize];
1273                if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
1274                OS.GetDIBits(hBitmapDC, hBitmap, height, height, lpvBits, bmi, OS.DIB_RGB_COLORS);
1275                OS.MoveMemory(maskData, lpvBits, imageSize);
1276            } else {
1277                /* Do the entire mask */
1278                /* Create the BITMAPINFO */
1279                bmiHeader = new BITMAPINFOHEADER();
1280                bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
1281                bmiHeader.biWidth = width;
1282                bmiHeader.biHeight = -height;
1283                bmiHeader.biPlanes = 1;
1284                bmiHeader.biBitCount = 1;
1285                bmiHeader.biCompression = OS.BI_RGB;
1286                bmi = new byte[BITMAPINFOHEADER.sizeof + 8];
1287                OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
1288                
1289                /* First color black, second color white */
1290                int offset = BITMAPINFOHEADER.sizeof;
1291                bmi[offset + 4] = bmi[offset + 5] = bmi[offset + 6] = (byte)0xFF;
1292                bmi[offset + 7] = 0;
1293                OS.SelectObject(hBitmapDC, info.hbmMask);
1294                /* Call with null lpBits to get the image size */
1295                if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
1296                OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, 0, bmi, OS.DIB_RGB_COLORS);
1297                OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
1298                imageSize = bmiHeader.biSizeImage;
1299                maskData = new byte[imageSize];
1300                int lpvMaskBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
1301                if (lpvMaskBits == 0) SWT.error(SWT.ERROR_NO_HANDLES);
1302                if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
1303                OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, lpvMaskBits, bmi, OS.DIB_RGB_COLORS);
1304                OS.MoveMemory(maskData, lpvMaskBits, imageSize);
1305                OS.HeapFree(hHeap, 0, lpvMaskBits);
1306                /* Loop to invert the mask */
1307                for (int i = 0; i < maskData.length; i++) {
1308                    maskData[i] ^= -1;
1309                }
1310                /* Make sure mask scanlinePad is 2 */
1311                int maskPad;
1312                int bpl = imageSize / height;
1313                for (maskPad = 1; maskPad < 128; maskPad++) {
1314                    int calcBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad;
1315                    if (calcBpl == bpl) break;
1316                }
1317                maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, 2);
1318            }
1319            /* Clean up */
1320            OS.HeapFree(hHeap, 0, lpvBits);
1321            OS.SelectObject(hBitmapDC, hOldBitmap);
1322            if (oldPalette != 0) {
1323                OS.SelectPalette(hBitmapDC, oldPalette, false);
1324                OS.RealizePalette(hBitmapDC);
1325            }
1326            OS.DeleteDC(hBitmapDC);
1327            
1328            /* Release the HDC for the device */
1329            device.internal_dispose_GC(hDC, null);
1330            
1331            if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor);
1332            if (info.hbmMask != 0) OS.DeleteObject(info.hbmMask);
1333            /* Construct and return the ImageData */
1334            ImageData imageData = new ImageData(width, height, depth, palette, 4, data);
1335            imageData.maskData = maskData;
1336            imageData.maskPad = 2;
1337            return imageData;
1338        }
1339        case SWT.BITMAP: {
1340            /* Get the basic BITMAP information */
1341            bm = new BITMAP();
1342            OS.GetObject(handle, BITMAP.sizeof, bm);
1343            depth = bm.bmPlanes * bm.bmBitsPixel;
1344            width = bm.bmWidth;
1345            height = bm.bmHeight;
1346            /* Find out whether this is a DIB or a DDB. */
1347            boolean isDib = (bm.bmBits != 0);
1348            /* Get the HDC for the device */
1349            int hDC = device.internal_new_GC(null);
1350
1351            /*
1352            * Feature in WinCE. GetDIBits is not available in WinCE. The
1353            * workaround is to create a temporary DIB from the DDB and use
1354            * the bmBits field of DIBSECTION to retrieve the image data.
1355            */

1356            int handle = this.handle;
1357            if (OS.IsWinCE) {
1358                if (!isDib) {
1359                    boolean mustRestore = false;
1360                    if (memGC != null && !memGC.isDisposed()) {
1361                        memGC.flush ();
1362                        mustRestore = true;
1363                        GCData data = memGC.data;
1364                        if (data.hNullBitmap != 0) {
1365                            OS.SelectObject(memGC.handle, data.hNullBitmap);
1366                            data.hNullBitmap = 0;
1367                        }
1368                    }
1369                    handle = createDIBFromDDB(hDC, this.handle, width, height);
1370                    if (mustRestore) {
1371                        int hOldBitmap = OS.SelectObject(memGC.handle, this.handle);
1372                        memGC.data.hNullBitmap = hOldBitmap;
1373                    }
1374                    isDib = true;
1375                }
1376            }
1377            DIBSECTION dib = null;
1378            if (isDib) {
1379                dib = new DIBSECTION();
1380                OS.GetObject(handle, DIBSECTION.sizeof, dib);
1381            }
1382            /* Calculate number of colors */
1383            int numColors = 0;
1384            if (depth <= 8) {
1385                if (isDib) {
1386                    numColors = dib.biClrUsed;
1387                } else {
1388                    numColors = 1 << depth;
1389                }
1390            }
1391            /* Create the BITMAPINFO */
1392            byte[] bmi = null;
1393            BITMAPINFOHEADER bmiHeader = null;
1394            if (!isDib) {
1395                bmiHeader = new BITMAPINFOHEADER();
1396                bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
1397                bmiHeader.biWidth = width;
1398                bmiHeader.biHeight = -height;
1399                bmiHeader.biPlanes = 1;
1400                bmiHeader.biBitCount = (short)depth;
1401                bmiHeader.biCompression = OS.BI_RGB;
1402                bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
1403                OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
1404            }
1405            
1406            /* Create the DC and select the bitmap */
1407            int hBitmapDC = OS.CreateCompatibleDC(hDC);
1408            int hOldBitmap = OS.SelectObject(hBitmapDC, handle);
1409            /* Select the palette if necessary */
1410            int oldPalette = 0;
1411            if (!isDib && depth <= 8) {
1412                int hPalette = device.hPalette;
1413                if (hPalette != 0) {
1414                    oldPalette = OS.SelectPalette(hBitmapDC, hPalette, false);
1415                    OS.RealizePalette(hBitmapDC);
1416                }
1417            }
1418            /* Find the size of the image and allocate data */
1419            int imageSize;
1420            if (isDib) {
1421                imageSize = dib.biSizeImage;
1422            } else {
1423                /* Call with null lpBits to get the image size */
1424                if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
1425                OS.GetDIBits(hBitmapDC, handle, 0, height, 0, bmi, OS.DIB_RGB_COLORS);
1426                OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof);
1427                imageSize = bmiHeader.biSizeImage;
1428            }
1429            byte[] data = new byte[imageSize];
1430            /* Get the bitmap data */
1431            if (isDib) {
1432                if (OS.IsWinCE && this.handle != handle) {
1433                    /* get image data from the temporary DIB */
1434                    OS.MoveMemory(data, dib.bmBits, imageSize);
1435                } else {
1436                    OS.MoveMemory(data, bm.bmBits, imageSize);
1437                }
1438            } else {
1439                int hHeap = OS.GetProcessHeap();
1440                int lpvBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
1441                if (lpvBits == 0) SWT.error(SWT.ERROR_NO_HANDLES);
1442                if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
1443                OS.GetDIBits(hBitmapDC, handle, 0, height, lpvBits, bmi, OS.DIB_RGB_COLORS);
1444                OS.MoveMemory(data, lpvBits, imageSize);
1445                OS.HeapFree(hHeap, 0, lpvBits);
1446            }
1447            /* Calculate the palette */
1448            PaletteData palette = null;
1449            if (depth <= 8) {
1450                RGB[] rgbs = new RGB[numColors];
1451                if (isDib) {
1452                    if (OS.IsWinCE) {
1453                        /*
1454                        * Feature on WinCE. GetDIBColorTable is not supported.
1455                        * The workaround is to set a pixel to the desired
1456                        * palette index and use getPixel to get the corresponding
1457                        * RGB value.
1458                        */

1459                        int red = 0, green = 0, blue = 0;
1460                        byte[] pBits = new byte[1];
1461                        OS.MoveMemory(pBits, bm.bmBits, 1);
1462                        byte oldValue = pBits[0];
1463                        int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF;
1464                        for (int i = 0; i < numColors; i++) {
1465                            pBits[0] = (byte)((i << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask));
1466                            OS.MoveMemory(bm.bmBits, pBits, 1);
1467                            int color = OS.GetPixel(hBitmapDC, 0, 0);
1468                            blue = (color & 0xFF0000) >> 16;
1469                            green = (color & 0xFF00) >> 8;
1470                            red = color & 0xFF;
1471                            rgbs[i] = new RGB(red, green, blue);
1472                        }
1473                        pBits[0] = oldValue;
1474                        OS.MoveMemory(bm.bmBits, pBits, 1);
1475                    } else {
1476                        byte[] colors = new byte[numColors * 4];
1477                        OS.GetDIBColorTable(hBitmapDC, 0, numColors, colors);
1478                        int colorIndex = 0;
1479                        for (int i = 0; i < rgbs.length; i++) {
1480                            rgbs[i] = new RGB(colors[colorIndex + 2] & 0xFF, colors[colorIndex + 1] & 0xFF, colors[colorIndex] & 0xFF);
1481                            colorIndex += 4;
1482                        }
1483                    }
1484                } else {
1485                    int srcIndex = BITMAPINFOHEADER.sizeof;
1486                    for (int i = 0; i < numColors; i++) {
1487                        rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF);
1488                        srcIndex += 4;
1489                    }
1490                }
1491                palette = new PaletteData(rgbs);
1492            } else if (depth == 16) {
1493                palette = new PaletteData(0x7C00, 0x3E0, 0x1F);
1494            } else if (depth == 24) {
1495                palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
1496            } else if (depth == 32) {
1497                palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
1498            } else {
1499                SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
1500            }
1501            /* Clean up */
1502            OS.SelectObject(hBitmapDC, hOldBitmap);
1503            if (oldPalette != 0) {
1504                OS.SelectPalette(hBitmapDC, oldPalette, false);
1505                OS.RealizePalette(hBitmapDC);
1506            }
1507            if (OS.IsWinCE) {
1508                if (handle != this.handle) {
1509                    /* free temporary DIB */
1510                    OS.DeleteObject (handle);
1511                }
1512            }
1513            OS.DeleteDC(hBitmapDC);
1514            
1515            /* Release the HDC for the device */
1516            device.internal_dispose_GC(hDC, null);
1517            
1518            /* Construct and return the ImageData */
1519            ImageData imageData = new ImageData(width, height, depth, palette, 4, data);
1520            imageData.transparentPixel = this.transparentPixel;
1521            imageData.alpha = alpha;
1522            if (alpha == -1 && alphaData != null) {
1523                imageData.alphaData = new byte[alphaData.length];
1524                System.arraycopy(alphaData, 0, imageData.alphaData, 0, alphaData.length);
1525            }
1526            return imageData;
1527        }
1528        default:
1529            SWT.error(SWT.ERROR_INVALID_IMAGE);
1530            return null;
1531    }
1532}
1533
1534/**
1535 * Returns an integer hash code for the receiver. Any two
1536 * objects that return <code>true</code> when passed to
1537 * <code>equals</code> must return the same value for this
1538 * method.
1539 *
1540 * @return the receiver's hash
1541 *
1542 * @see #equals
1543 */

1544public int hashCode () {
1545    return handle;
1546}
1547
1548void init(Device device, int width, int height) {
1549    if (width <= 0 || height <= 0) {
1550        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1551    }
1552    this.device = device;
1553    type = SWT.BITMAP;
1554    int hDC = device.internal_new_GC(null);
1555    handle = OS.CreateCompatibleBitmap(hDC, width, height);
1556    /*
1557    * Feature in Windows. CreateCompatibleBitmap() may fail
1558    * for large images. The fix is to create a DIB section
1559    * in that case.
1560    */

1561    if (handle == 0) {
1562        int bits = OS.GetDeviceCaps(hDC, OS.BITSPIXEL);
1563        int planes = OS.GetDeviceCaps(hDC, OS.PLANES);
1564        int depth = bits * planes;
1565        if (depth < 16) depth = 16;
1566        handle = createDIB(width, height, depth);
1567    }
1568    if (handle != 0) {
1569        int memDC = OS.CreateCompatibleDC(hDC);
1570        int hOldBitmap = OS.SelectObject(memDC, handle);
1571        OS.PatBlt(memDC, 0, 0, width, height, OS.PATCOPY);
1572        OS.SelectObject(memDC, hOldBitmap);
1573        OS.DeleteDC(memDC);
1574    }
1575    device.internal_dispose_GC(hDC, null);
1576    if (handle == 0) {
1577        SWT.error(SWT.ERROR_NO_HANDLES, null, device.getLastError());
1578    }
1579}
1580
1581static int createDIB(int width, int height, int depth) {
1582    BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
1583    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
1584    bmiHeader.biWidth = width;
1585    bmiHeader.biHeight = -height;
1586    bmiHeader.biPlanes = 1;
1587    bmiHeader.biBitCount = (short)depth;
1588    if (OS.IsWinCE) bmiHeader.biCompression = OS.BI_BITFIELDS;
1589    else bmiHeader.biCompression = OS.BI_RGB;
1590    byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + (OS.IsWinCE ? 12 : 0)];
1591    OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
1592    /* Set the rgb colors into the bitmap info */
1593    if (OS.IsWinCE) {
1594        int redMask = 0xFF00;
1595        int greenMask = 0xFF0000;
1596        int blueMask = 0xFF000000;
1597        /* big endian */
1598        int offset = BITMAPINFOHEADER.sizeof;
1599        bmi[offset] = (byte)((redMask & 0xFF000000) >> 24);
1600        bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16);
1601        bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8);
1602        bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0);
1603        bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24);
1604        bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16);
1605        bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8);
1606        bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0);
1607        bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24);
1608        bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16);
1609        bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8);
1610        bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0);
1611    }
1612
1613    int[] pBits = new int[1];
1614    return OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
1615}
1616
1617/**
1618 * Feature in WinCE. GetIconInfo is not available in WinCE.
1619 * The workaround is to cache the object ImageData for images
1620 * of type SWT.ICON. The bitmaps hbmMask and hbmColor can then
1621 * be reconstructed by using our version of getIconInfo.
1622 * This function takes an ICONINFO object and sets the fields
1623 * hbmMask and hbmColor with the corresponding bitmaps it has
1624 * created.
1625 * Note. These bitmaps must be freed - as they would have to be
1626 * if the regular GetIconInfo had been used.
1627 */

1628static void GetIconInfo(Image image, ICONINFO info) {
1629    int[] result = init(image.device, null, image.data);
1630    info.hbmColor = result[0];
1631    info.hbmMask = result[1];
1632}
1633
1634static int[] init(Device device, Image image, ImageData i) {
1635    if (image != null) image.device = device;
1636    
1637    /*
1638     * BUG in Windows 98:
1639     * A monochrome DIBSection will display as solid black
1640     * on Windows 98 machines, even though it contains the
1641     * correct data. The fix is to convert 1-bit ImageData
1642     * into 4-bit ImageData before creating the image.
1643     */

1644    /* Windows does not support 2-bit images. Convert to 4-bit image. */
1645    if ((OS.IsWin95 && i.depth == 1 && i.getTransparencyType() != SWT.TRANSPARENCY_MASK) || i.depth == 2) {
1646        ImageData img = new ImageData(i.width, i.height, 4, i.palette);
1647        ImageData.blit(ImageData.BLIT_SRC,
1648            i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, null, null, null,
1649            ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
1650            img.data, img.depth, img.bytesPerLine, i.getByteOrder(), 0, 0, img.width, img.height, null, null, null,
1651            false, false);
1652        img.transparentPixel = i.transparentPixel;
1653        img.maskPad = i.maskPad;
1654        img.maskData = i.maskData;
1655        img.alpha = i.alpha;
1656        img.alphaData = i.alphaData;
1657        i = img;
1658    }
1659    /*
1660     * Windows supports 16-bit mask of (0x7C00, 0x3E0, 0x1F),
1661     * 24-bit mask of (0xFF0000, 0xFF00, 0xFF) and 32-bit mask
1662     * (0x00FF0000, 0x0000FF00, 0x000000FF) as documented in
1663     * MSDN BITMAPINFOHEADER. Make sure the image is
1664     * Windows-supported.
1665     */

1666    /*
1667    * Note on WinCE. CreateDIBSection requires the biCompression
1668    * field of the BITMAPINFOHEADER to be set to BI_BITFIELDS for
1669    * 16 and 32 bit direct images (see MSDN for CreateDIBSection).
1670    * In this case, the color mask can be set to any value. For
1671    * consistency, it is set to the same mask used by non WinCE
1672    * platforms in BI_RGB mode.
1673    */

1674    if (i.palette.isDirect) {
1675        final PaletteData palette = i.palette;
1676        final int redMask = palette.redMask;
1677        final int greenMask = palette.greenMask;
1678        final int blueMask = palette.blueMask;
1679        int newDepth = i.depth;
1680        int newOrder = ImageData.MSB_FIRST;
1681        PaletteData newPalette = null;
1682
1683        switch (i.depth) {
1684            case 8:
1685                newDepth = 16;
1686                newOrder = ImageData.LSB_FIRST;
1687                newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
1688                break;
1689            case 16:
1690                newOrder = ImageData.LSB_FIRST;
1691                if (!(redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F)) {
1692                    newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
1693                }
1694                break;
1695            case 24:
1696                if (!(redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000)) {
1697                    newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
1698                }
1699                break;
1700            case 32:
1701                if (!(redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) {
1702                    newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
1703                }
1704                break;
1705            default:
1706                SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
1707        }
1708        if (newPalette != null) {
1709            ImageData img = new ImageData(i.width, i.height, newDepth, newPalette);
1710            ImageData.blit(ImageData.BLIT_SRC,
1711                    i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, redMask, greenMask, blueMask,
1712                    ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
1713                    img.data, img.depth, img.bytesPerLine, newOrder, 0, 0, img.width, img.height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
1714                    false, false);
1715            if (i.transparentPixel != -1) {
1716                img.transparentPixel = newPalette.getPixel(palette.getRGB(i.transparentPixel));
1717            }
1718            img.maskPad = i.maskPad;
1719            img.maskData = i.maskData;
1720            img.alpha = i.alpha;
1721            img.alphaData = i.alphaData;
1722            i = img;
1723        }
1724    }
1725    /* Construct bitmap info header by hand */
1726    RGB[] rgbs = i.palette.getRGBs();
1727    boolean useBitfields = OS.IsWinCE && (i.depth == 16 || i.depth == 32);
1728    BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
1729    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
1730    bmiHeader.biWidth = i.width;
1731    bmiHeader.biHeight = -i.height;
1732    bmiHeader.biPlanes = 1;
1733    bmiHeader.biBitCount = (short)i.depth;
1734    if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS;
1735    else bmiHeader.biCompression = OS.BI_RGB;
1736    bmiHeader.biClrUsed = rgbs == null ? 0 : rgbs.length;
1737    byte[] bmi;
1738    if (i.palette.isDirect)
1739        bmi = new byte[BITMAPINFOHEADER.sizeof + (useBitfields ? 12 : 0)];
1740    else
1741        bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4];
1742    OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
1743    /* Set the rgb colors into the bitmap info */
1744    int offset = BITMAPINFOHEADER.sizeof;
1745    if (i.palette.isDirect) {
1746        if (useBitfields) {
1747            PaletteData palette = i.palette;
1748            int redMask = palette.redMask;
1749            int greenMask = palette.greenMask;
1750            int blueMask = palette.blueMask;
1751            /*
1752             * The color masks must be written based on the
1753             * endianness of the ImageData.
1754             */

1755            if (i.getByteOrder() == ImageData.LSB_FIRST) {
1756                bmi[offset] = (byte)((redMask & 0xFF) >> 0);
1757                bmi[offset + 1] = (byte)((redMask & 0xFF00) >> 8);
1758                bmi[offset + 2] = (byte)((redMask & 0xFF0000) >> 16);
1759                bmi[offset + 3] = (byte)((redMask & 0xFF000000) >> 24);
1760                bmi[offset + 4] = (byte)((greenMask & 0xFF) >> 0);
1761                bmi[offset + 5] = (byte)((greenMask & 0xFF00) >> 8);
1762                bmi[offset + 6] = (byte)((greenMask & 0xFF0000) >> 16);
1763                bmi[offset + 7] = (byte)((greenMask & 0xFF000000) >> 24);
1764                bmi[offset + 8] = (byte)((blueMask & 0xFF) >> 0);
1765                bmi[offset + 9] = (byte)((blueMask & 0xFF00) >> 8);
1766                bmi[offset + 10] = (byte)((blueMask & 0xFF0000) >> 16);
1767                bmi[offset + 11] = (byte)((blueMask & 0xFF000000) >> 24);
1768            } else {
1769                bmi[offset] = (byte)((redMask & 0xFF000000) >> 24);
1770                bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16);
1771                bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8);
1772                bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0);
1773                bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24);
1774                bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16);
1775                bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8);
1776                bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0);
1777                bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24);
1778                bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16);
1779                bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8);
1780                bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0);
1781            }
1782        }
1783    } else {
1784        for (int j = 0; j < rgbs.length; j++) {
1785            bmi[offset] = (byte)rgbs[j].blue;
1786            bmi[offset + 1] = (byte)rgbs[j].green;
1787            bmi[offset + 2] = (byte)rgbs[j].red;
1788            bmi[offset + 3] = 0;
1789            offset += 4;
1790        }
1791    }
1792    int[] pBits = new int[1];
1793    int hDib = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
1794    if (hDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
1795    /* In case of a scanline pad other than 4, do the work to convert it */
1796    byte[] data = i.data;
1797    if (i.scanlinePad != 4 && (i.bytesPerLine % 4 != 0)) {
1798        data = ImageData.convertPad(data, i.width, i.height, i.depth, i.scanlinePad, 4);
1799    }
1800    OS.MoveMemory(pBits[0], data, data.length);
1801    
1802    int[] result = null;
1803    if (i.getTransparencyType() == SWT.TRANSPARENCY_MASK) {
1804        /* Get the HDC for the device */
1805        int hDC = device.internal_new_GC(null);
1806            
1807        /* Create the color bitmap */
1808        int hdcSrc = OS.CreateCompatibleDC(hDC);
1809        OS.SelectObject(hdcSrc, hDib);
1810        int hBitmap = OS.CreateCompatibleBitmap(hDC, i.width, i.height);
1811        if (hBitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
1812        int hdcDest = OS.CreateCompatibleDC(hDC);
1813        OS.SelectObject(hdcDest, hBitmap);
1814        OS.BitBlt(hdcDest, 0, 0, i.width, i.height, hdcSrc, 0, 0, OS.SRCCOPY);
1815        
1816        /* Release the HDC for the device */
1817        device.internal_dispose_GC(hDC, null);
1818            
1819        /* Create the mask. Windows requires icon masks to have a scanline pad of 2. */
1820        byte[] maskData = ImageData.convertPad(i.maskData, i.width, i.height, 1, i.maskPad, 2);
1821        int hMask = OS.CreateBitmap(i.width, i.height, 1, 1, maskData);
1822        if (hMask == 0) SWT.error(SWT.ERROR_NO_HANDLES);
1823        OS.SelectObject(hdcSrc, hMask);
1824        OS.PatBlt(hdcSrc, 0, 0, i.width, i.height, OS.DSTINVERT);
1825        OS.DeleteDC(hdcSrc);
1826        OS.DeleteDC(hdcDest);
1827        OS.DeleteObject(hDib);
1828        
1829        if (image == null) {
1830            result = new int[]{hBitmap, hMask};
1831        } else {
1832            /* Create the icon */
1833            ICONINFO info = new ICONINFO();
1834            info.fIcon = true;
1835            info.hbmColor = hBitmap;
1836            info.hbmMask = hMask;
1837            int hIcon = OS.CreateIconIndirect(info);
1838            if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
1839            OS.DeleteObject(hBitmap);
1840            OS.DeleteObject(hMask);
1841            image.handle = hIcon;
1842            image.type = SWT.ICON;
1843            if (OS.IsWinCE) image.data = i;
1844        }
1845    } else {
1846        if (image == null) {
1847            result = new int[]{hDib};
1848        } else {
1849            image.handle = hDib;
1850            image.type = SWT.BITMAP;
1851            image.transparentPixel = i.transparentPixel;
1852            if (image.transparentPixel == -1) {
1853                image.alpha = i.alpha;
1854                if (i.alpha == -1 && i.alphaData != null) {
1855                    int length = i.alphaData.length;
1856                    image.alphaData = new byte[length];
1857                    System.arraycopy(i.alphaData, 0, image.alphaData, 0, length);
1858                }
1859            }
1860        }
1861    }
1862    return result;
1863}
1864
1865static int[] init(Device device, Image image, ImageData source, ImageData mask) {
1866    /* Create a temporary image and locate the black pixel */
1867    ImageData imageData;
1868    int blackIndex = 0;
1869    if (source.palette.isDirect) {
1870        imageData = new ImageData(source.width, source.height, source.depth, source.palette);
1871    } else {
1872        RGB black = new RGB(0, 0, 0);
1873        RGB[] rgbs = source.getRGBs();
1874        if (source.transparentPixel != -1) {
1875            /*
1876             * The source had transparency, so we can use the transparent pixel
1877             * for black.
1878             */

1879            RGB[] newRGBs = new RGB[rgbs.length];
1880            System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length);
1881            if (source.transparentPixel >= newRGBs.length) {
1882                /* Grow the palette with black */
1883                rgbs = new RGB[source.transparentPixel + 1];
1884                System.arraycopy(newRGBs, 0, rgbs, 0, newRGBs.length);
1885                for (int i = newRGBs.length; i <= source.transparentPixel; i++) {
1886                    rgbs[i] = new RGB(0, 0, 0);
1887                }
1888            } else {
1889                newRGBs[source.transparentPixel] = black;
1890                rgbs = newRGBs;
1891            }
1892            blackIndex = source.transparentPixel;
1893            imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs));
1894        } else {
1895            while (blackIndex < rgbs.length) {
1896                if (rgbs[blackIndex].equals(black)) break;
1897                blackIndex++;
1898            }
1899            if (blackIndex == rgbs.length) {
1900                /*
1901                 * We didn't find black in the palette, and there is no transparent
1902                 * pixel we can use.
1903                 */

1904                if ((1 << source.depth) > rgbs.length) {
1905                    /* We can grow the palette and add black */
1906                    RGB[] newRGBs = new RGB[rgbs.length + 1];
1907                    System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length);
1908                    newRGBs[rgbs.length] = black;
1909                    rgbs = newRGBs;
1910                } else {
1911                    /* No room to grow the palette */
1912                    blackIndex = -1;
1913                }
1914            }
1915            imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs));
1916        }
1917    }
1918    if (blackIndex == -1) {
1919        /* There was no black in the palette, so just copy the data over */
1920        System.arraycopy(source.data, 0, imageData.data, 0, imageData.data.length);
1921    } else {
1922        /* Modify the source image to contain black wherever the mask is 0 */
1923        int[] imagePixels = new int[imageData.width];
1924        int[] maskPixels = new int[mask.width];
1925        for (int y = 0; y < imageData.height; y++) {
1926            source.getPixels(0, y, imageData.width, imagePixels, 0);
1927            mask.getPixels(0, y, mask.width, maskPixels, 0);
1928            for (int i = 0; i < imagePixels.length; i++) {
1929                if (maskPixels[i] == 0) imagePixels[i] = blackIndex;
1930            }
1931            imageData.setPixels(0, y, source.width, imagePixels, 0);
1932        }
1933    }
1934    imageData.maskPad = mask.scanlinePad;
1935    imageData.maskData = mask.data;
1936    return init(device, image, imageData);
1937}
1938void init(Device device, ImageData i) {
1939    if (i == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
1940    init(device, this, i);
1941}
1942
1943/**
1944 * Invokes platform specific functionality to allocate a new GC handle.
1945 * <p>
1946 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1947 * API for <code>Image</code>. It is marked public only so that it
1948 * can be shared within the packages provided by SWT. It is not
1949 * available on all platforms, and should never be called from
1950 * application code.
1951 * </p>
1952 *
1953 * @param data the platform specific GC data
1954 * @return the platform specific GC handle
1955 */

1956public int internal_new_GC (GCData data) {
1957    if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1958    /*
1959    * Create a new GC that can draw into the image.
1960    * Only supported for bitmaps.
1961    */

1962    if (type != SWT.BITMAP || memGC != null) {
1963        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1964    }
1965    
1966    /* Create a compatible HDC for the device */
1967    int hDC = device.internal_new_GC(null);
1968    int imageDC = OS.CreateCompatibleDC(hDC);
1969    device.internal_dispose_GC(hDC, null);
1970    if (imageDC == 0) SWT.error(SWT.ERROR_NO_HANDLES);
1971
1972    if (data != null) {
1973        /* Set the GCData fields */
1974        int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
1975        if ((data.style & mask) != 0) {
1976            data.layout = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.LAYOUT_RTL : 0;
1977        } else {
1978            data.style |= SWT.LEFT_TO_RIGHT;
1979        }
1980        data.device = device;
1981        data.image = this;
1982        data.hFont = device.systemFont;
1983    }
1984    return imageDC;
1985}
1986
1987/**
1988 * Invokes platform specific functionality to dispose a GC handle.
1989 * <p>
1990 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1991 * API for <code>Image</code>. It is marked public only so that it
1992 * can be shared within the packages provided by SWT. It is not
1993 * available on all platforms, and should never be called from
1994 * application code.
1995 * </p>
1996 *
1997 * @param hDC the platform specific GC handle
1998 * @param data the platform specific GC data
1999 */

2000public void internal_dispose_GC (int hDC, GCData data) {
2001    OS.DeleteDC(hDC);
2002}
2003
2004/**
2005 * Returns <code>true</code> if the image has been disposed,
2006 * and <code>false</code> otherwise.
2007 * <p>
2008 * This method gets the dispose state for the image.
2009 * When an image has been disposed, it is an error to
2010 * invoke any other method using the image.
2011 *
2012 * @return <code>true</code> when the image is disposed and <code>false</code> otherwise
2013 */

2014public boolean isDisposed() {
2015    return handle == 0;
2016}
2017
2018/**
2019 * Sets the color to which to map the transparent pixel.
2020 * <p>
2021 * There are certain uses of <code>Images</code> that do not support
2022 * transparency (for example, setting an image into a button or label).
2023 * In these cases, it may be desired to simulate transparency by using
2024 * the background color of the widget to paint the transparent pixels
2025 * of the image. This method specifies the color that will be used in
2026 * these cases. For example:
2027 * <pre>
2028 * Button b = new Button();
2029 * image.setBackground(b.getBackground());
2030 * b.setImage(image);
2031 * </pre>
2032 * </p><p>
2033 * The image may be modified by this operation (in effect, the
2034 * transparent regions may be filled with the supplied color). Hence
2035 * this operation is not reversible and it is not legal to call
2036 * this function twice or with a null argument.
2037 * </p><p>
2038 * This method has no effect if the receiver does not have a transparent
2039 * pixel value.
2040 * </p>
2041 *
2042 * @param color the color to use when a transparent pixel is specified
2043 *
2044 * @exception IllegalArgumentException <ul>
2045 * <li>ERROR_NULL_ARGUMENT - if the color is null</li>
2046 * <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
2047 * </ul>
2048 * @exception SWTException <ul>
2049 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2050 * </ul>
2051 */

2052public void setBackground(Color color) {
2053    /*
2054    * Note. Not implemented on WinCE.
2055    */

2056    if (OS.IsWinCE) return;
2057    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
2058    if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
2059    if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2060    if (transparentPixel == -1) return;
2061
2062    /* Get the HDC for the device */
2063    int hDC = device.internal_new_GC(null);
2064    
2065    /* Change the background color in the image */
2066    BITMAP bm = new BITMAP();
2067    OS.GetObject(handle, BITMAP.sizeof, bm);
2068    int hdcMem = OS.CreateCompatibleDC(hDC);
2069    OS.SelectObject(hdcMem, handle);
2070    int maxColors = 1 << bm.bmBitsPixel;
2071    byte[] colors = new byte[maxColors * 4];
2072    if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
2073    int numColors = OS.GetDIBColorTable(hdcMem, 0, maxColors, colors);
2074    int offset = transparentPixel * 4;
2075    colors[offset] = (byte)color.getBlue();
2076    colors[offset + 1] = (byte)color.getGreen();
2077    colors[offset + 2] = (byte)color.getRed();
2078    if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
2079    OS.SetDIBColorTable(hdcMem, 0, numColors, colors);
2080    OS.DeleteDC(hdcMem);
2081    
2082    /* Release the HDC for the device */
2083    device.internal_dispose_GC(hDC, null);
2084}
2085
2086/**
2087 * Returns a string containing a concise, human-readable
2088 * description of the receiver.
2089 *
2090 * @return a string representation of the receiver
2091 */

2092public String JavaDoc toString () {
2093    if (isDisposed()) return "Image {*DISPOSED*}";
2094    return "Image {" + handle + "}";
2095}
2096
2097/**
2098 * Invokes platform specific functionality to allocate a new image.
2099 * <p>
2100 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
2101 * API for <code>Image</code>. It is marked public only so that it
2102 * can be shared within the packages provided by SWT. It is not
2103 * available on all platforms, and should never be called from
2104 * application code.
2105 * </p>
2106 *
2107 * @param device the device on which to allocate the color
2108 * @param type the type of the image (<code>SWT.BITMAP</code> or <code>SWT.ICON</code>)
2109 * @param handle the OS handle for the image
2110 * @return a new image object containing the specified device, type and handle
2111 */

2112public static Image win32_new(Device device, int type, int handle) {
2113    if (device == null) device = Device.getDevice();
2114    Image image = new Image();
2115    image.type = type;
2116    image.handle = handle;
2117    image.device = device;
2118    return image;
2119}
2120
2121}
2122
Popular Tags