Skip to content

Commit 63048a2

Browse files
akoch-yattaHeikoKlare
authored andcommitted
[win32] Choose best Image handle drawing with GC
This commit adapts the drawImage method in GC in the windows implementation for copying and (probably) scaling an area from a source image into the GC target. With the Image supporting multiple handles now, the handle from the source image is no longer chosen by the zoom context of the GC but from the target size, e.g. if an image should be drawn with a scale of 2 on a 100% monitor, it might provide better results to use an image handle fitting for 200%.
1 parent 0642bb4 commit 63048a2

File tree

1 file changed

+50
-7
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+50
-7
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java

+50-7
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
package org.eclipse.swt.graphics;
1515

1616

17+
import java.util.*;
18+
import java.util.stream.*;
19+
1720
import org.eclipse.swt.*;
1821
import org.eclipse.swt.internal.*;
1922
import org.eclipse.swt.internal.gdip.*;
2023
import org.eclipse.swt.internal.win32.*;
24+
import org.eclipse.swt.widgets.*;
2125

2226
/**
2327
* 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
985989
if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
986990
if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
987991

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);
9901030
Rectangle dest = DPIUtil.scaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom);
991-
if (imageZoom != 100) {
1031+
if (scaledImageZoom != 100) {
9921032
/*
9931033
* This is a HACK! Due to rounding errors at fractional scale factors,
9941034
* the coordinates may be slightly off. The workaround is to restrict
9951035
* coordinates to the allowed bounds.
9961036
*/
997-
Rectangle b = image.getBounds(imageZoom);
1037+
Rectangle b = image.getBounds(scaledImageZoom);
9981038
int errX = src.x + src.width - b.width;
9991039
int errY = src.y + src.height - b.height;
10001040
if (errX != 0 || errY != 0) {
1001-
if (errX <= imageZoom / 100 && errY <= imageZoom / 100) {
1041+
if (errX <= scaledImageZoom / 100 && errY <= scaledImageZoom / 100) {
10021042
src.intersect(b);
10031043
} else {
10041044
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
10051045
}
10061046
}
10071047
}
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);
10091049
}
10101050

10111051
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) {
10131056
if (data.gdipGraphics != 0) {
10141057
//TODO - cache bitmap
10151058
long [] gdipImage = srcImage.createGdipImage(imageZoom);

0 commit comments

Comments
 (0)