From 34950ab586f7f4934c841d33a9cd94efbe5f024e Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Sun, 24 Mar 2024 15:52:01 +0100 Subject: [PATCH 1/2] Revert "[Win32] Remove buggy icon retrieval from file extensions #715" This reverts commit 97ca656d5c331132b19dd45c682a93803eb161c2 because it resulted in specific program icons (such as the one for .exe files) not being loaded anymore. Contributes to https://github.com/eclipse-platform/eclipse.platform.swt/issues/1130 --- .../org/eclipse/swt/program/Program.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Program/win32/org/eclipse/swt/program/Program.java b/bundles/org.eclipse.swt/Eclipse SWT Program/win32/org/eclipse/swt/program/Program.java index b5a2b6252a9..a5d483c30fb 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Program/win32/org/eclipse/swt/program/Program.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Program/win32/org/eclipse/swt/program/Program.java @@ -35,6 +35,7 @@ public final class Program { String name; String command; String iconName; + String extension; static final String [] ARGUMENTS = new String [] {"%1", "%l", "%L"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ /** @@ -101,6 +102,7 @@ public static Program findProgram (String extension) { program.name = name; program.command = command; program.iconName = iconName; + program.extension = extension; } return program; } @@ -182,7 +184,7 @@ static String getKeyValue (String string, boolean expand) { return result; } -static Program getProgram (String key) { +static Program getProgram (String key, String extension) { /* Name */ String name = getKeyValue (key, false); @@ -208,6 +210,7 @@ static Program getProgram (String key) { program.name = name; program.command = command; program.iconName = iconName; + program.extension = extension; return program; } @@ -233,7 +236,7 @@ static Program getProgram (String key) { //map paths to programs in parallel which takes now ~ 4/5 of time: ConcurrentHashMap programs = new ConcurrentHashMap<>(paths.size()); paths.stream().parallel().forEach(path -> { - Program program = getProgram(path); // getProgram takes most time + Program program = getProgram(path, null); // getProgram takes most time if (program != null) { programs.put(path, program); } @@ -377,6 +380,22 @@ public ImageData getImageData () { * @since 3.125 */ public ImageData getImageData (int zoom) { + // Windows API returns image data according to primary monitor zoom factor + // rather than at original scaling + int nativeZoomFactor = 100 * Display.getCurrent().getPrimaryMonitor().getZoom() / DPIUtil.getDeviceZoom(); + int imageZoomFactor = 100 * zoom / nativeZoomFactor; + if (extension != null) { + SHFILEINFO shfi = new SHFILEINFO (); + int flags = OS.SHGFI_ICON | OS.SHGFI_SMALLICON | OS.SHGFI_USEFILEATTRIBUTES; + TCHAR pszPath = new TCHAR (0, extension, true); + OS.SHGetFileInfo (pszPath.chars, OS.FILE_ATTRIBUTE_NORMAL, shfi, SHFILEINFO.sizeof, flags); + if (shfi.hIcon != 0) { + Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon); + ImageData imageData = image.getImageData (imageZoomFactor); + image.dispose (); + return imageData; + } + } int nIconIndex = 0; String fileName = iconName; int index = iconName.indexOf (','); @@ -398,10 +417,7 @@ public ImageData getImageData (int zoom) { OS.ExtractIconEx (lpszFile, nIconIndex, phiconLarge, phiconSmall, 1); if (phiconSmall [0] == 0) return null; Image image = Image.win32_new (null, SWT.ICON, phiconSmall [0]); - // Windows API returns image data according to primary monitor zoom factor - // rather than at original scaling - int nativeZoomFactor = 100 * Display.getCurrent().getPrimaryMonitor().getZoom() / DPIUtil.getDeviceZoom(); - ImageData imageData = image.getImageData (100 * zoom / nativeZoomFactor); + ImageData imageData = image.getImageData (imageZoomFactor); image.dispose (); return imageData; } From 78573aa18a6adf2d336e51b20d000970b1117fc9 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Wed, 24 Jan 2024 09:21:12 +0100 Subject: [PATCH 2/2] [Win32] Extract alpha values from icons if available #715 #1130 Under certain conditions, program icons loaded on Windows via GDI+ have empty mask data, even though the original icon has proper mask data. As a result, these icons are printed with a black instead of a transparent background. Still these icons can contain valid alpha data in their usual 32-bit data. With this change, alpha data is extracted for icons which are loaded without proper mask data to ensure that they have proper transparency information. Fixes https://github.com/eclipse-platform/eclipse.platform.swt/issues/715 Fixes https://github.com/eclipse-platform/eclipse.platform.swt/issues/1130 --- .../win32/org/eclipse/swt/graphics/Image.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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 4ee1bd38e78..72e6c52e562 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 @@ -1430,6 +1430,7 @@ public ImageData getImageDataAtCurrentZoom() { /* Do the mask */ byte [] maskData = null; + byte [] alphaData = null; if (info.hbmColor == 0) { /* Do the bottom half of the mask */ maskData = new byte[imageSize]; @@ -1459,7 +1460,9 @@ public ImageData getImageDataAtCurrentZoom() { 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 */ @@ -1470,6 +1473,21 @@ public ImageData getImageDataAtCurrentZoom() { 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); @@ -1482,6 +1500,7 @@ public ImageData getImageDataAtCurrentZoom() { 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;