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..6f48044ec4 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
@@ -1183,15 +1180,6 @@ void apply() {
drawImage(getImage(), source.x, source.y, source.width, source.height, destination.x, destination.y, destination.width, destination.height, 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
@@ -1205,15 +1193,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;
}
}
@@ -1232,37 +1214,73 @@ void apply() {
}
}
+private float calculateTransformationScale() {
+ Transform current = new Transform(device);
+ getTransform(current);
+ float[] m = new float[6];
+ current.getElements(m);
+ float scaleWidth = (float) Math.hypot(m[0], m[2]);
+ float scaleHeight = (float) Math.hypot(m[1], m[3]);
+ current.dispose();
+ return Math.max(scaleWidth, scaleHeight);
+}
+
private void drawImage(Image image, int destX, int destY, int destWidth, int destHeight, int imageZoom) {
- Rectangle destPixels = Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX, destY, destWidth, destHeight),
+ float transformationScale = calculateTransformationScale();
+ int scaledImageZoomWithTransform = Math.round(transformationScale * imageZoom);
+ Rectangle destPixels = Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX , destY, destWidth , destHeight),
imageZoom);
+ Rectangle destPixelsScaledWithTransform = Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX , destY, destWidth , destHeight),
+ scaledImageZoomWithTransform);
+
image.executeOnImageHandleAtBestFittingSize(tempHandle -> {
drawImage(image, 0, 0, tempHandle.width(), tempHandle.height(), destPixels.x, destPixels.y,
destPixels.width, destPixels.height, false, tempHandle);
- }, destPixels.width, destPixels.height);
+ }, destPixelsScaledWithTransform.width, destPixelsScaledWithTransform.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);
+ Rectangle srcPixels = Win32DPIUtils.pointToPixel(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), scaledImageZoom);
+ Rectangle destPixels = Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom);
+ Rectangle fullImageBounds = image.getBounds();
+ Rectangle fullImageBoundsPixels = Win32DPIUtils.pointToPixel(drawable, fullImageBounds, scaledImageZoom);
+ Rectangle src = new Rectangle(srcX, srcY, srcWidth, srcHeight);
+ float transformationScale = calculateTransformationScale();
+ int scaledImageZoomWithTransform = Math.round(transformationScale * scaledImageZoom);
+ Rectangle fullImageBoundsScaledWithTransform = Win32DPIUtils.pointToPixel(drawable, fullImageBounds, scaledImageZoomWithTransform);
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;
+ int errX = srcPixels.x + srcPixels.width - fullImageBoundsPixels.width;
+ int errY = srcPixels.y + srcPixels.height - fullImageBoundsPixels.height;
if (errX != 0 || errY != 0) {
if (errX <= scaledImageZoom / 100 && errY <= scaledImageZoom / 100) {
- src.intersect(b);
+ srcPixels.intersect(fullImageBoundsPixels);
} 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));
+ image.executeOnImageHandleAtBestFittingSize((tempHandle) -> {
+ Rectangle newSrcPixels = computeSourceRectangle(tempHandle, fullImageBounds, fullImageBoundsPixels, src, srcPixels);
+ drawImage(image, newSrcPixels.x, newSrcPixels.y, newSrcPixels.width, newSrcPixels.height, destPixels.x, destPixels.y, destPixels.width,
+ destPixels.height, false, tempHandle);
+ }, fullImageBoundsScaledWithTransform.width, fullImageBoundsScaledWithTransform.height);
+}
+
+private Rectangle computeSourceRectangle(ImageHandle imageHandle, Rectangle fullImageBounds, Rectangle fullImageBoundsPixels, Rectangle src, Rectangle srcPixels) {
+ if (new Rectangle(0, 0, imageHandle.width(), imageHandle.height()).equals(fullImageBoundsPixels)) {
+ return srcPixels;
+ } else {
+ // handle has not the required size, so source must be scaled with respect to handle size
+ float scaleFactor = Math.max(1f * imageHandle.width() / fullImageBounds.width, 1f * imageHandle.height() / fullImageBounds.height);
+ int closestZoomOfHandle = Math.round(scaleFactor * 100);
+ return Win32DPIUtils.pointToPixel(drawable, src, closestZoomOfHandle);
+ }
}
private class DrawImageToImageOperation extends ImageOperation {