|
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