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 e9fd414034..089f87cc05 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 @@ -1183,15 +1183,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 @@ -1207,13 +1198,7 @@ private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int d float imageScaleFactor = 1f * destWidth / srcWidth; int imageZoom = Math.round(gcZoom * imageScaleFactor); - if (getAllCurrentMonitorZooms().contains(imageZoom)) { - return imageZoom; - } - if (imageZoom > 150) { - return 200; - } - return 100; + return imageZoom; } } @@ -1243,6 +1228,7 @@ 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); if (scaledImageZoom != 100) { @@ -1262,7 +1248,31 @@ private void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHei } } } - drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false, image.getHandle(scaledImageZoom, data.nativeZoom)); + Rectangle fullImageBounds = image.getBounds(); + Rectangle targetSrc = Win32DPIUtils.pointToPixel(drawable, fullImageBounds, scaledImageZoom); + Rectangle startSrc = new Rectangle(srcX, srcY, srcWidth, srcHeight); + image.executeOnImageHandleAtBestFittingSizeAtZoom((tempHandle) -> { + Rectangle src1 = computeSourceRectangle(tempHandle, fullImageBounds, targetSrc, startSrc, src); + drawImage(image, src1.x, src1.y, src1.width, src1.height, dest.x, dest.y, dest.width, + dest.height, false, tempHandle); + }, scaledImageZoom); + +} + +private Rectangle computeSourceRectangle(ImageHandle imageHandle, Rectangle fullImageBounds, Rectangle targetSrc, Rectangle startSrc, Rectangle srcPart) { + if (new Rectangle(0, 0, imageHandle.getWidth(), imageHandle.getHeight()).equals(targetSrc)) { + return srcPart; + } 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 = 1f * imageHandle.getWidth() / fullImageBounds.width; + int closestZoomOfHandle = Math.round(scaleFactor * 100); + return Win32DPIUtils.pointToPixel(drawable, startSrc, closestZoomOfHandle); + } } private class DrawImageToImageOperation extends ImageOperation { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java index a580d24c3c..a8ee2c8649 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java @@ -179,6 +179,17 @@ private Optional createHandleAtExactSize(int width, int height) { return Optional.empty(); } + public ImageHandle getOrCreateImageHandleAtClosestSizeAtZoom(int scaledZoom) { + scaledZoom = DPIUtil.getZoomForAutoscaleProperty(scaledZoom); + ImageHandle bestFittingHandle = zoomLevelToImageHandle.get(scaledZoom); + if (bestFittingHandle == null) { + ImageData bestFittingImageData = imageProvider.loadImageData(scaledZoom).element(); + ImageData adaptedData = adaptImageDataIfDisabledOrGray(bestFittingImageData); + bestFittingHandle = init(adaptedData, -1); + } + return bestFittingHandle; + } + private ImageHandle getOrCreateImageHandleAtClosestSize(int widthHint, int heightHint) { Rectangle bounds = getBounds(100); int imageZoomForWidth = 100 * widthHint / bounds.width; @@ -880,6 +891,15 @@ void executeOnImageHandleAtBestFittingSize(Consumer handleAtSizeCon handleAtSizeConsumer.accept(imageHandle); } +void executeOnImageHandleAtBestFittingSizeAtZoom(Consumer handleAtSizeConsumer, int scaledZoom) { + ImageHandle imageHandle = lastRequestedHandle.getOrCreateImageHandleAtClosestSizeAtZoom(scaledZoom); + handleAtSizeConsumer.accept(imageHandle); +} +void executeOnImageHandleAtSizeOrZoom(BiConsumer handleAtSizeConsumer, int targetWidth, int targetHeight, int zoom) { + ImageHandle imageHandle = lastRequestedHandle.getOrCreateImageHandleAtClosestSizeAtZoom(zoom); + handleAtSizeConsumer.accept(imageHandle, new Point(imageHandle.getWidth(), imageHandle.getHeight())); +} + /** * IMPORTANT: This method is not part of the public * API for Image. It is marked public only so that it diff --git a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet10.java b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet10.java index bedaca7f4f..31138fe18a 100644 --- a/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet10.java +++ b/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet10.java @@ -32,18 +32,18 @@ public static void main(String[] args) { shell.setText("Advanced Graphics"); FontData fd = shell.getFont().getFontData()[0]; final Font font = new Font(display, fd.getName(), 60, SWT.BOLD | SWT.ITALIC); - final Image image = new Image(display, 640, 480); - final Rectangle rect = image.getBounds(); - GC gc = new GC(image); - gc.setBackground(display.getSystemColor(SWT.COLOR_RED)); - gc.fillOval(rect.x, rect.y, rect.width, rect.height); - gc.dispose(); + ImageGcDrawer igc = (gc, w, h) -> { + gc.setBackground(display.getSystemColor(SWT.COLOR_RED)); + gc.fillOval(0, 0, w, h); + }; + Image image = new Image(display, igc, 640, 480); + Rectangle rect = image.getBounds(); shell.addListener(SWT.Paint, event -> { GC gc1 = event.gc; Transform tr = new Transform(display); tr.translate(50, 120); tr.rotate(-30); - gc1.drawImage(image, 0, 0, rect.width, rect.height, 0, 0, rect.width / 2, rect.height / 2); + gc1.drawImage(image, 0, 0, rect.width / 2, rect.height / 2); gc1.setAlpha(100); gc1.setTransform(tr); Path path = new Path(display);