Skip to content

Commit 47da655

Browse files
ShahzaibIbrahimakoch-yatta
authored andcommitted
[win32] Move transparent pixel handling from Image to ImageHandle
Previously, the transparency pixel was managed at the Image level, which caused issues when an Image had multiple handles at different zoom levels or color models (e.g., indexed vs. direct/ARGB). For example, a GIF image at 100% zoom may use a transparency pixel, but when scaled, SWT converts it to a direct image with alpha data, making the transparency pixel concept invalid for the scaled handle. This change moves the transparency pixel field from the Image class to the ImageHandle class. Now, each handle manages its own transparency information, allowing a single Image to have multiple handles, each with the correct transparency type (pixel or alpha) according to its color model. This ensures correct transparency handling for all handles, regardless of how they were created or scaled.
1 parent 03cc46e commit 47da655

File tree

2 files changed

+70
-67
lines changed

2 files changed

+70
-67
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,8 +1527,8 @@ private void drawBitmap(Image srcImage, ImageHandle imageHandle, int srcX, int s
15271527
int depth = bm.bmPlanes * bm.bmBitsPixel;
15281528
if (isDib && depth == 32) {
15291529
drawBitmapAlpha(handle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
1530-
} else if (srcImage.transparentPixel != -1) {
1531-
drawBitmapTransparent(srcImage, imageHandle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
1530+
} else if (imageHandle.transparentPixel != -1) {
1531+
drawBitmapTransparent(imageHandle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
15321532
} else {
15331533
drawBitmapColor(handle, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
15341534
}
@@ -1788,15 +1788,15 @@ private void drawBitmapMask(long srcColor, long srcMask, int srcX, int srcY, int
17881788
OS.DeleteDC(srcHdc);
17891789
}
17901790

1791-
private void drawBitmapTransparent(Image srcImage, ImageHandle imageHandle, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) {
1791+
private void drawBitmapTransparent(ImageHandle imageHandle, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, BITMAP bm, int imgWidth, int imgHeight) {
17921792

17931793
/* Find the RGB values for the transparent pixel. */
17941794
boolean isDib = bm.bmBits != 0;
17951795
long hBitmap = imageHandle.getHandle();
17961796
long srcHdc = OS.CreateCompatibleDC(handle);
17971797
long oldSrcBitmap = OS.SelectObject(srcHdc, hBitmap);
17981798
byte[] originalColors = null;
1799-
int transparentColor = srcImage.transparentColor;
1799+
int transparentColor = imageHandle.transparentColor;
18001800
if (transparentColor == -1) {
18011801
int transBlue = 0, transGreen = 0, transRed = 0;
18021802
boolean fixPalette = false;
@@ -1805,7 +1805,7 @@ private void drawBitmapTransparent(Image srcImage, ImageHandle imageHandle, int
18051805
int maxColors = 1 << bm.bmBitsPixel;
18061806
byte[] oldColors = new byte[maxColors * 4];
18071807
OS.GetDIBColorTable(srcHdc, 0, maxColors, oldColors);
1808-
int offset = srcImage.transparentPixel * 4;
1808+
int offset = imageHandle.transparentPixel * 4;
18091809
for (int i = 0; i < oldColors.length; i += 4) {
18101810
if (i != offset) {
18111811
if (oldColors[offset] == oldColors[i] && oldColors[offset+1] == oldColors[i+1] && oldColors[offset+2] == oldColors[i+2]) {
@@ -1838,14 +1838,14 @@ private void drawBitmapTransparent(Image srcImage, ImageHandle imageHandle, int
18381838
byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
18391839
OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
18401840
OS.GetDIBits(srcHdc, imageHandle.getHandle(), 0, 0, null, bmi, OS.DIB_RGB_COLORS);
1841-
int offset = BITMAPINFOHEADER.sizeof + 4 * srcImage.transparentPixel;
1841+
int offset = BITMAPINFOHEADER.sizeof + 4 * imageHandle.transparentPixel;
18421842
transRed = bmi[offset + 2] & 0xFF;
18431843
transGreen = bmi[offset + 1] & 0xFF;
18441844
transBlue = bmi[offset] & 0xFF;
18451845
}
18461846
} else {
18471847
/* Direct color image */
1848-
int pixel = srcImage.transparentPixel;
1848+
int pixel = imageHandle.transparentPixel;
18491849
switch (bm.bmBitsPixel) {
18501850
case 16:
18511851
transBlue = (pixel & 0x1F) << 3;
@@ -1865,7 +1865,7 @@ private void drawBitmapTransparent(Image srcImage, ImageHandle imageHandle, int
18651865
}
18661866
}
18671867
transparentColor = transBlue << 16 | transGreen << 8 | transRed;
1868-
if (!fixPalette) srcImage.transparentColor = transparentColor;
1868+
if (!fixPalette) imageHandle.transparentColor = transparentColor;
18691869
}
18701870

18711871
if (originalColors == null) {

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java

Lines changed: 62 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,6 @@ public final class Image extends Resource implements Drawable {
104104
*/
105105
private boolean isDestroyed;
106106

107-
/**
108-
* specifies the transparent pixel
109-
*/
110-
int transparentPixel = -1, transparentColor = -1;
111-
112107
/**
113108
* the GC which is drawing on the image
114109
*/
@@ -277,7 +272,7 @@ public Image(Device device, Image srcImage, int flag) {
277272
long hOldSrc = OS.SelectObject(hdcSource, srcImageHandle);
278273
BITMAP bm = new BITMAP();
279274
OS.GetObject(srcImageHandle, BITMAP.sizeof, bm);
280-
imageMetadata = new ImageHandle(OS.CreateCompatibleBitmap(hdcSource, rect.width, bm.bmBits != 0 ? -rect.height : rect.height), imageHandle.zoom);
275+
imageMetadata = new ImageHandle(OS.CreateCompatibleBitmap(hdcSource, rect.width, bm.bmBits != 0 ? -rect.height : rect.height), imageHandle.zoom, imageHandle.transparentPixel);
281276
if (imageMetadata.handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
282277
long hOldDest = OS.SelectObject(hdcDest, imageMetadata.handle);
283278
OS.BitBlt(hdcDest, 0, 0, rect.width, rect.height, hdcSource, 0, 0, OS.SRCCOPY);
@@ -289,12 +284,11 @@ public Image(Device device, Image srcImage, int flag) {
289284
/* Release the HDC for the device */
290285
device.internal_dispose_GC(hDC, null);
291286
}
292-
transparentPixel = srcImage.transparentPixel;
293287
break;
294288
case SWT.ICON:
295289
for (ImageHandle imageHandle : srcImage.zoomLevelToImageHandle.values()) {
296290
Rectangle rect = imageHandle.getBounds();
297-
imageMetadata = new ImageHandle(OS.CopyImage(imageHandle.handle, OS.IMAGE_ICON, rect.width, rect.height, 0), imageHandle.zoom);
291+
imageMetadata = new ImageHandle(OS.CopyImage(imageHandle.handle, OS.IMAGE_ICON, rect.width, rect.height, 0), imageHandle.zoom, imageHandle.transparentPixel);
298292
if (imageMetadata.handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
299293
}
300294
break;
@@ -888,7 +882,8 @@ public static void drawAtSize(GC gc, ImageData imageData, int width, int height)
888882
}
889883

890884
long[] createGdipImageFromHandle(ImageHandle imageHandle) {
891-
long handle = imageHandle.handle;
885+
long handle = imageHandle.getHandle();
886+
int transparentPixel = imageHandle.transparentPixel;
892887
switch (type) {
893888
case SWT.BITMAP: {
894889
BITMAP bm = new BITMAP();
@@ -1124,7 +1119,7 @@ public boolean equals (Object object) {
11241119
if (object == this) return true;
11251120
if (!(object instanceof Image)) return false;
11261121
Image image = (Image) object;
1127-
if (device != image.device || transparentPixel != image.transparentPixel) return false;
1122+
if (device != image.device) return false;
11281123
return (styleFlag == image.styleFlag) && imageProvider.equals(image.imageProvider);
11291124
}
11301125

@@ -1148,57 +1143,58 @@ public boolean equals (Object object) {
11481143
*/
11491144
public Color getBackground() {
11501145
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1151-
if (transparentPixel == -1) return null;
1146+
if (this.getImageData().transparentPixel == -1) return null;
11521147
if (backgroundColor != null) {
11531148
// if a background color was set explicitly, we use the cached color directly
11541149
return Color.win32_new(device, (backgroundColor.blue << 16) | (backgroundColor.green << 8) | backgroundColor.red);
11551150
}
1156-
1151+
ImageHandle imageHandle = this.getHandle(100, 100);
1152+
if (imageHandle.transparentPixel == -1) {
1153+
return null;
1154+
}
11571155
/* Get the HDC for the device */
11581156
long hDC = device.internal_new_GC(null);
1159-
return applyUsingAnyHandle(imageHandle -> {
1160-
long handle = imageHandle.handle;
1161-
/* Compute the background color */
1162-
BITMAP bm = new BITMAP();
1163-
OS.GetObject(handle, BITMAP.sizeof, bm);
1164-
long hdcMem = OS.CreateCompatibleDC(hDC);
1165-
long hOldObject = OS.SelectObject(hdcMem, handle);
1166-
int red = 0, green = 0, blue = 0;
1167-
if (bm.bmBitsPixel <= 8) {
1168-
byte[] color = new byte[4];
1169-
OS.GetDIBColorTable(hdcMem, transparentPixel, 1, color);
1170-
blue = color[0] & 0xFF;
1171-
green = color[1] & 0xFF;
1172-
red = color[2] & 0xFF;
1173-
} else {
1174-
switch (bm.bmBitsPixel) {
1175-
case 16:
1176-
blue = (transparentPixel & 0x1F) << 3;
1177-
green = (transparentPixel & 0x3E0) >> 2;
1178-
red = (transparentPixel & 0x7C00) >> 7;
1179-
break;
1180-
case 24:
1181-
blue = (transparentPixel & 0xFF0000) >> 16;
1182-
green = (transparentPixel & 0xFF00) >> 8;
1183-
red = transparentPixel & 0xFF;
1184-
break;
1185-
case 32:
1186-
blue = (transparentPixel & 0xFF000000) >>> 24;
1187-
green = (transparentPixel & 0xFF0000) >> 16;
1188-
red = (transparentPixel & 0xFF00) >> 8;
1189-
break;
1190-
default:
1191-
return null;
1192-
}
1157+
long handle = imageHandle.handle;
1158+
int transparentPixel = imageHandle.transparentPixel;
1159+
/* Compute the background color */
1160+
BITMAP bm = new BITMAP();
1161+
OS.GetObject(handle, BITMAP.sizeof, bm);
1162+
long hdcMem = OS.CreateCompatibleDC(hDC);
1163+
long hOldObject = OS.SelectObject(hdcMem, handle);
1164+
int red = 0, green = 0, blue = 0;
1165+
if (bm.bmBitsPixel <= 8) {
1166+
byte[] color = new byte[4];
1167+
OS.GetDIBColorTable(hdcMem, transparentPixel, 1, color);
1168+
blue = color[0] & 0xFF;
1169+
green = color[1] & 0xFF;
1170+
red = color[2] & 0xFF;
1171+
} else {
1172+
switch (bm.bmBitsPixel) {
1173+
case 16:
1174+
blue = (transparentPixel & 0x1F) << 3;
1175+
green = (transparentPixel & 0x3E0) >> 2;
1176+
red = (transparentPixel & 0x7C00) >> 7;
1177+
break;
1178+
case 24:
1179+
blue = (transparentPixel & 0xFF0000) >> 16;
1180+
green = (transparentPixel & 0xFF00) >> 8;
1181+
red = transparentPixel & 0xFF;
1182+
break;
1183+
case 32:
1184+
blue = (transparentPixel & 0xFF000000) >>> 24;
1185+
green = (transparentPixel & 0xFF0000) >> 16;
1186+
red = (transparentPixel & 0xFF00) >> 8;
1187+
break;
1188+
default:
1189+
return null;
11931190
}
1194-
OS.SelectObject(hdcMem, hOldObject);
1195-
OS.DeleteDC(hdcMem);
1196-
1191+
}
1192+
OS.SelectObject(hdcMem, hOldObject);
1193+
OS.DeleteDC(hdcMem);
11971194

1198-
/* Release the HDC for the device */
1199-
device.internal_dispose_GC(hDC, null);
1200-
return Color.win32_new(device, (blue << 16) | (green << 8) | red);
1201-
});
1195+
/* Release the HDC for the device */
1196+
device.internal_dispose_GC(hDC, null);
1197+
return Color.win32_new(device, (blue << 16) | (green << 8) | red);
12021198
}
12031199

12041200
/**
@@ -1659,8 +1655,7 @@ private ImageHandle initIconHandle(long[] handles, int zoom) {
16591655

16601656
private ImageHandle initBitmapHandle(ImageData imageData, long handle, Integer zoom) {
16611657
type = SWT.BITMAP;
1662-
transparentPixel = imageData.transparentPixel;
1663-
return new ImageHandle(handle, zoom);
1658+
return new ImageHandle(handle, zoom, imageData.transparentPixel);
16641659
}
16651660

16661661
static long [] initIcon(Device device, ImageData source, ImageData mask) {
@@ -1900,8 +1895,6 @@ public void setBackground(Color color) {
19001895
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
19011896
if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
19021897
if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1903-
if (transparentPixel == -1) return;
1904-
transparentColor = -1;
19051898
backgroundColor = color.getRGB();
19061899
zoomLevelToImageHandle.values().forEach(imageHandle -> imageHandle.setBackground(backgroundColor));
19071900
}
@@ -2457,7 +2450,7 @@ protected ElementAtZoom<ImageData> loadImageData(int zoom) {
24572450

24582451
@Override
24592452
public int hashCode() {
2460-
return Objects.hash(provider, styleFlag, transparentPixel);
2453+
return Objects.hash(provider, styleFlag);
24612454
}
24622455

24632456
@Override
@@ -2532,7 +2525,7 @@ ImageHandle initNative(String filename, int zoom) {
25322525
OS.SelectObject(srcHDC, oldSrcBitmap);
25332526
OS.DeleteDC(srcHDC);
25342527
device.internal_dispose_GC(hDC, null);
2535-
imageMetadata = new ImageHandle(handle, zoom);
2528+
imageMetadata = new ImageHandle(handle, zoom, -1);
25362529
} else {
25372530
long lockedBitmapData = Gdip.BitmapData_new();
25382531
if (lockedBitmapData != 0) {
@@ -2813,13 +2806,23 @@ class ImageHandle {
28132806
private final int zoom;
28142807
private final int height;
28152808
private final int width;
2809+
/**
2810+
* specifies the transparent pixel
2811+
*/
2812+
final int transparentPixel;
2813+
int transparentColor = -1;
28162814

28172815
ImageHandle(long handle, int zoom) {
2816+
this(handle, zoom, -1);
2817+
}
2818+
2819+
ImageHandle(long handle, int zoom, int transparentPixel) {
28182820
this.handle = handle;
28192821
this.zoom = zoom;
28202822
Point bounds = getBoundsInPixelsFromNative();
28212823
this.width = bounds.x;
28222824
this.height = bounds.y;
2825+
this.transparentPixel = transparentPixel;
28232826
if (backgroundColor != null) {
28242827
setBackground(backgroundColor);
28252828
}

0 commit comments

Comments
 (0)