Skip to content

Commit a0e1809

Browse files
committed
[macOS] Initialize image data from ImageGcDrawer at device zoom only
An Image based on an ImageGcDrawer currently initializes two image representations for 100% and 200% zoom, so that an appropriate representation for each of the two zoom levels can be retrieved. This, however, leads to issues when creating a GC on an Image created in that way, as only one of the two representations (the one fitting to the current device zoom) will be modified by the GC. If later the representation with the other zoom is used, it will not contain the changes performed by the GC. One such scenario is starting an application at a monitor with one zoom (used as the device zoom throughout the application lifecycle then) and moving the shell to a monitor with a different zoom. An image will then be modified only for the zoom of the first monitor, thus if using it inside a control, it will yield the unmodified version on the second monitor. To avoid this issue, this change ensures that an Image based on an ImageGcDrawer is only initialized for the device zoom. Fixes eclipse-platform/eclipse.platform.ui#3039
1 parent 1bf111f commit a0e1809

File tree

2 files changed

+40
-17
lines changed

2 files changed

+40
-17
lines changed

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

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ public Image(Device device, ImageData data) {
572572
NSAutoreleasePool pool = null;
573573
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
574574
try {
575-
init(data);
575+
init(data, 100);
576576
init();
577577
} finally {
578578
if (pool != null) pool.release();
@@ -623,7 +623,7 @@ public Image(Device device, ImageData source, ImageData mask) {
623623
ImageData image = new ImageData(source.width, source.height, source.depth, source.palette, source.scanlinePad, source.data);
624624
image.maskPad = mask.scanlinePad;
625625
image.maskData = mask.data;
626-
init(image);
626+
init(image, 100);
627627
} finally {
628628
if (pool != null) pool.release();
629629
}
@@ -789,7 +789,7 @@ public Image(Device device, ImageFileNameProvider imageFileNameProvider) {
789789
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
790790
try {
791791
initNative(filename);
792-
if (this.handle == null) init(ImageDataLoader.load(filename, 100, 100).element());
792+
if (this.handle == null) init(ImageDataLoader.load(filename, 100, 100).element(), 100);
793793
init();
794794
String filename2x = imageFileNameProvider.getImagePath(200);
795795
if (filename2x != null) {
@@ -848,7 +848,7 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
848848
NSAutoreleasePool pool = null;
849849
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
850850
try {
851-
init (data);
851+
init (data, 100);
852852
init ();
853853
ImageData data2x = imageDataProvider.getImageData (200);
854854
if (data2x != null) {
@@ -886,20 +886,13 @@ public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height)
886886
this.imageGcDrawer = imageGcDrawer;
887887
this.width = width;
888888
this.height = height;
889-
ImageData data = drawWithImageGcDrawer(imageGcDrawer, width, height, 100);
889+
ImageData data = drawWithImageGcDrawer(imageGcDrawer, width, height, DPIUtil.getDeviceZoom());
890890
if (data == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
891891
NSAutoreleasePool pool = null;
892892
if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
893893
try {
894-
init (data);
894+
init (data, DPIUtil.getDeviceZoom());
895895
init ();
896-
ImageData data2x = drawWithImageGcDrawer(imageGcDrawer, width, height, 200);
897-
if (data2x != null) {
898-
alphaInfo_200 = new AlphaInfo();
899-
NSBitmapImageRep rep = createRepresentation (data2x, alphaInfo_200);
900-
handle.addRepresentation(rep);
901-
rep.release();
902-
}
903896
} finally {
904897
if (pool != null) pool.release();
905898
}
@@ -1474,7 +1467,7 @@ void init(int width, int height) {
14741467
if (alphaInfo_100 == null) alphaInfo_100 = new AlphaInfo();
14751468
}
14761469

1477-
void init(ImageData image) {
1470+
void init(ImageData image, int imageZoom) {
14781471
if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
14791472

14801473
if (handle != null) handle.release();
@@ -1484,8 +1477,8 @@ void init(ImageData image) {
14841477
size.width = width;
14851478
size.height = height;
14861479
handle = handle.initWithSize(size);
1487-
this.width = image.width;
1488-
this.height = image.height;
1480+
this.width = image.width * 100 / imageZoom;
1481+
this.height = image.height * 100 / imageZoom;
14891482
if (alphaInfo_100 == null) alphaInfo_100 = new AlphaInfo();
14901483
NSBitmapImageRep rep = createRepresentation(image, alphaInfo_100);
14911484
handle.addRepresentation(rep);
@@ -1495,7 +1488,7 @@ void init(ImageData image) {
14951488

14961489
private void initWithSupplier(Function<Integer, Boolean> canLoadAtZoom, Function<Integer, ImageData> zoomToImageData) {
14971490
ImageData imageData = zoomToImageData.apply(100);
1498-
init(imageData);
1491+
init(imageData, 100);
14991492
if (canLoadAtZoom.apply(200)) {
15001493
ImageData imageData2x = zoomToImageData.apply(200);
15011494
alphaInfo_200 = new AlphaInfo();

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_Image.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static org.junit.Assert.assertTrue;
2626
import static org.junit.Assume.assumeFalse;
2727
import static org.junit.Assume.assumeTrue;
28+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
2829

2930
import java.io.ByteArrayInputStream;
3031
import java.io.IOException;
@@ -1075,6 +1076,34 @@ public void test_imageDataSameViaProviderAndSimpleData() {
10751076
dataImage.dispose();
10761077
}
10771078

1079+
/**
1080+
* See https://github.com/eclipse-platform/eclipse.platform.ui/issues/3039
1081+
*/
1082+
@Test
1083+
public void test_gcOnImageGcDrawer_imageDataAtNonDeviceZoom() {
1084+
int originalDeviceZoom = DPIUtil.getDeviceZoom();
1085+
int deviceZoom = 200;
1086+
int nonDeviceZoom = 100;
1087+
DPIUtil.setDeviceZoom(deviceZoom);
1088+
1089+
ImageGcDrawer blueDrawer = (gc, width, height) -> {
1090+
gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE));
1091+
gc.fillRectangle(0, 0, width, height);
1092+
};
1093+
Image image = new Image(display, blueDrawer, 1, 1);
1094+
int bluePixelValue = image.getImageData(nonDeviceZoom).getPixel(0, 0);
1095+
1096+
GC redOverwritingGc = new GC(image);
1097+
try {
1098+
redOverwritingGc.setBackground(display.getSystemColor(SWT.COLOR_RED));
1099+
redOverwritingGc.fillRectangle(0, 0, 1, 1);
1100+
assertNotEquals(bluePixelValue, image.getImageData(nonDeviceZoom).getPixel(0, 0));
1101+
} finally {
1102+
redOverwritingGc.dispose();
1103+
image.dispose();
1104+
DPIUtil.setDeviceZoom(originalDeviceZoom);
1105+
}
1106+
}
10781107

10791108
private Comparator<ImageData> imageDataComparator() {
10801109
return Comparator.<ImageData>comparingInt(d -> d.width) //
@@ -1095,3 +1124,4 @@ private Comparator<ImageData> imageDataComparator() {
10951124
}
10961125

10971126
}
1127+

0 commit comments

Comments
 (0)