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..ac25be042d 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; } } @@ -1233,7 +1215,7 @@ void apply() { } 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), + Rectangle destPixels= Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX , destY, destWidth , destHeight), imageZoom); image.executeOnImageHandleAtBestFittingSize(tempHandle -> { drawImage(image, 0, 0, tempHandle.width(), tempHandle.height(), destPixels.x, destPixels.y, @@ -1243,26 +1225,48 @@ private void drawImage(Image image, int destX, int destY, int destWidth, int des 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); 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); + }, fullImageBoundsPixels.width, fullImageBoundsPixels.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 { + /* + * the achieved handle with its drawings has not the required size, thus we calculate the zoom of the handle + * + * with respect to the full 100% image. The point values (x,y,width,height) of the source "part" of the full image will + * be computed to pixels by this zoom. + */ + 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 {