diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
index ddaa6da5964..9edadddfacf 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java
@@ -14,10 +14,14 @@
package org.eclipse.swt.graphics;
+import java.util.*;
+import java.util.stream.*;
+
import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gdip.*;
import org.eclipse.swt.internal.win32.*;
+import org.eclipse.swt.widgets.*;
/**
* Class GC
is where all of the drawing capabilities that are
@@ -985,31 +989,70 @@ public void drawImage (Image image, int srcX, int srcY, int srcWidth, int srcHei
if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- int imageZoom = getZoom();
- Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), imageZoom);
+ int gcZoom = getZoom();
+ int srcImageZoom = calculateZoomForImage(gcZoom, srcWidth, srcHeight, destWidth, destHeight);
+ drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, gcZoom, srcImageZoom);
+}
+
+private Collection getAllCurrentMonitorZooms() {
+ if (device instanceof Display display) {
+ return Arrays.stream(display.getMonitors())
+ .map(Monitor::getZoom)
+ .collect(Collectors.toSet());
+ }
+ return Collections.emptySet();
+}
+
+private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int destWidth, int destHeight) {
+ if (srcWidth == 1 && srcHeight == 1) {
+ // One pixel images can use the GC zoom
+ return gcZoom;
+ }
+ if (destWidth == srcWidth && destHeight == srcHeight) {
+ // unscaled images can use the GC zoom
+ return gcZoom;
+ }
+
+ float imageScaleFactor = 1f * destWidth / srcWidth;
+ int imageZoom = Math.round(gcZoom * imageScaleFactor);
+ if (getAllCurrentMonitorZooms().contains(imageZoom)) {
+ return imageZoom;
+ }
+ if (imageZoom > 150) {
+ return 200;
+ }
+ return 100;
+}
+
+private void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY,
+ int destWidth, int destHeight, int imageZoom, int scaledImageZoom) {
+ Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), scaledImageZoom);
Rectangle dest = DPIUtil.scaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom);
- if (imageZoom != 100) {
+ if (scaledImageZoom != 100) {
/*
* This is a HACK! Due to rounding errors at fractional scale factors,
* the coordinates may be slightly off. The workaround is to restrict
* coordinates to the allowed bounds.
*/
- Rectangle b = image.getBounds(imageZoom);
+ Rectangle b = image.getBounds(scaledImageZoom);
int errX = src.x + src.width - b.width;
int errY = src.y + src.height - b.height;
if (errX != 0 || errY != 0) {
- if (errX <= imageZoom / 100 && errY <= imageZoom / 100) {
+ if (errX <= scaledImageZoom / 100 && errY <= scaledImageZoom / 100) {
src.intersect(b);
} else {
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
}
}
}
- drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false);
+ drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false, scaledImageZoom);
}
void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
- int imageZoom = getZoom();
+ drawImage(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, getZoom());
+}
+
+void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imageZoom) {
if (data.gdipGraphics != 0) {
//TODO - cache bitmap
long [] gdipImage = srcImage.createGdipImage(imageZoom);