|
14 | 14 | package org.eclipse.swt.graphics;
|
15 | 15 |
|
16 | 16 |
|
| 17 | +import java.util.*; |
| 18 | +import java.util.stream.*; |
| 19 | + |
17 | 20 | import org.eclipse.swt.*;
|
18 | 21 | import org.eclipse.swt.internal.*;
|
19 | 22 | import org.eclipse.swt.internal.gdip.*;
|
20 | 23 | import org.eclipse.swt.internal.win32.*;
|
| 24 | +import org.eclipse.swt.widgets.*; |
21 | 25 |
|
22 | 26 | /**
|
23 | 27 | * Class <code>GC</code> is where all of the drawing capabilities that are
|
@@ -985,31 +989,70 @@ public void drawImage (Image image, int srcX, int srcY, int srcWidth, int srcHei
|
985 | 989 | if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
|
986 | 990 | if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
|
987 | 991 |
|
988 |
| - int imageZoom = getZoom(); |
989 |
| - Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), imageZoom); |
| 992 | + int gcZoom = getZoom(); |
| 993 | + int srcImageZoom = calculateZoomForImage(gcZoom, srcWidth, srcHeight, destWidth, destHeight); |
| 994 | + drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, gcZoom, srcImageZoom); |
| 995 | +} |
| 996 | + |
| 997 | +private Collection<Integer> getAllCurrentMonitorZooms() { |
| 998 | + if (device instanceof Display display) { |
| 999 | + return Arrays.stream(display.getMonitors()) |
| 1000 | + .map(Monitor::getZoom) |
| 1001 | + .collect(Collectors.toSet()); |
| 1002 | + } |
| 1003 | + return Collections.emptySet(); |
| 1004 | +} |
| 1005 | + |
| 1006 | +private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int destWidth, int destHeight) { |
| 1007 | + if (srcWidth == 1 && srcHeight == 1) { |
| 1008 | + // One pixel images can use the GC zoom |
| 1009 | + return gcZoom; |
| 1010 | + } |
| 1011 | + if (destWidth == srcWidth && destHeight == srcHeight) { |
| 1012 | + // unscaled images can use the GC zoom |
| 1013 | + return gcZoom; |
| 1014 | + } |
| 1015 | + |
| 1016 | + float imageScaleFactor = 1f * destWidth / srcWidth; |
| 1017 | + int imageZoom = Math.round(gcZoom * imageScaleFactor); |
| 1018 | + if (getAllCurrentMonitorZooms().contains(imageZoom)) { |
| 1019 | + return imageZoom; |
| 1020 | + } |
| 1021 | + if (imageZoom > 150) { |
| 1022 | + return 200; |
| 1023 | + } |
| 1024 | + return 100; |
| 1025 | +} |
| 1026 | + |
| 1027 | +private void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, |
| 1028 | + int destWidth, int destHeight, int imageZoom, int scaledImageZoom) { |
| 1029 | + Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), scaledImageZoom); |
990 | 1030 | Rectangle dest = DPIUtil.scaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom);
|
991 |
| - if (imageZoom != 100) { |
| 1031 | + if (scaledImageZoom != 100) { |
992 | 1032 | /*
|
993 | 1033 | * This is a HACK! Due to rounding errors at fractional scale factors,
|
994 | 1034 | * the coordinates may be slightly off. The workaround is to restrict
|
995 | 1035 | * coordinates to the allowed bounds.
|
996 | 1036 | */
|
997 |
| - Rectangle b = image.getBounds(imageZoom); |
| 1037 | + Rectangle b = image.getBounds(scaledImageZoom); |
998 | 1038 | int errX = src.x + src.width - b.width;
|
999 | 1039 | int errY = src.y + src.height - b.height;
|
1000 | 1040 | if (errX != 0 || errY != 0) {
|
1001 |
| - if (errX <= imageZoom / 100 && errY <= imageZoom / 100) { |
| 1041 | + if (errX <= scaledImageZoom / 100 && errY <= scaledImageZoom / 100) { |
1002 | 1042 | src.intersect(b);
|
1003 | 1043 | } else {
|
1004 | 1044 | SWT.error (SWT.ERROR_INVALID_ARGUMENT);
|
1005 | 1045 | }
|
1006 | 1046 | }
|
1007 | 1047 | }
|
1008 |
| - drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false); |
| 1048 | + drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false, scaledImageZoom); |
1009 | 1049 | }
|
1010 | 1050 |
|
1011 | 1051 | void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
|
1012 |
| - int imageZoom = getZoom(); |
| 1052 | + drawImage(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, getZoom()); |
| 1053 | +} |
| 1054 | + |
| 1055 | +void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imageZoom) { |
1013 | 1056 | if (data.gdipGraphics != 0) {
|
1014 | 1057 | //TODO - cache bitmap
|
1015 | 1058 | long [] gdipImage = srcImage.createGdipImage(imageZoom);
|
|
0 commit comments