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 1c85beb57d..4894a5de70 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
@@ -15,16 +15,13 @@
import java.util.*;
-import java.util.List;
import java.util.function.*;
-import java.util.stream.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.Image.*;
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
@@ -1178,18 +1175,52 @@ private class DrawScalingImageToImageOperation extends ImageOperation {
@Override
void apply() {
+ draw(getImage(), source.x, source.y, source.width, source.height, destination.x, destination.y, destination.width, destination.height);
+ }
+
+ private void draw(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
int gcZoom = getZoom();
- int srcImageZoom = calculateZoomForImage(gcZoom, source.width, source.height, destination.width, destination.height);
- drawImage(getImage(), source.x, source.y, source.width, source.height, destination.x, destination.y, destination.width, destination.height, gcZoom, srcImageZoom);
+ int requestedImageZoom = calculateZoomForImage(gcZoom, source.width, source.height, destination.width, destination.height);
+
+ Rectangle src = new Rectangle(srcX, srcY, srcWidth, srcHeight);
+ Rectangle destPixels = Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX, destY, destWidth, destHeight), gcZoom);
+ Rectangle fullImageBounds = image.getBounds();
+ Rectangle requestedFullImageBoundsPixels = Win32DPIUtils.pointToPixel(drawable, fullImageBounds, requestedImageZoom);
+
+ image.executeOnImageHandleAtBestFittingSize((tempHandle) -> {
+ Rectangle srcPixels = computeSourceRectangle(tempHandle, fullImageBounds, src);
+ drawImage(image, srcPixels.x, srcPixels.y, srcPixels.width, srcPixels.height, destPixels.x, destPixels.y, destPixels.width,
+ destPixels.height, false, tempHandle);
+ }, requestedFullImageBoundsPixels.width, requestedFullImageBoundsPixels.height);
}
- private Collection getAllCurrentMonitorZooms() {
- if (device instanceof Display display) {
- return Arrays.stream(display.getMonitors())
- .map(Monitor::getZoom)
- .collect(Collectors.toSet());
+ private Rectangle computeSourceRectangle(ImageHandle imageHandle, Rectangle fullImageBounds, Rectangle src) {
+ /*
+ * The point values (x, y, width, height) of the source "part" in points will be
+ * computed to pixels depending on the factor of the full image bounds to the
+ * actual OS handle size that will be used.
+ */
+ float scaleFactor = Math.min(1f * imageHandle.width() / fullImageBounds.width, 1f * imageHandle.height() / fullImageBounds.height);
+ int closestZoomOfHandle = Math.round(scaleFactor * 100);
+ Rectangle srcPixels = Win32DPIUtils.pointToPixel(drawable, src, closestZoomOfHandle);
+
+ if (closestZoomOfHandle != 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.
+ */
+ int errX = srcPixels.x + srcPixels.width - imageHandle.width();
+ int errY = srcPixels.y + srcPixels.height - imageHandle.height();
+ if (errX != 0 || errY != 0) {
+ if (errX <= closestZoomOfHandle / 100 && errY <= closestZoomOfHandle / 100) {
+ srcPixels.intersect(new Rectangle(0, 0, imageHandle.width(), imageHandle.height()));
+ } else {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ }
}
- return Collections.emptySet();
+ return srcPixels;
}
private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int destWidth, int destHeight) {
@@ -1205,15 +1236,9 @@ private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int d
return gcZoom;
}
- float imageScaleFactor = 1f * destWidth / srcWidth;
+ float imageScaleFactor = Math.max(1f * destWidth / srcWidth, 1f * destHeight / srcHeight);
int imageZoom = Math.round(gcZoom * imageScaleFactor);
- if (getAllCurrentMonitorZooms().contains(imageZoom)) {
- return imageZoom;
- }
- if (imageZoom > 150) {
- return 200;
- }
- return 100;
+ return imageZoom;
}
}
@@ -1241,30 +1266,6 @@ private void drawImage(Image image, int destX, int destY, int destWidth, int des
}, destPixels.width, destPixels.height);
}
-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 = Win32DPIUtils.pointToPixel(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), scaledImageZoom);
- Rectangle dest = Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom);
- 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(scaledImageZoom);
- int errX = src.x + src.width - b.width;
- int errY = src.y + src.height - b.height;
- if (errX != 0 || errY != 0) {
- 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, image.getHandle(scaledImageZoom, data.nativeZoom));
-}
-
private class DrawImageToImageOperation extends ImageOperation {
private final Rectangle source;
private final Rectangle destination;