Skip to content

Commit 45cd163

Browse files
committed
Ensure DrawImage deals with scenario ImageData not linearly scaled
This change makes sure DrawImage handles the scenario where ImageData may not be linearly scaled across zooms.
1 parent 649bb49 commit 45cd163

File tree

2 files changed

+91
-5
lines changed
  • bundles/org.eclipse.swt

2 files changed

+91
-5
lines changed

bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/ImagesWin32Tests.java

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,90 @@
2525
@ExtendWith(WithMonitorSpecificScalingExtension.class)
2626
class ImagesWin32Tests {
2727

28+
@Test
29+
public void test_imageScaledFrom150_when125PercentImageUnavailable() {
30+
Display display = Display.getDefault();
31+
GC gc = new GC(display);
32+
GCData gcData = gc.getGCData();
33+
gcData.nativeZoom = 125;
34+
ImageDataProvider imageDataProviderReturnsNullAt125 = zoom -> {
35+
if (zoom == 125) {
36+
return null;
37+
}
38+
float scaleFactor = zoom / 100f;
39+
int scaledWidth = Math.round(16 * scaleFactor);
40+
int scaledHeight = Math.round(16 * scaleFactor);
41+
return new ImageData(scaledWidth, scaledHeight, 1, new PaletteData(new RGB(255, 0, 0)));
42+
};
43+
Image image = new Image(display, imageDataProviderReturnsNullAt125);
44+
gc.drawImage(image, 0, 0, 16, 16, 0, 0, 16, 16);
45+
gc.dispose();
46+
image.dispose();
47+
}
48+
49+
@Test
50+
public void test_imageScaledFrom100_when125And150PercentImagesUnavailable() {
51+
Display display = Display.getDefault();
52+
GC gc = new GC(display);
53+
GCData gcData = gc.getGCData();
54+
gcData.nativeZoom = 125;
55+
ImageDataProvider imageDataProviderReturnsNullAt125and150 = zoom -> {
56+
if (zoom == 125) {
57+
return null;
58+
}
59+
if (zoom == 150) {
60+
return null;
61+
}
62+
float scaleFactor = zoom / 100f;
63+
int scaledWidth = Math.round(16 * scaleFactor);
64+
int scaledHeight = Math.round(16 * scaleFactor);
65+
return new ImageData(scaledWidth, scaledHeight, 1, new PaletteData(new RGB(255, 0, 0)));
66+
};
67+
Image image = new Image(display, imageDataProviderReturnsNullAt125and150);
68+
gc.drawImage(image, 0, 0, 16, 16, 0, 0, 16, 16);
69+
gc.dispose();
70+
image.dispose();
71+
}
72+
73+
@Test
74+
public void test_drawImage_when130PercentImageUnavailable() {
75+
Display display = Display.getDefault();
76+
GC gc = new GC(display);
77+
GCData gcData = gc.getGCData();
78+
gcData.nativeZoom = 130;
79+
ImageDataProvider imageDataProviderReturnsNullAt125 = zoom -> {
80+
if (zoom == 130){
81+
return null;
82+
}
83+
float scaleFactor = zoom / 100f;
84+
int scaledWidth = Math.round(16 * scaleFactor);
85+
int scaledHeight = Math.round(16 * scaleFactor);
86+
return new ImageData(scaledWidth, scaledHeight, 1, new PaletteData(new RGB(255, 0, 0)));
87+
};
88+
Image image = new Image(display, imageDataProviderReturnsNullAt125);
89+
gc.drawImage(image, 0, 0, 16, 16, 0, 0, 16, 16);
90+
gc.dispose();
91+
image.dispose();
92+
}
93+
94+
@Test
95+
public void test_drawImageUsesWronglyScaledImageDataProvider() {
96+
Display display = Display.getDefault();
97+
GC gc = new GC(display);
98+
GCData gcData = gc.getGCData();
99+
gcData.nativeZoom = 125;
100+
ImageDataProvider incorrectlyScaledimageDataProvider = zoom -> {
101+
int scaleFactor = zoom / 100;
102+
int scaledWidth = Math.round(16 * scaleFactor);
103+
int scaledHeight = Math.round(16 * scaleFactor);
104+
return new ImageData(scaledWidth, scaledHeight, 1, new PaletteData(new RGB(255, 0, 0)));
105+
};
106+
Image image = new Image(display, incorrectlyScaledimageDataProvider);
107+
gc.drawImage(image, 0, 0, 16, 16, 0, 0, 16, 16);
108+
gc.dispose();
109+
image.dispose();
110+
}
111+
28112
@Test
29113
public void testImageIconTypeShouldNotChangeAfterCallingGetHandleForDifferentZoom() {
30114
Image icon = Display.getDefault().getSystemImage(SWT.ICON_ERROR);

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,20 +1026,22 @@ private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int d
10261026

10271027
private void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY,
10281028
int destWidth, int destHeight, int imageZoom, int scaledImageZoom) {
1029-
Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), scaledImageZoom);
1029+
Rectangle scaledBounds = image.getBounds(scaledImageZoom);
1030+
Rectangle unScaledBound = image.getBounds();
1031+
float scalingFactor = (float) scaledBounds.height / unScaledBound.height;
1032+
Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight),(int) (scalingFactor * 100));
10301033
Rectangle dest = DPIUtil.scaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom);
10311034
if (scaledImageZoom != 100) {
10321035
/*
10331036
* This is a HACK! Due to rounding errors at fractional scale factors,
10341037
* the coordinates may be slightly off. The workaround is to restrict
10351038
* coordinates to the allowed bounds.
10361039
*/
1037-
Rectangle b = image.getBounds(scaledImageZoom);
1038-
int errX = src.x + src.width - b.width;
1039-
int errY = src.y + src.height - b.height;
1040+
int errX = src.x + src.width - scaledBounds.width;
1041+
int errY = src.y + src.height - scaledBounds.height;
10401042
if (errX != 0 || errY != 0) {
10411043
if (errX <= scaledImageZoom / 100 && errY <= scaledImageZoom / 100) {
1042-
src.intersect(b);
1044+
src.intersect(scaledBounds);
10431045
} else {
10441046
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
10451047
}

0 commit comments

Comments
 (0)