KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > internal > ImageList


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.internal;
12
13
14 import org.eclipse.swt.internal.win32.*;
15 import org.eclipse.swt.*;
16 import org.eclipse.swt.graphics.*;
17
18 public class ImageList {
19     int handle, style, refCount;
20     Image [] images;
21
22 public ImageList (int style) {
23     this.style = style;
24     int flags = OS.ILC_MASK;
25     if (OS.IsWinCE) {
26         flags |= OS.ILC_COLOR;
27     } else {
28         if (OS.COMCTL32_MAJOR >= 6) {
29             flags |= OS.ILC_COLOR32;
30         } else {
31             int hDC = OS.GetDC (0);
32             int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
33             int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
34             OS.ReleaseDC (0, hDC);
35             int depth = bits * planes;
36             switch (depth) {
37                 case 4: flags |= OS.ILC_COLOR4; break;
38                 case 8: flags |= OS.ILC_COLOR8; break;
39                 case 16: flags |= OS.ILC_COLOR16; break;
40                 case 24: flags |= OS.ILC_COLOR24; break;
41                 case 32: flags |= OS.ILC_COLOR32; break;
42                 default: flags |= OS.ILC_COLOR; break;
43             }
44         }
45     }
46     if ((style & SWT.RIGHT_TO_LEFT) != 0) flags |= OS.ILC_MIRROR;
47     handle = OS.ImageList_Create (32, 32, flags, 16, 16);
48     images = new Image [4];
49 }
50
51 public int add (Image image) {
52     int count = OS.ImageList_GetImageCount (handle);
53     int index = 0;
54     while (index < count) {
55         if (images [index] != null) {
56             if (images [index].isDisposed ()) images [index] = null;
57         }
58         if (images [index] == null) break;
59         index++;
60     }
61     if (count == 0) {
62         Rectangle rect = image.getBounds ();
63         OS.ImageList_SetIconSize (handle, rect.width, rect.height);
64     }
65     set (index, image, count);
66     if (index == images.length) {
67         Image [] newImages = new Image [images.length + 4];
68         System.arraycopy (images, 0, newImages, 0, images.length);
69         images = newImages;
70     }
71     images [index] = image;
72     return index;
73 }
74
75 public int addRef() {
76     return ++refCount;
77 }
78
79 int copyBitmap (int hImage, int width, int height) {
80     BITMAP bm = new BITMAP ();
81     OS.GetObject (hImage, BITMAP.sizeof, bm);
82     int hDC = OS.GetDC (0);
83     int hdc1 = OS.CreateCompatibleDC (hDC);
84     OS.SelectObject (hdc1, hImage);
85     int hdc2 = OS.CreateCompatibleDC (hDC);
86     /*
87     * Feature in Windows. If a bitmap has a 32-bit depth and any
88     * pixel has an alpha value different than zero, common controls
89     * version 6.0 assumes that the bitmap should be alpha blended.
90     * AlphaBlend() composes the alpha channel of a destination 32-bit
91     * depth image with the alpha channel of the source image. This
92     * may cause opaque images to draw transparently. The fix is
93     * remove the alpha channel of opaque images by down sampling
94     * it to 24-bit depth.
95     */

96     int hBitmap;
97     if (bm.bmBitsPixel == 32 && OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
98         BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
99         bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
100         bmiHeader.biWidth = width;
101         bmiHeader.biHeight = -height;
102         bmiHeader.biPlanes = 1;
103         bmiHeader.biBitCount = (short)24;
104         if (OS.IsWinCE) bmiHeader.biCompression = OS.BI_BITFIELDS;
105         else bmiHeader.biCompression = OS.BI_RGB;
106         byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + (OS.IsWinCE ? 12 : 0)];
107         OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
108         /* Set the rgb colors into the bitmap info */
109         if (OS.IsWinCE) {
110             int redMask = 0xFF00;
111             int greenMask = 0xFF0000;
112             int blueMask = 0xFF000000;
113             /* big endian */
114             int offset = BITMAPINFOHEADER.sizeof;
115             bmi[offset] = (byte)((redMask & 0xFF000000) >> 24);
116             bmi[offset + 1] = (byte)((redMask & 0xFF0000) >> 16);
117             bmi[offset + 2] = (byte)((redMask & 0xFF00) >> 8);
118             bmi[offset + 3] = (byte)((redMask & 0xFF) >> 0);
119             bmi[offset + 4] = (byte)((greenMask & 0xFF000000) >> 24);
120             bmi[offset + 5] = (byte)((greenMask & 0xFF0000) >> 16);
121             bmi[offset + 6] = (byte)((greenMask & 0xFF00) >> 8);
122             bmi[offset + 7] = (byte)((greenMask & 0xFF) >> 0);
123             bmi[offset + 8] = (byte)((blueMask & 0xFF000000) >> 24);
124             bmi[offset + 9] = (byte)((blueMask & 0xFF0000) >> 16);
125             bmi[offset + 10] = (byte)((blueMask & 0xFF00) >> 8);
126             bmi[offset + 11] = (byte)((blueMask & 0xFF) >> 0);
127         }
128         int[] pBits = new int[1];
129         hBitmap = OS.CreateDIBSection(0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
130     } else {
131         hBitmap = OS.CreateCompatibleBitmap (hDC, width, height);
132     }
133     OS.SelectObject (hdc2, hBitmap);
134     if (width != bm.bmWidth || height != bm.bmHeight) {
135         if (!OS.IsWinCE) OS.SetStretchBltMode(hdc2, OS.COLORONCOLOR);
136         OS.StretchBlt (hdc2, 0, 0, width, height, hdc1, 0, 0, bm.bmWidth, bm.bmHeight, OS.SRCCOPY);
137     } else {
138         OS.BitBlt (hdc2, 0, 0, width, height, hdc1, 0, 0, OS.SRCCOPY);
139     }
140     OS.DeleteDC (hdc1);
141     OS.DeleteDC (hdc2);
142     OS.ReleaseDC (0, hDC);
143     return hBitmap;
144 }
145
146 int copyIcon (int hImage, int width, int height) {
147     if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
148     int hIcon = OS.CopyImage (hImage, OS.IMAGE_ICON, width, height, 0);
149     return hIcon != 0 ? hIcon : hImage;
150 }
151
152 int copyWithAlpha (int hBitmap, int background, byte[] alphaData, int destWidth, int destHeight) {
153     BITMAP bm = new BITMAP ();
154     OS.GetObject (hBitmap, BITMAP.sizeof, bm);
155     int srcWidth = bm.bmWidth;
156     int srcHeight = bm.bmHeight;
157     
158     /* Create resources */
159     int hdc = OS.GetDC (0);
160     int srcHdc = OS.CreateCompatibleDC (hdc);
161     int oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
162     int memHdc = OS.CreateCompatibleDC (hdc);
163     BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
164     bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
165     bmiHeader.biWidth = srcWidth;
166     bmiHeader.biHeight = -srcHeight;
167     bmiHeader.biPlanes = 1;
168     bmiHeader.biBitCount = 32;
169     bmiHeader.biCompression = OS.BI_RGB;
170     byte [] bmi = new byte[BITMAPINFOHEADER.sizeof];
171     OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
172     int [] pBits = new int [1];
173     int memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
174     if (memDib == 0) SWT.error (SWT.ERROR_NO_HANDLES);
175     int oldMemBitmap = OS.SelectObject (memHdc, memDib);
176
177     BITMAP dibBM = new BITMAP ();
178     OS.GetObject (memDib, BITMAP.sizeof, dibBM);
179     int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
180
181     /* Get the foreground pixels */
182     OS.BitBlt (memHdc, 0, 0, srcWidth, srcHeight, srcHdc, 0, 0, OS.SRCCOPY);
183     byte[] srcData = new byte [sizeInBytes];
184     OS.MoveMemory (srcData, dibBM.bmBits, sizeInBytes);
185     
186     /* Merge the alpha channel in place */
187     if (alphaData != null) {
188         int spinc = dibBM.bmWidthBytes - srcWidth * 4;
189         int ap = 0, sp = 3;
190         for (int y = 0; y < srcHeight; ++y) {
191             for (int x = 0; x < srcWidth; ++x) {
192                 srcData [sp] = alphaData [ap++];
193                 sp += 4;
194             }
195             sp += spinc;
196         }
197     } else {
198         byte transRed = (byte)(background & 0xFF);
199         byte transGreen = (byte)((background >> 8) & 0xFF);
200         byte transBlue = (byte)((background >> 16) & 0xFF);
201         final int spinc = dibBM.bmWidthBytes - srcWidth * 4;
202         int sp = 3;
203         for (int y = 0; y < srcHeight; ++y) {
204             for (int x = 0; x < srcWidth; ++x) {
205                 srcData [sp] = (srcData[sp-1] == transRed && srcData[sp-2] == transGreen && srcData[sp-3] == transBlue) ? 0 : (byte)255;
206                 sp += 4;
207             }
208             sp += spinc;
209         }
210     }
211     OS.MoveMemory (dibBM.bmBits, srcData, sizeInBytes);
212     
213     /* Stretch and free resources */
214     if (srcWidth != destWidth || srcHeight != destHeight) {
215         BITMAPINFOHEADER bmiHeader2 = new BITMAPINFOHEADER ();
216         bmiHeader2.biSize = BITMAPINFOHEADER.sizeof;
217         bmiHeader2.biWidth = destWidth;
218         bmiHeader2.biHeight = -destHeight;
219         bmiHeader2.biPlanes = 1;
220         bmiHeader2.biBitCount = 32;
221         bmiHeader2.biCompression = OS.BI_RGB;
222         byte [] bmi2 = new byte[BITMAPINFOHEADER.sizeof];
223         OS.MoveMemory (bmi2, bmiHeader2, BITMAPINFOHEADER.sizeof);
224         int [] pBits2 = new int [1];
225         int memDib2 = OS.CreateDIBSection (0, bmi2, OS.DIB_RGB_COLORS, pBits2, 0, 0);
226         int memHdc2 = OS.CreateCompatibleDC (hdc);
227         int oldMemBitmap2 = OS.SelectObject (memHdc2, memDib2);
228         if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc2, OS.COLORONCOLOR);
229         OS.StretchBlt (memHdc2, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
230         OS.SelectObject (memHdc2, oldMemBitmap2);
231         OS.DeleteDC (memHdc2);
232         OS.SelectObject (memHdc, oldMemBitmap);
233         OS.DeleteDC (memHdc);
234         OS.DeleteObject (memDib);
235         memDib = memDib2;
236     } else {
237         OS.SelectObject (memHdc, oldMemBitmap);
238         OS.DeleteDC (memHdc);
239     }
240     OS.SelectObject (srcHdc, oldSrcBitmap);
241     OS.DeleteDC (srcHdc);
242     OS.ReleaseDC (0, hdc);
243     return memDib;
244 }
245
246 int createMaskFromAlpha (ImageData data, int destWidth, int destHeight) {
247     int srcWidth = data.width;
248     int srcHeight = data.height;
249     ImageData mask = ImageData.internal_new (srcWidth, srcHeight, 1,
250             new PaletteData(new RGB [] {new RGB (0, 0, 0), new RGB (0xff, 0xff, 0xff)}),
251             2, null, 1, null, null, -1, -1, -1, 0, 0, 0, 0);
252     int ap = 0;
253     for (int y = 0; y < mask.height; y++) {
254         for (int x = 0; x < mask.width; x++) {
255             mask.setPixel (x, y, (data.alphaData [ap++] & 0xff) <= 127 ? 1 : 0);
256         }
257     }
258     int hMask = OS.CreateBitmap (srcWidth, srcHeight, 1, 1, mask.data);
259     if (srcWidth != destWidth || srcHeight != destHeight) {
260         int hdc = OS.GetDC (0);
261         int hdc1 = OS.CreateCompatibleDC (hdc);
262         OS.SelectObject (hdc1, hMask);
263         int hdc2 = OS.CreateCompatibleDC (hdc);
264         int hMask2 = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
265         OS.SelectObject (hdc2, hMask2);
266         if (!OS.IsWinCE) OS.SetStretchBltMode(hdc2, OS.COLORONCOLOR);
267         OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
268         OS.DeleteDC (hdc1);
269         OS.DeleteDC (hdc2);
270         OS.ReleaseDC (0, hdc);
271         OS.DeleteObject(hMask);
272         hMask = hMask2;
273     }
274     return hMask;
275 }
276
277 int createMask (int hBitmap, int destWidth, int destHeight, int background, int transparentPixel) {
278     BITMAP bm = new BITMAP ();
279     OS.GetObject (hBitmap, BITMAP.sizeof, bm);
280     int srcWidth = bm.bmWidth;
281     int srcHeight = bm.bmHeight;
282     int hMask = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
283     int hDC = OS.GetDC (0);
284     int hdc1 = OS.CreateCompatibleDC (hDC);
285     if (background != -1) {
286         OS.SelectObject (hdc1, hBitmap);
287         
288         /*
289         * If the image has a palette with multiple entries having
290         * the same color and one of those entries is the transparentPixel,
291         * only the first entry becomes transparent. To avoid this
292         * problem, temporarily change the image palette to a palette
293         * where the transparentPixel is white and everything else is
294         * black.
295         */

296         boolean isDib = bm.bmBits != 0;
297         byte[] originalColors = null;
298         if (!OS.IsWinCE && transparentPixel != -1 && isDib && bm.bmBitsPixel <= 8) {
299             int maxColors = 1 << bm.bmBitsPixel;
300             byte[] oldColors = new byte[maxColors * 4];
301             OS.GetDIBColorTable(hdc1, 0, maxColors, oldColors);
302             int offset = transparentPixel * 4;
303             byte[] newColors = new byte[oldColors.length];
304             newColors[offset] = (byte)0xFF;
305             newColors[offset+1] = (byte)0xFF;
306             newColors[offset+2] = (byte)0xFF;
307             OS.SetDIBColorTable(hdc1, 0, maxColors, newColors);
308             originalColors = oldColors;
309             OS.SetBkColor (hdc1, 0xFFFFFF);
310         } else {
311             OS.SetBkColor (hdc1, background);
312         }
313         
314         int hdc2 = OS.CreateCompatibleDC (hDC);
315         OS.SelectObject (hdc2, hMask);
316         if (destWidth != srcWidth || destHeight != srcHeight) {
317             if (!OS.IsWinCE) OS.SetStretchBltMode (hdc2, OS.COLORONCOLOR);
318             OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
319         } else {
320             OS.BitBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, OS.SRCCOPY);
321         }
322         OS.DeleteDC (hdc2);
323
324         /* Put back the original palette */
325         if (originalColors != null) OS.SetDIBColorTable(hdc1, 0, 1 << bm.bmBitsPixel, originalColors);
326     } else {
327         int hOldBitmap = OS.SelectObject (hdc1, hMask);
328         OS.PatBlt (hdc1, 0, 0, destWidth, destHeight, OS.BLACKNESS);
329         OS.SelectObject (hdc1, hOldBitmap);
330     }
331     OS.ReleaseDC (0, hDC);
332     OS.DeleteDC (hdc1);
333     return hMask;
334 }
335
336 public void dispose () {
337     if (handle != 0) OS.ImageList_Destroy (handle);
338     handle = 0;
339     images = null;
340 }
341
342 public Image get (int index) {
343     return images [index];
344 }
345
346 public int getStyle () {
347     return style;
348 }
349
350 public int getHandle () {
351     return handle;
352 }
353
354 public Point getImageSize() {
355     int [] cx = new int [1], cy = new int [1];
356     OS.ImageList_GetIconSize (handle, cx, cy);
357     return new Point (cx [0], cy [0]);
358 }
359
360 public int indexOf (Image image) {
361     int count = OS.ImageList_GetImageCount (handle);
362     for (int i=0; i<count; i++) {
363         if (images [i] != null) {
364             if (images [i].isDisposed ()) images [i] = null;
365             if (images [i] != null && images [i].equals (image)) return i;
366         }
367     }
368     return -1;
369 }
370
371 public void put (int index, Image image) {
372     int count = OS.ImageList_GetImageCount (handle);
373     if (!(0 <= index && index < count)) return;
374     if (image != null) set(index, image, count);
375     images [index] = image;
376 }
377
378 public void remove (int index) {
379     int count = OS.ImageList_GetImageCount (handle);
380     if (!(0 <= index && index < count)) return;
381     OS.ImageList_Remove (handle, index);
382     System.arraycopy (images, index + 1, images, index, --count - index);
383     images [index] = null;
384 }
385
386 public int removeRef() {
387     return --refCount;
388 }
389
390 void set (int index, Image image, int count) {
391     int hImage = image.handle;
392     int [] cx = new int [1], cy = new int [1];
393     OS.ImageList_GetIconSize (handle, cx, cy);
394     switch (image.type) {
395         case SWT.BITMAP: {
396             /*
397             * Note that the image size has to match the image list icon size.
398             */

399             int hBitmap = 0, hMask = 0;
400             ImageData data = image.getImageData ();
401             switch (data.getTransparencyType ()) {
402                 case SWT.TRANSPARENCY_ALPHA:
403                     if (OS.COMCTL32_MAJOR >= 6) {
404                         hBitmap = copyWithAlpha (hImage, -1, data.alphaData, cx [0], cy [0]);
405                     } else {
406                         hBitmap = copyBitmap (hImage, cx [0], cy [0]);
407                         hMask = createMaskFromAlpha (data, cx [0], cy [0]);
408                     }
409                     break;
410                 case SWT.TRANSPARENCY_PIXEL:
411                     int background = -1;
412                     Color color = image.getBackground ();
413                     if (color != null) background = color.handle;
414                     hBitmap = copyBitmap (hImage, cx [0], cy [0]);
415                     hMask = createMask (hImage, cx [0], cy [0], background, data.transparentPixel);
416                     break;
417                 case SWT.TRANSPARENCY_NONE:
418                 default:
419                     hBitmap = copyBitmap (hImage, cx [0], cy [0]);
420                     if (index != count) hMask = createMask (hImage, cx [0], cy [0], -1, -1);
421                     break;
422             }
423             if (index == count) {
424                 OS.ImageList_Add (handle, hBitmap, hMask);
425             } else {
426                 /* Note that the mask must always be replaced even for TRANSPARENCY_NONE */
427                 OS.ImageList_Replace (handle, index, hBitmap, hMask);
428             }
429             if (hMask != 0) OS.DeleteObject (hMask);
430             if (hBitmap != hImage) OS.DeleteObject (hBitmap);
431             break;
432         }
433         case SWT.ICON: {
434             if (OS.IsWinCE) {
435                 OS.ImageList_ReplaceIcon (handle, index == count ? -1 : index, hImage);
436             } else {
437                 int hIcon = copyIcon (hImage, cx [0], cy [0]);
438                 OS.ImageList_ReplaceIcon (handle, index == count ? -1 : index, hIcon);
439                 OS.DestroyIcon (hIcon);
440             }
441             break;
442         }
443     }
444 }
445
446 public int size () {
447     int result = 0;
448     int count = OS.ImageList_GetImageCount (handle);
449     for (int i=0; i<count; i++) {
450         if (images [i] != null) {
451             if (images [i].isDisposed ()) images [i] = null;
452             if (images [i] != null) result++;
453         }
454     }
455     return result;
456 }
457
458 }
459
Popular Tags