From e353b1ae88fef63bc583ba9c28ee9c9f3837faab Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Wed, 25 Sep 2024 10:34:57 +0200 Subject: [PATCH] Image metadata refactoring for win32 This contribution encapsulates the metadata of the image in an innerclass ImageMetadata which is used to create a hashmap of zoom level to imageMetadata object inside an image object, making it straight forward to obtain any metadata information from an image for a zoom level. contributes to #62 and #127 --- .../win32/org/eclipse/swt/graphics/Image.java | 853 +++++++++--------- .../org/eclipse/swt/widgets/Decorations.java | 4 +- .../org/eclipse/swt/widgets/Display.java | 6 +- .../org/eclipse/swt/widgets/TaskBar.java | 9 +- .../org/eclipse/swt/widgets/TaskItem.java | 2 +- .../org/eclipse/swt/widgets/TrayItem.java | 2 +- 6 files changed, 429 insertions(+), 447 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java index afed0488e7e..12ea24fcd28 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java @@ -89,20 +89,6 @@ public final class Image extends Resource implements Drawable { */ public int type; - /** - * the handle to the OS image resource - * (Warning: This field is platform dependent) - *

- * IMPORTANT: This field is not part of the SWT - * public API. It is marked public only so that it can be shared - * within the packages provided by SWT. It is not available on all - * platforms and should never be accessed from application code. - *

- * - * @noreference This field is not intended to be referenced by clients. - */ - public long handle; - /** * specifies the transparent pixel */ @@ -113,12 +99,6 @@ public final class Image extends Resource implements Drawable { */ GC memGC; - /** - * Base image data at given zoom in % of the standard resolution. It will be used for - * scaled variants of this image - */ - private ElementAtZoom dataAtBaseZoom; - /** * ImageFileNameProvider to provide file names at various Zoom levels */ @@ -141,22 +121,13 @@ public final class Image extends Resource implements Drawable { */ private int initialNativeZoom = 100; - /** - * width of the image - */ - int width = -1; - - /** - * height of the image - */ - int height = -1; - /** * specifies the default scanline padding */ static final int DEFAULT_SCANLINE_PAD = 4; - private HashMap zoomLevelToHandle = new HashMap<>(); +// private HashMap zoomLevelToHandle = new HashMap<>(); + private HashMap zoomLevelToImageMetadata = new HashMap<>(); /** * Prevents uninitialized instances from being created outside the package. @@ -250,6 +221,7 @@ public Image(Device device, int width, int height) { public Image(Device device, Image srcImage, int flag) { super(device); device = this.device; + ImageMetadata imageMetadata; if (srcImage == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); Rectangle rect = srcImage.getBoundsInPixels(); @@ -258,7 +230,7 @@ public Image(Device device, Image srcImage, int flag) { this.imageFileNameProvider = srcImage.imageFileNameProvider; this.styleFlag = srcImage.styleFlag | flag; initialNativeZoom = srcImage.initialNativeZoom; - this.dataAtBaseZoom = srcImage.dataAtBaseZoom; + long srcImageHandle = win32_getHandle(srcImage, getZoom()); switch (flag) { case SWT.IMAGE_COPY: { switch (type) { @@ -269,12 +241,13 @@ public Image(Device device, Image srcImage, int flag) { /* Copy the bitmap */ long hdcSource = OS.CreateCompatibleDC(hDC); long hdcDest = OS.CreateCompatibleDC(hDC); - long hOldSrc = OS.SelectObject(hdcSource, srcImage.handle); + long hOldSrc = OS.SelectObject(hdcSource, srcImageHandle); BITMAP bm = new BITMAP(); - OS.GetObject(srcImage.handle, BITMAP.sizeof, bm); - setHandleForZoomLevel(OS.CreateCompatibleBitmap(hdcSource, rect.width, bm.bmBits != 0 ? -rect.height : rect.height), this.getZoom()); - if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES); - long hOldDest = OS.SelectObject(hdcDest, handle); + OS.GetObject(srcImageHandle, BITMAP.sizeof, bm); + imageMetadata = new ImageMetadata(OS.CreateCompatibleBitmap(hdcSource, rect.width, bm.bmBits != 0 ? -rect.height : rect.height), getZoom()); + setImageMetadataForHandle(imageMetadata, getZoom()); + if (imageMetadata.handle == 0) SWT.error(SWT.ERROR_NO_HANDLES); + long hOldDest = OS.SelectObject(hdcDest, imageMetadata.handle); OS.BitBlt(hdcDest, 0, 0, rect.width, rect.height, hdcSource, 0, 0, OS.SRCCOPY); OS.SelectObject(hdcSource, hOldSrc); OS.SelectObject(hdcDest, hOldDest); @@ -287,8 +260,9 @@ public Image(Device device, Image srcImage, int flag) { transparentPixel = srcImage.transparentPixel; break; case SWT.ICON: - setHandleForZoomLevel(OS.CopyImage(srcImage.handle, OS.IMAGE_ICON, rect.width, rect.height, 0), getZoom()); - if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES); + imageMetadata = new ImageMetadata(OS.CopyImage(srcImageHandle, OS.IMAGE_ICON, rect.width, rect.height, 0), getZoom()); + setImageMetadataForHandle(imageMetadata, getZoom()); + if (imageMetadata.handle == 0) SWT.error(SWT.ERROR_NO_HANDLES); break; default: SWT.error(SWT.ERROR_INVALID_IMAGE); @@ -384,8 +358,7 @@ public Image(Device device, ImageData data) { super(device); if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); initialNativeZoom = DPIUtil.getNativeDeviceZoom(); - this.dataAtBaseZoom = new ElementAtZoom<>(data, 100); - data = DPIUtil.autoScaleUp(device, this.dataAtBaseZoom); + data = DPIUtil.autoScaleUp(device, new ElementAtZoom<>(data, 100)); init(data, getZoom()); init(); } @@ -428,7 +401,6 @@ public Image(Device device, ImageData source, ImageData mask) { SWT.error(SWT.ERROR_INVALID_ARGUMENT); } initialNativeZoom = DPIUtil.getNativeDeviceZoom(); - this.dataAtBaseZoom = new ElementAtZoom<>(applyMask(source, ImageData.convertMask(mask)), 100); source = DPIUtil.autoScaleUp(device, source); mask = DPIUtil.autoScaleUp(device, mask); mask = ImageData.convertMask(mask); @@ -492,8 +464,7 @@ public Image(Device device, ImageData source, ImageData mask) { public Image (Device device, InputStream stream) { super(device); initialNativeZoom = DPIUtil.getNativeDeviceZoom(); - this.dataAtBaseZoom = new ElementAtZoom<>(new ImageData (stream), 100); - ImageData data = DPIUtil.autoScaleUp(device, this.dataAtBaseZoom); + ImageData data = DPIUtil.autoScaleUp(device, new ElementAtZoom<>(new ImageData (stream), 100)); init(data, getZoom()); init(); } @@ -534,8 +505,7 @@ public Image (Device device, String filename) { super(device); if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); initialNativeZoom = DPIUtil.getNativeDeviceZoom(); - this.dataAtBaseZoom = new ElementAtZoom<>(new ImageData (filename), 100); - ImageData data = DPIUtil.autoScaleUp(device, this.dataAtBaseZoom); + ImageData data = DPIUtil.autoScaleUp(device, new ElementAtZoom<>(new ImageData (filename), 100)); init(data, getZoom()); init(); } @@ -575,11 +545,11 @@ public Image(Device device, ImageFileNameProvider imageFileNameProvider) { initialNativeZoom = DPIUtil.getNativeDeviceZoom(); ElementAtZoom fileName = DPIUtil.validateAndGetImagePathAtZoom (imageFileNameProvider, getZoom()); if (fileName.zoom() == getZoom()) { - long handle = initNative (fileName.element(), getZoom()); - if (handle == 0) { + ImageMetadata imageMetadata = initNative (fileName.element(), getZoom()); + if (imageMetadata == null) { init(new ImageData (fileName.element()), getZoom()); } else { - setHandleForZoomLevel(handle, getZoom()); + setImageMetadataForHandle(imageMetadata, getZoom()); } } else { ImageData resizedData = DPIUtil.autoScaleImageData (device, new ImageData (fileName.element()), fileName.zoom()); @@ -770,6 +740,39 @@ private ImageData applyGrayImageData(ImageData data, int pHeight, int pWidth) { return newData; } +private ImageMetadata getImageMetadata(int zoom) { + if(zoomLevelToImageMetadata.get(zoom) != null) { + return zoomLevelToImageMetadata.get(zoom); + } + + if (imageFileNameProvider != null) { + ElementAtZoom imageCandidate = DPIUtil.validateAndGetImagePathAtZoom (imageFileNameProvider, zoom); + ImageData imageData = new ImageData (imageCandidate.element()); + if (imageCandidate.zoom() == zoom) { + /* Release current native resources */ + ImageMetadata imageMetadata = initNative(imageCandidate.element(), zoom); + if (imageMetadata == null) init(imageData, zoom); + init(); + } else { + ImageData resizedData = DPIUtil.scaleImageData(device, imageData, zoom, imageCandidate.zoom()); + ImageData newData = adaptImageDataIfDisabledOrGray(resizedData); + init(newData, zoom); + } + } else if (imageDataProvider != null) { + ElementAtZoom imageCandidate = DPIUtil.validateAndGetImageDataAtZoom (imageDataProvider, zoom); + ImageData resizedData = DPIUtil.scaleImageData (device, imageCandidate.element(), zoom, imageCandidate.zoom()); + ImageData newData = adaptImageDataIfDisabledOrGray(resizedData); + init(newData, zoom); + init(); + } else { + ImageData resizedData = getImageData(zoom); + ImageData newData = adaptImageDataIfDisabledOrGray(resizedData); + init(newData, zoom); + init(); + } + return zoomLevelToImageMetadata.get(zoom); +} + /** * IMPORTANT: This method is not part of the public @@ -787,50 +790,18 @@ private ImageData applyGrayImageData(ImageData data, int pHeight, int pWidth) { * * @noreference This method is not intended to be referenced by clients. */ -public static Long win32_getHandle (Image image, int zoom) { +public static long win32_getHandle (Image image, int zoom) { if(image.isDisposed()) { - return image.handle; - } - if(image.zoomLevelToHandle.get(zoom) != null) { - return image.zoomLevelToHandle.get(zoom); - } - - if (image.imageFileNameProvider != null) { - ElementAtZoom imageCandidate = DPIUtil.validateAndGetImagePathAtZoom (image.imageFileNameProvider, zoom); - ImageData imageData = new ImageData (imageCandidate.element()); - if (imageCandidate.zoom() == zoom) { - /* Release current native resources */ - long handle = image.initNative(imageCandidate.element(), zoom); - if (handle == 0) image.init(imageData, zoom); - image.init(); - } else { - ImageData resizedData = DPIUtil.scaleImageData(image.device, imageData, zoom, imageCandidate.zoom()); - ImageData newData = image.adaptImageDataIfDisabledOrGray(resizedData); - image.init(newData, zoom); - } - } else if (image.imageDataProvider != null) { - ElementAtZoom imageCandidate = DPIUtil.validateAndGetImageDataAtZoom (image.imageDataProvider, zoom); - ImageData resizedData = DPIUtil.scaleImageData (image.device, imageCandidate.element(), zoom, imageCandidate.zoom()); - ImageData newData = image.adaptImageDataIfDisabledOrGray(resizedData); - image.init(newData, zoom); - image.init(); - } else { - if (image.dataAtBaseZoom == null && image.memGC == null) { - // Cache data at base zoom before refresh. - image.dataAtBaseZoom = new ElementAtZoom<>(image.getImageData(image.getZoom()), image.getZoom()); - } - if (image.dataAtBaseZoom != null) { - ImageData resizedData = image.getImageData(zoom); - ImageData newData = image.adaptImageDataIfDisabledOrGray(resizedData); - image.init(newData, zoom); - image.init(); - } + return 0L; } - return image.zoomLevelToHandle.get(zoom); + return image.getImageMetadata(zoom).handle; } -long initNative(String filename, int zoom) { +ImageMetadata initNative(String filename, int zoom) { + ImageMetadata imageMetadata = null; long handle = 0; + int width = -1; + int height = -1; device.checkGDIP(); boolean gdip = true; /* @@ -859,10 +830,12 @@ long initNative(String filename, int zoom) { long[] hicon = new long[1]; status = Gdip.Bitmap_GetHICON(bitmap, hicon); handle = hicon[0]; + imageMetadata = new ImageMetadata(handle, zoom); + setImageMetadataForHandle(imageMetadata, zoom); } else { this.type = SWT.BITMAP; - int width = Gdip.Image_GetWidth(bitmap); - int height = Gdip.Image_GetHeight(bitmap); + width = Gdip.Image_GetWidth(bitmap); + height = Gdip.Image_GetHeight(bitmap); int pixelFormat = Gdip.Image_GetPixelFormat(bitmap); switch (pixelFormat) { case Gdip.PixelFormat16bppRGB555: @@ -907,7 +880,8 @@ long initNative(String filename, int zoom) { OS.SelectObject(srcHDC, oldSrcBitmap); OS.DeleteDC(srcHDC); device.internal_dispose_GC(hDC, null); - zoomLevelToHandle.put(zoom, handle); + imageMetadata = new ImageMetadata(handle, zoom); + setImageMetadataForHandle(imageMetadata, zoom); } else { long lockedBitmapData = Gdip.BitmapData_new(); if (lockedBitmapData != 0) { @@ -983,7 +957,8 @@ long initNative(String filename, int zoom) { ImageData newData = adaptImageDataIfDisabledOrGray(img); init(newData, zoom); - handle = zoomLevelToHandle.get(zoom); + imageMetadata = zoomLevelToImageMetadata.get(zoom); + handle = imageMetadata.handle; } Gdip.Bitmap_UnlockBits(bitmap, lockedBitmapData); } else { @@ -997,10 +972,11 @@ long initNative(String filename, int zoom) { Gdip.Bitmap_delete(bitmap); if (status == 0) { if (handle == 0) SWT.error(error); + if (imageMetadata == null) SWT.error(error); } } } - return handle; + return imageMetadata; } long [] createGdipImage() { @@ -1185,15 +1161,14 @@ void destroy () { static int count = 0; private void destroyHandle () { - for (Long handle : zoomLevelToHandle.values()) { + for (ImageMetadata imageMetadata : zoomLevelToImageMetadata.values()) { if (type == SWT.ICON) { - OS.DestroyIcon (handle); + OS.DestroyIcon (imageMetadata.handle); } else { - OS.DeleteObject (handle); + OS.DeleteObject (imageMetadata.handle); } } - zoomLevelToHandle.clear(); - handle = 0; + zoomLevelToImageMetadata.clear(); } /** @@ -1217,7 +1192,7 @@ public boolean equals (Object object) { } else if (imageFileNameProvider != null && image.imageFileNameProvider != null) { return (styleFlag == image.styleFlag) && imageFileNameProvider.equals (image.imageFileNameProvider); } else { - return handle == image.handle; + return win32_getHandle(this, getZoom()) == win32_getHandle(image, getZoom()); } } @@ -1245,6 +1220,7 @@ public Color getBackground() { /* Get the HDC for the device */ long hDC = device.internal_new_GC(null); + long handle = win32_getHandle(this, getZoom()); /* Compute the background color */ BITMAP bm = new BITMAP(); @@ -1306,12 +1282,8 @@ public Rectangle getBounds() { Rectangle getBounds(int zoom) { if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); - // Read the bounds in pixels from native layer. - Rectangle bounds = getBoundsInPixelsFromNative(); - if (bounds != null && zoom != getZoom()) { - bounds = DPIUtil.scaleBounds(bounds, zoom, getZoom()); - } - return bounds; + ImageMetadata imageMetadata = getImageMetadata(zoom); + return new Rectangle(0, 0, imageMetadata.width, imageMetadata.height); } /** @@ -1331,34 +1303,7 @@ Rectangle getBounds(int zoom) { */ @Deprecated public Rectangle getBoundsInPixels() { - if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); - if (width != -1 && height != -1) { - return new Rectangle(0, 0, width, height); - } - return getBoundsInPixelsFromNative(); -} - -private Rectangle getBoundsInPixelsFromNative() { - switch (type) { - case SWT.BITMAP: - BITMAP bm = new BITMAP(); - OS.GetObject(handle, BITMAP.sizeof, bm); - return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight); - case SWT.ICON: - ICONINFO info = new ICONINFO(); - OS.GetIconInfo(handle, info); - long hBitmap = info.hbmColor; - if (hBitmap == 0) hBitmap = info.hbmMask; - bm = new BITMAP(); - OS.GetObject(hBitmap, BITMAP.sizeof, bm); - if (hBitmap == info.hbmMask) bm.bmHeight /= 2; - if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor); - if (info.hbmMask != 0) OS.DeleteObject(info.hbmMask); - return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight); - default: - SWT.error(SWT.ERROR_INVALID_IMAGE); - return null; - } + return getBounds(getZoom()); } /** @@ -1428,15 +1373,7 @@ public ImageData getImageData (int zoom) { if (memGC != null) { return getImageDataAtCurrentZoom(); } - if (this.dataAtBaseZoom == null) { - // Cache data at base zoom before resizing it. - this.dataAtBaseZoom = new ElementAtZoom<>(getImageData(currentZoom), currentZoom); - } - if (this.dataAtBaseZoom != null) { - return DPIUtil.scaleImageData(device, this.dataAtBaseZoom, zoom); - } else { - return DPIUtil.scaleImageData (device, getImageDataAtCurrentZoom (), zoom, currentZoom); - } + return DPIUtil.scaleImageData (device, getImageMetadata(currentZoom).getImageData(), zoom, currentZoom); } /** @@ -1460,279 +1397,7 @@ public ImageData getImageData (int zoom) { */ @Deprecated public ImageData getImageDataAtCurrentZoom() { - if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); - BITMAP bm; - int depth, width, height; - switch (type) { - case SWT.ICON: { - ICONINFO info = new ICONINFO(); - OS.GetIconInfo(handle, info); - /* Get the basic BITMAP information */ - long hBitmap = info.hbmColor; - if (hBitmap == 0) hBitmap = info.hbmMask; - bm = new BITMAP(); - OS.GetObject(hBitmap, BITMAP.sizeof, bm); - depth = bm.bmPlanes * bm.bmBitsPixel; - width = bm.bmWidth; - if (hBitmap == info.hbmMask) bm.bmHeight /= 2; - height = bm.bmHeight; - int numColors = 0; - if (depth <= 8) numColors = 1 << depth; - /* Create the BITMAPINFO */ - BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); - bmiHeader.biSize = BITMAPINFOHEADER.sizeof; - bmiHeader.biWidth = width; - bmiHeader.biHeight = -height; - bmiHeader.biPlanes = 1; - bmiHeader.biBitCount = (short)depth; - bmiHeader.biCompression = OS.BI_RGB; - byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4]; - OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); - - /* Get the HDC for the device */ - long hDC = device.internal_new_GC(null); - - /* Create the DC and select the bitmap */ - long hBitmapDC = OS.CreateCompatibleDC(hDC); - long hOldBitmap = OS.SelectObject(hBitmapDC, hBitmap); - /* Find the size of the image and allocate data */ - int imageSize; - /* Call with null lpBits to get the image size */ - OS.GetDIBits(hBitmapDC, hBitmap, 0, height, null, bmi, OS.DIB_RGB_COLORS); - OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); - imageSize = bmiHeader.biSizeImage; - byte[] data = new byte[imageSize]; - /* Get the bitmap data */ - OS.GetDIBits(hBitmapDC, hBitmap, 0, height, data, bmi, OS.DIB_RGB_COLORS); - /* Calculate the palette */ - PaletteData palette = null; - if (depth <= 8) { - RGB[] rgbs = new RGB[numColors]; - int srcIndex = 40; - for (int i = 0; i < numColors; i++) { - rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF); - srcIndex += 4; - } - palette = new PaletteData(rgbs); - } else if (depth == 16) { - palette = new PaletteData(0x7C00, 0x3E0, 0x1F); - } else if (depth == 24) { - palette = new PaletteData(0xFF, 0xFF00, 0xFF0000); - } else if (depth == 32) { - palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); - } else { - SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); - } - - /* Do the mask */ - byte [] maskData = null; - byte [] alphaData = null; - if (info.hbmColor == 0) { - /* Do the bottom half of the mask */ - maskData = new byte[imageSize]; - OS.GetDIBits(hBitmapDC, hBitmap, height, height, maskData, bmi, OS.DIB_RGB_COLORS); - } else { - /* Do the entire mask */ - /* Create the BITMAPINFO */ - bmiHeader = new BITMAPINFOHEADER(); - bmiHeader.biSize = BITMAPINFOHEADER.sizeof; - bmiHeader.biWidth = width; - bmiHeader.biHeight = -height; - bmiHeader.biPlanes = 1; - bmiHeader.biBitCount = 1; - bmiHeader.biCompression = OS.BI_RGB; - bmi = new byte[BITMAPINFOHEADER.sizeof + 8]; - OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); - - /* First color black, second color white */ - int offset = BITMAPINFOHEADER.sizeof; - bmi[offset + 4] = bmi[offset + 5] = bmi[offset + 6] = (byte)0xFF; - bmi[offset + 7] = 0; - OS.SelectObject(hBitmapDC, info.hbmMask); - /* Call with null lpBits to get the image size */ - OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, null, bmi, OS.DIB_RGB_COLORS); - OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); - imageSize = bmiHeader.biSizeImage; - maskData = new byte[imageSize]; - OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, maskData, bmi, OS.DIB_RGB_COLORS); - /* Loop to invert the mask */ - boolean hasMaskData = false; - for (int i = 0; i < maskData.length; i++) { - hasMaskData |= maskData[i] != 0; - maskData[i] ^= -1; - } - /* Make sure mask scanlinePad is 2 */ - int maskPad; - int bpl = imageSize / height; - for (maskPad = 1; maskPad < 128; maskPad++) { - int calcBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad; - if (calcBpl == bpl) break; - } - maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, 2); - // For missing mask data, see https://github.com/eclipse-platform/eclipse.platform.swt/issues/715 - if (!hasMaskData && depth == 32) { - alphaData = new byte[width * height]; - boolean hasAlphaData = false; - for (int pixelIndex = 0; pixelIndex < alphaData.length; pixelIndex++) { - alphaData[pixelIndex] = data[pixelIndex * 4 + 3]; - hasAlphaData |= alphaData[pixelIndex] != -1; - } - // In case there is alpha data, replace the empty mask data with proper alpha data - if (hasAlphaData) { - maskData = null; - } else { - alphaData = null; - } - } - } - /* Clean up */ - OS.SelectObject(hBitmapDC, hOldBitmap); - OS.DeleteDC(hBitmapDC); - - /* Release the HDC for the device */ - device.internal_dispose_GC(hDC, null); - - if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor); - if (info.hbmMask != 0) OS.DeleteObject(info.hbmMask); - /* Construct and return the ImageData */ - ImageData imageData = new ImageData(width, height, depth, palette, 4, data); - imageData.alphaData = alphaData; - imageData.maskData = maskData; - imageData.maskPad = 2; - return imageData; - } - case SWT.BITMAP: { - /* Get the basic BITMAP information */ - bm = new BITMAP(); - OS.GetObject(handle, BITMAP.sizeof, bm); - depth = bm.bmPlanes * bm.bmBitsPixel; - width = bm.bmWidth; - height = bm.bmHeight; - /* Find out whether this is a DIB or a DDB. */ - boolean isDib = (bm.bmBits != 0); - /* Get the HDC for the device */ - long hDC = device.internal_new_GC(null); - DIBSECTION dib = null; - if (isDib) { - dib = new DIBSECTION(); - OS.GetObject(handle, DIBSECTION.sizeof, dib); - } - /* Calculate number of colors */ - int numColors = 0; - if (depth <= 8) { - if (isDib) { - numColors = dib.biClrUsed; - } else { - numColors = 1 << depth; - } - } - /* Create the BITMAPINFO */ - byte[] bmi = null; - BITMAPINFOHEADER bmiHeader = null; - if (!isDib) { - bmiHeader = new BITMAPINFOHEADER(); - bmiHeader.biSize = BITMAPINFOHEADER.sizeof; - bmiHeader.biWidth = width; - bmiHeader.biHeight = -height; - bmiHeader.biPlanes = 1; - bmiHeader.biBitCount = (short)depth; - bmiHeader.biCompression = OS.BI_RGB; - bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4]; - OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); - } - - /* Create the DC and select the bitmap */ - long hBitmapDC = OS.CreateCompatibleDC(hDC); - long hOldBitmap = OS.SelectObject(hBitmapDC, handle); - /* Find the size of the image and allocate data */ - int imageSize; - if (isDib) { - imageSize = dib.biSizeImage; - } else { - /* Call with null lpBits to get the image size */ - OS.GetDIBits(hBitmapDC, handle, 0, height, null, bmi, OS.DIB_RGB_COLORS); - OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); - imageSize = bmiHeader.biSizeImage; - } - byte[] data = new byte[imageSize]; - /* Get the bitmap data */ - if (isDib) { - OS.MoveMemory(data, bm.bmBits, imageSize); - } else { - OS.GetDIBits(hBitmapDC, handle, 0, height, data, bmi, OS.DIB_RGB_COLORS); - } - /* Calculate the palette */ - PaletteData palette = null; - if (depth <= 8) { - RGB[] rgbs = new RGB[numColors]; - if (isDib) { - byte[] colors = new byte[numColors * 4]; - OS.GetDIBColorTable(hBitmapDC, 0, numColors, colors); - int colorIndex = 0; - for (int i = 0; i < rgbs.length; i++) { - rgbs[i] = new RGB(colors[colorIndex + 2] & 0xFF, colors[colorIndex + 1] & 0xFF, colors[colorIndex] & 0xFF); - colorIndex += 4; - } - } else { - int srcIndex = BITMAPINFOHEADER.sizeof; - for (int i = 0; i < numColors; i++) { - rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF); - srcIndex += 4; - } - } - palette = new PaletteData(rgbs); - } else if (depth == 16) { - palette = new PaletteData(0x7C00, 0x3E0, 0x1F); - } else if (depth == 24) { - palette = new PaletteData(0xFF, 0xFF00, 0xFF0000); - } else if (depth == 32) { - palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); - } else { - SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); - } - /* Clean up */ - OS.SelectObject(hBitmapDC, hOldBitmap); - OS.DeleteDC(hBitmapDC); - - /* Release the HDC for the device */ - device.internal_dispose_GC(hDC, null); - - /* Construct and return the ImageData */ - ImageData imageData = new ImageData(width, height, depth, palette, 4, data); - imageData.transparentPixel = this.transparentPixel; - if (depth == 32) { - byte straightData[] = new byte[imageSize]; - byte alphaData[] = new byte[width * height]; - boolean validAlpha = isDib; - for (int ap = 0, dp = 0; validAlpha && ap < alphaData.length; ap++, dp += 4) { - int b = data[dp ] & 0xFF; - int g = data[dp + 1] & 0xFF; - int r = data[dp + 2] & 0xFF; - int a = data[dp + 3] & 0xFF; - alphaData[ap] = (byte) a; - validAlpha = validAlpha && b <= a && g <= a && r <= a; - if (a != 0) { - straightData[dp ] = (byte) (((b * 0xFF) + a / 2) / a); - straightData[dp + 1] = (byte) (((g * 0xFF) + a / 2) / a); - straightData[dp + 2] = (byte) (((r * 0xFF) + a / 2) / a); - } - } - if (validAlpha) { - imageData.data = straightData; - imageData.alphaData = alphaData; - } - else { - for (int dp = 3; dp < imageSize; dp += 4) { - data[dp] = (byte) 0xFF; - } - } - } - return imageData; - } - default: - SWT.error(SWT.ERROR_INVALID_IMAGE); - return null; - } + return getImageMetadata(getZoom()).getImageData(); } /** @@ -1752,7 +1417,7 @@ public int hashCode () { } else if (imageFileNameProvider != null) { return Objects.hash(imageFileNameProvider, styleFlag, transparentPixel, getZoom()); } else { - return (int)handle; + return (int)win32_getHandle(this, getZoom()); } } @@ -1762,29 +1427,32 @@ void init(int width, int height) { } type = SWT.BITMAP; long hDC = device.internal_new_GC(null); - setHandleForZoomLevel(OS.CreateCompatibleBitmap(hDC, width, height), getZoom()); + ImageMetadata imageMetadata = new ImageMetadata(OS.CreateCompatibleBitmap(hDC, width, height), getZoom()); + setImageMetadataForHandle(imageMetadata, getZoom()); +// setHandleForZoomLevel(OS.CreateCompatibleBitmap(hDC, width, height), getZoom()); /* * Feature in Windows. CreateCompatibleBitmap() may fail * for large images. The fix is to create a DIB section * in that case. */ - if (handle == 0) { + if (imageMetadata.handle == 0) { int bits = OS.GetDeviceCaps(hDC, OS.BITSPIXEL); int planes = OS.GetDeviceCaps(hDC, OS.PLANES); int depth = bits * planes; if (depth < 16) depth = 16; if (depth > 24) depth = 24; - setHandleForZoomLevel(createDIB(width, height, depth), getZoom()); + imageMetadata = new ImageMetadata(createDIB(width, height, depth), getZoom()); + setImageMetadataForHandle(imageMetadata, getZoom()); } - if (handle != 0) { + if (imageMetadata.handle != 0) { long memDC = OS.CreateCompatibleDC(hDC); - long hOldBitmap = OS.SelectObject(memDC, handle); + long hOldBitmap = OS.SelectObject(memDC, imageMetadata.handle); OS.PatBlt(memDC, 0, 0, width, height, OS.PATCOPY); OS.SelectObject(memDC, hOldBitmap); OS.DeleteDC(memDC); } device.internal_dispose_GC(hDC, null); - if (handle == 0) { + if (imageMetadata.handle == 0) { SWT.error(SWT.ERROR_NO_HANDLES, null, device.getLastError()); } } @@ -2077,14 +1745,16 @@ else if (i.alphaData != null) { if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES); OS.DeleteObject(hBitmap); OS.DeleteObject(hMask); - image.setHandleForZoomLevel(hIcon, zoom); + ImageMetadata imageMetadata = image.new ImageMetadata(hIcon, zoom); + image.setImageMetadataForHandle(imageMetadata, zoom); image.type = SWT.ICON; } } else { if (image == null) { result = new long []{hDib}; } else { - image.setHandleForZoomLevel(hDib, zoom); + ImageMetadata imageMetadata = image.new ImageMetadata(hDib, zoom); + image.setImageMetadataForHandle(imageMetadata, zoom); image.type = SWT.BITMAP; image.transparentPixel = i.transparentPixel; } @@ -2092,12 +1762,9 @@ else if (i.alphaData != null) { return result; } -private void setHandleForZoomLevel(long handle, Integer zoom) { - if (this.handle == 0) { - this.handle = handle; // Set handle for default zoom level - } - if (zoom != null && !zoomLevelToHandle.containsKey(zoom)) { - zoomLevelToHandle.put(zoom, handle); +private void setImageMetadataForHandle(ImageMetadata imageMetadata, Integer zoom) { + if (zoom != null && !zoomLevelToImageMetadata.containsKey(zoom)) { + zoomLevelToImageMetadata.put(zoom, imageMetadata); } } @@ -2203,7 +1870,7 @@ void init(ImageData i, Integer zoom) { */ @Override public long internal_new_GC (GCData data) { - if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); /* * Create a new GC that can draw into the image. * Only supported for bitmaps. @@ -2266,7 +1933,7 @@ public void internal_dispose_GC (long hDC, GCData data) { */ @Override public boolean isDisposed() { - return handle == 0; + return zoomLevelToImageMetadata.isEmpty(); } /** @@ -2312,6 +1979,7 @@ public void setBackground(Color color) { /* Get the HDC for the device */ long hDC = device.internal_new_GC(null); + long handle = win32_getHandle(this, getZoom()); /* Change the background color in the image */ BITMAP bm = new BITMAP(); @@ -2344,7 +2012,7 @@ private int getZoom() { @Override public String toString () { if (isDisposed()) return "Image {*DISPOSED*}"; - return "Image {" + handle + "}"; + return "Image {" + zoomLevelToImageMetadata + "}"; } /** @@ -2367,7 +2035,324 @@ public String toString () { public static Image win32_new(Device device, int type, long handle) { Image image = new Image(device); image.type = type; - image.setHandleForZoomLevel(handle, image.getZoom()); + ImageMetadata imageMetadata = image.new ImageMetadata(handle, image.getZoom()); + image.setImageMetadataForHandle(imageMetadata, image.getZoom()); return image; } + +class ImageMetadata { + long handle; + int nativeZoom; + int height; + int width; + + public ImageMetadata(long handle, int nativeZoom) { + Rectangle bounds = getBoundsInPixelsFromNative(handle); + this.handle = handle; + this.nativeZoom = nativeZoom; + this.height = bounds.height; + this.width = bounds.width; + } + + + private Rectangle getBoundsInPixelsFromNative(long handle) { + switch (type) { + case SWT.BITMAP: + BITMAP bm = new BITMAP(); + OS.GetObject(handle, BITMAP.sizeof, bm); + return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight); + case SWT.ICON: + ICONINFO info = new ICONINFO(); + OS.GetIconInfo(handle, info); + long hBitmap = info.hbmColor; + if (hBitmap == 0) hBitmap = info.hbmMask; + bm = new BITMAP(); + OS.GetObject(hBitmap, BITMAP.sizeof, bm); + if (hBitmap == info.hbmMask) bm.bmHeight /= 2; + if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor); + if (info.hbmMask != 0) OS.DeleteObject(info.hbmMask); + return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight); + default: + SWT.error(SWT.ERROR_INVALID_IMAGE); + return null; + } + } + + private ImageData getImageData() { + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + BITMAP bm; + int depth, width, height; + switch (type) { + case SWT.ICON: { + ICONINFO info = new ICONINFO(); + OS.GetIconInfo(handle, info); + /* Get the basic BITMAP information */ + long hBitmap = info.hbmColor; + if (hBitmap == 0) hBitmap = info.hbmMask; + bm = new BITMAP(); + OS.GetObject(hBitmap, BITMAP.sizeof, bm); + depth = bm.bmPlanes * bm.bmBitsPixel; + width = bm.bmWidth; + if (hBitmap == info.hbmMask) bm.bmHeight /= 2; + height = bm.bmHeight; + int numColors = 0; + if (depth <= 8) numColors = 1 << depth; + /* Create the BITMAPINFO */ + BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); + bmiHeader.biSize = BITMAPINFOHEADER.sizeof; + bmiHeader.biWidth = width; + bmiHeader.biHeight = -height; + bmiHeader.biPlanes = 1; + bmiHeader.biBitCount = (short)depth; + bmiHeader.biCompression = OS.BI_RGB; + byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4]; + OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); + + /* Get the HDC for the device */ + long hDC = device.internal_new_GC(null); + + /* Create the DC and select the bitmap */ + long hBitmapDC = OS.CreateCompatibleDC(hDC); + long hOldBitmap = OS.SelectObject(hBitmapDC, hBitmap); + /* Find the size of the image and allocate data */ + int imageSize; + /* Call with null lpBits to get the image size */ + OS.GetDIBits(hBitmapDC, hBitmap, 0, height, null, bmi, OS.DIB_RGB_COLORS); + OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); + imageSize = bmiHeader.biSizeImage; + byte[] data = new byte[imageSize]; + /* Get the bitmap data */ + OS.GetDIBits(hBitmapDC, hBitmap, 0, height, data, bmi, OS.DIB_RGB_COLORS); + /* Calculate the palette */ + PaletteData palette = null; + if (depth <= 8) { + RGB[] rgbs = new RGB[numColors]; + int srcIndex = 40; + for (int i = 0; i < numColors; i++) { + rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF); + srcIndex += 4; + } + palette = new PaletteData(rgbs); + } else if (depth == 16) { + palette = new PaletteData(0x7C00, 0x3E0, 0x1F); + } else if (depth == 24) { + palette = new PaletteData(0xFF, 0xFF00, 0xFF0000); + } else if (depth == 32) { + palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); + } else { + SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); + } + + /* Do the mask */ + byte [] maskData = null; + byte [] alphaData = null; + if (info.hbmColor == 0) { + /* Do the bottom half of the mask */ + maskData = new byte[imageSize]; + OS.GetDIBits(hBitmapDC, hBitmap, height, height, maskData, bmi, OS.DIB_RGB_COLORS); + } else { + /* Do the entire mask */ + /* Create the BITMAPINFO */ + bmiHeader = new BITMAPINFOHEADER(); + bmiHeader.biSize = BITMAPINFOHEADER.sizeof; + bmiHeader.biWidth = width; + bmiHeader.biHeight = -height; + bmiHeader.biPlanes = 1; + bmiHeader.biBitCount = 1; + bmiHeader.biCompression = OS.BI_RGB; + bmi = new byte[BITMAPINFOHEADER.sizeof + 8]; + OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); + + /* First color black, second color white */ + int offset = BITMAPINFOHEADER.sizeof; + bmi[offset + 4] = bmi[offset + 5] = bmi[offset + 6] = (byte)0xFF; + bmi[offset + 7] = 0; + OS.SelectObject(hBitmapDC, info.hbmMask); + /* Call with null lpBits to get the image size */ + OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, null, bmi, OS.DIB_RGB_COLORS); + OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); + imageSize = bmiHeader.biSizeImage; + maskData = new byte[imageSize]; + OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, maskData, bmi, OS.DIB_RGB_COLORS); + /* Loop to invert the mask */ + boolean hasMaskData = false; + for (int i = 0; i < maskData.length; i++) { + hasMaskData |= maskData[i] != 0; + maskData[i] ^= -1; + } + /* Make sure mask scanlinePad is 2 */ + int maskPad; + int bpl = imageSize / height; + for (maskPad = 1; maskPad < 128; maskPad++) { + int calcBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad; + if (calcBpl == bpl) break; + } + maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, 2); + // For missing mask data, see https://github.com/eclipse-platform/eclipse.platform.swt/issues/715 + if (!hasMaskData && depth == 32) { + alphaData = new byte[width * height]; + boolean hasAlphaData = false; + for (int pixelIndex = 0; pixelIndex < alphaData.length; pixelIndex++) { + alphaData[pixelIndex] = data[pixelIndex * 4 + 3]; + hasAlphaData |= alphaData[pixelIndex] != -1; + } + // In case there is alpha data, replace the empty mask data with proper alpha data + if (hasAlphaData) { + maskData = null; + } else { + alphaData = null; + } + } + } + /* Clean up */ + OS.SelectObject(hBitmapDC, hOldBitmap); + OS.DeleteDC(hBitmapDC); + + /* Release the HDC for the device */ + device.internal_dispose_GC(hDC, null); + + if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor); + if (info.hbmMask != 0) OS.DeleteObject(info.hbmMask); + /* Construct and return the ImageData */ + ImageData imageData = new ImageData(width, height, depth, palette, 4, data); + imageData.alphaData = alphaData; + imageData.maskData = maskData; + imageData.maskPad = 2; + return imageData; + } + case SWT.BITMAP: { + /* Get the basic BITMAP information */ + bm = new BITMAP(); + OS.GetObject(handle, BITMAP.sizeof, bm); + depth = bm.bmPlanes * bm.bmBitsPixel; + width = bm.bmWidth; + height = bm.bmHeight; + /* Find out whether this is a DIB or a DDB. */ + boolean isDib = (bm.bmBits != 0); + /* Get the HDC for the device */ + long hDC = device.internal_new_GC(null); + DIBSECTION dib = null; + if (isDib) { + dib = new DIBSECTION(); + OS.GetObject(handle, DIBSECTION.sizeof, dib); + } + /* Calculate number of colors */ + int numColors = 0; + if (depth <= 8) { + if (isDib) { + numColors = dib.biClrUsed; + } else { + numColors = 1 << depth; + } + } + /* Create the BITMAPINFO */ + byte[] bmi = null; + BITMAPINFOHEADER bmiHeader = null; + if (!isDib) { + bmiHeader = new BITMAPINFOHEADER(); + bmiHeader.biSize = BITMAPINFOHEADER.sizeof; + bmiHeader.biWidth = width; + bmiHeader.biHeight = -height; + bmiHeader.biPlanes = 1; + bmiHeader.biBitCount = (short)depth; + bmiHeader.biCompression = OS.BI_RGB; + bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4]; + OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof); + } + + /* Create the DC and select the bitmap */ + long hBitmapDC = OS.CreateCompatibleDC(hDC); + long hOldBitmap = OS.SelectObject(hBitmapDC, handle); + /* Find the size of the image and allocate data */ + int imageSize; + if (isDib) { + imageSize = dib.biSizeImage; + } else { + /* Call with null lpBits to get the image size */ + OS.GetDIBits(hBitmapDC, handle, 0, height, null, bmi, OS.DIB_RGB_COLORS); + OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); + imageSize = bmiHeader.biSizeImage; + } + byte[] data = new byte[imageSize]; + /* Get the bitmap data */ + if (isDib) { + OS.MoveMemory(data, bm.bmBits, imageSize); + } else { + OS.GetDIBits(hBitmapDC, handle, 0, height, data, bmi, OS.DIB_RGB_COLORS); + } + /* Calculate the palette */ + PaletteData palette = null; + if (depth <= 8) { + RGB[] rgbs = new RGB[numColors]; + if (isDib) { + byte[] colors = new byte[numColors * 4]; + OS.GetDIBColorTable(hBitmapDC, 0, numColors, colors); + int colorIndex = 0; + for (int i = 0; i < rgbs.length; i++) { + rgbs[i] = new RGB(colors[colorIndex + 2] & 0xFF, colors[colorIndex + 1] & 0xFF, colors[colorIndex] & 0xFF); + colorIndex += 4; + } + } else { + int srcIndex = BITMAPINFOHEADER.sizeof; + for (int i = 0; i < numColors; i++) { + rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF); + srcIndex += 4; + } + } + palette = new PaletteData(rgbs); + } else if (depth == 16) { + palette = new PaletteData(0x7C00, 0x3E0, 0x1F); + } else if (depth == 24) { + palette = new PaletteData(0xFF, 0xFF00, 0xFF0000); + } else if (depth == 32) { + palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); + } else { + SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); + } + /* Clean up */ + OS.SelectObject(hBitmapDC, hOldBitmap); + OS.DeleteDC(hBitmapDC); + + /* Release the HDC for the device */ + device.internal_dispose_GC(hDC, null); + + /* Construct and return the ImageData */ + ImageData imageData = new ImageData(width, height, depth, palette, 4, data); + imageData.transparentPixel = transparentPixel; + if (depth == 32) { + byte straightData[] = new byte[imageSize]; + byte alphaData[] = new byte[width * height]; + boolean validAlpha = isDib; + for (int ap = 0, dp = 0; validAlpha && ap < alphaData.length; ap++, dp += 4) { + int b = data[dp ] & 0xFF; + int g = data[dp + 1] & 0xFF; + int r = data[dp + 2] & 0xFF; + int a = data[dp + 3] & 0xFF; + alphaData[ap] = (byte) a; + validAlpha = validAlpha && b <= a && g <= a && r <= a; + if (a != 0) { + straightData[dp ] = (byte) (((b * 0xFF) + a / 2) / a); + straightData[dp + 1] = (byte) (((g * 0xFF) + a / 2) / a); + straightData[dp + 2] = (byte) (((r * 0xFF) + a / 2) / a); + } + } + if (validAlpha) { + imageData.data = straightData; + imageData.alphaData = alphaData; + } + else { + for (int dp = 3; dp < imageSize; dp += 4) { + data[dp] = (byte) 0xFF; + } + } + } + return imageData; + } + default: + SWT.error(SWT.ERROR_INVALID_IMAGE); + return null; + } + } + +} } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java index 1f680949e54..4a6ba4b65d5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java @@ -914,7 +914,7 @@ void setImages (Image image, Image [] images) { if (smallIcon != null) { switch (smallIcon.type) { case SWT.BITMAP: - smallImage = Display.createIcon (smallIcon); + smallImage = Display.createIcon (smallIcon, getZoom()); hSmallIcon = Image.win32_getHandle(smallImage, getZoom()); break; case SWT.ICON: @@ -926,7 +926,7 @@ void setImages (Image image, Image [] images) { if (largeIcon != null) { switch (largeIcon.type) { case SWT.BITMAP: - largeImage = Display.createIcon (largeIcon); + largeImage = Display.createIcon (largeIcon, getZoom()); hLargeIcon = Image.win32_getHandle(largeImage, getZoom()); break; case SWT.ICON: diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java index 00205d39e30..e50b33cb47a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java @@ -1163,9 +1163,9 @@ static long create32bitDIB (long hBitmap, int alpha, byte [] alphaData, int tran return memDib; } -static Image createIcon (Image image) { +static Image createIcon (Image image, int zoom) { Device device = image.getDevice (); - ImageData data = image.getImageDataAtCurrentZoom(); + ImageData data = image.getImageData(zoom); if (data.alpha == -1 && data.alphaData == null) { ImageData mask = data.getTransparencyMask (); return new Image (device, data, mask); @@ -1174,7 +1174,7 @@ static Image createIcon (Image image) { long hMask, hBitmap; long hDC = device.internal_new_GC (null); long dstHdc = OS.CreateCompatibleDC (hDC), oldDstBitmap; - hBitmap = Display.create32bitDIB (image.handle, data.alpha, data.alphaData, data.transparentPixel); + hBitmap = Display.create32bitDIB (Image.win32_getHandle(image, zoom), data.alpha, data.alphaData, data.transparentPixel); hMask = OS.CreateBitmap (width, height, 1, 1, null); oldDstBitmap = OS.SelectObject (dstHdc, hMask); OS.PatBlt (dstHdc, 0, 0, width, height, OS.BLACKNESS); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TaskBar.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TaskBar.java index e0bc571bad3..3d2d1443628 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TaskBar.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TaskBar.java @@ -165,13 +165,10 @@ IShellLink createShellLink (MenuItem item) { icon = directory + "\\" + "menu" + item.id + ".ico"; ImageData data; if (item.hBitmap != 0) { - Image image2 = Image.win32_new (display, SWT.BITMAP, item.hBitmap); + long handle = OS.CopyImage(item.hBitmap, SWT.BITMAP, 0, 0, 0); + Image image2 = Image.win32_new (display, SWT.BITMAP, handle); data = image2.getImageData (DPIUtil.getDeviceZoom ()); - /* - * image2 instance doesn't own the handle and shall not be disposed. Make it - * appear disposed to cause leak trackers to ignore it. - */ - image2.handle = 0; + image2.dispose(); } else { data = image.getImageData (DPIUtil.getDeviceZoom ()); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TaskItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TaskItem.java index 8d3f03a163f..c450f0bc063 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TaskItem.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TaskItem.java @@ -473,7 +473,7 @@ void updateImage () { long hIcon = 0; switch (overlayImage.type) { case SWT.BITMAP: - image2 = Display.createIcon (overlayImage); + image2 = Display.createIcon (overlayImage, getZoom()); hIcon = Image.win32_getHandle(image2, getZoom()); break; case SWT.ICON: diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TrayItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TrayItem.java index a918fdcea40..1e213721065 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TrayItem.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TrayItem.java @@ -457,7 +457,7 @@ public void setImage (Image image) { if (icon != null) { switch (icon.type) { case SWT.BITMAP: - image2 = Display.createIcon (image); + image2 = Display.createIcon (image, getZoom()); hIcon = Image.win32_getHandle(image2, getZoom()); break; case SWT.ICON: