From b629e45deca3f6c8fe77d3579339d0553a4c4e7c Mon Sep 17 00:00:00 2001 From: al-noori Date: Tue, 6 Jan 2026 17:19:09 +0100 Subject: [PATCH] GC#drawImage methods now consider applied Transformations #2919 If a transform is applied via the GC, then both drawImage methods consider now the best fitting handle by requesting it through the width/height of the full image scaled by the scaleFactor (relating destination width/height to source width/height) times the width/height scaling induced by the transformation. Contributes to https://github.com/eclipse-platform/eclipse.platform.swt/issues/2919 --- .../win32/org/eclipse/swt/graphics/GC.java | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) 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 4894a5de70..4a2663e953 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 @@ -521,6 +521,20 @@ void disposeAll() { image.removeOnDisposeListener(disposeCallback); super.disposeAll(); } + + protected float calculateTransformationScale() { + Transform current = new Transform(device); + getTransform(current); + float[] m = new float[6]; + current.getElements(m); + // this calculates the effective length in x and y + // direction without being affected by the rotation + // of the transformation + 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 class CopyAreaToImageOperation extends ImageOperation { @@ -1181,11 +1195,13 @@ void apply() { 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 requestedImageZoom = calculateZoomForImage(gcZoom, source.width, source.height, destination.width, destination.height); + float transformationScale = calculateTransformationScale(); + int scaledImageZoomWithTransform = Math.round(transformationScale * requestedImageZoom); 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); + Rectangle requestedFullImageBoundsPixels = Win32DPIUtils.pointToPixel(drawable, fullImageBounds, scaledImageZoomWithTransform); image.executeOnImageHandleAtBestFittingSize((tempHandle) -> { Rectangle srcPixels = computeSourceRectangle(tempHandle, fullImageBounds, src); @@ -1252,18 +1268,22 @@ private class DrawScaledImageOperation extends ImageOperation { @Override void apply() { - int gcZoom = getZoom(); - drawImage(getImage(), destination.x, destination.y, destination.width, destination.height, gcZoom); + draw(getImage(), destination.x, destination.y, destination.width, destination.height); } -} -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), - imageZoom); - 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); + private void draw(Image image, int destX, int destY, int destWidth, int destHeight) { + int gcZoom = getZoom(); + float transformationScale = calculateTransformationScale(); + int scaledImageZoomWithTransform = Math.round(transformationScale * gcZoom); + Rectangle destPixels = Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX , destY, destWidth , destHeight), gcZoom); + 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); + }, destPixelsScaledWithTransform.width, destPixelsScaledWithTransform.height); + } } private class DrawImageToImageOperation extends ImageOperation {