Skip to content

Commit 512c3a9

Browse files
committed
[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 4df99ba commit 512c3a9

File tree

2 files changed

+44
-19
lines changed

2 files changed

+44
-19
lines changed

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

+28-19
Original file line numberDiff line numberDiff line change
@@ -986,30 +986,39 @@ public void drawImage (Image image, int srcX, int srcY, int srcWidth, int srcHei
986986
if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
987987

988988
int imageZoom = getZoom();
989-
Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), imageZoom);
990-
Rectangle dest = DPIUtil.scaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom);
991-
if (imageZoom != 100) {
992-
/*
993-
* This is a HACK! Due to rounding errors at fractional scale factors,
994-
* the coordinates may be slightly off. The workaround is to restrict
995-
* coordinates to the allowed bounds.
996-
*/
997-
Rectangle b = image.getBounds(imageZoom);
998-
int errX = src.x + src.width - b.width;
999-
int errY = src.y + src.height - b.height;
1000-
if (errX != 0 || errY != 0) {
1001-
if (errX <= imageZoom / 100 && errY <= imageZoom / 100) {
1002-
src.intersect(b);
1003-
} else {
1004-
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
989+
float imageScaleFactor = 1f*destWidth/srcWidth;
990+
int scaledImageZoom = Math.round(imageZoom*imageScaleFactor);
991+
992+
image.applyUsingAnyHandle(scaledImageZoom, (imageHandle) -> {
993+
Rectangle src = DPIUtil.scaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), scaledImageZoom);
994+
Rectangle dest = DPIUtil.scaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), imageZoom);
995+
996+
if (scaledImageZoom != 100) {
997+
/*
998+
* This is a HACK! Due to rounding errors at fractional scale factors,
999+
* the coordinates may be slightly off. The workaround is to restrict
1000+
* coordinates to the allowed bounds.
1001+
*/
1002+
Rectangle b = image.getBounds(scaledImageZoom);
1003+
int errX = src.x + src.width - b.width;
1004+
int errY = src.y + src.height - b.height;
1005+
if (errX != 0 || errY != 0) {
1006+
if (errX <= scaledImageZoom / 100 && errY <= scaledImageZoom / 100) {
1007+
src.intersect(b);
1008+
} else {
1009+
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
1010+
}
10051011
}
10061012
}
1007-
}
1008-
drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false);
1013+
drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false, scaledImageZoom);
1014+
});
10091015
}
10101016

10111017
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();
1018+
drawImage(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, getZoom());
1019+
}
1020+
1021+
void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imageZoom) {
10131022
if (data.gdipGraphics != 0) {
10141023
//TODO - cache bitmap
10151024
long [] gdipImage = srcImage.createGdipImage(imageZoom);

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

+16
Original file line numberDiff line numberDiff line change
@@ -1832,6 +1832,22 @@ <T> T applyUsingAnyHandle(Function<ImageHandle, T> function) {
18321832
return function.apply(zoomLevelToImageHandle.values().iterator().next());
18331833
}
18341834

1835+
void applyUsingAnyHandle(int zoom, Consumer<Long> consumer) {
1836+
ImageHandle imageHandle = zoomLevelToImageHandle.get(zoom);
1837+
if (imageHandle!= null) {
1838+
consumer.accept(imageHandle.handle);
1839+
return;
1840+
}
1841+
1842+
ImageHandle temporaryHandle = this.imageProvider.newImageHandle(zoom);
1843+
try {
1844+
consumer.accept(temporaryHandle.handle);
1845+
return;
1846+
} finally {
1847+
temporaryHandle.destroy();
1848+
}
1849+
}
1850+
18351851
/**
18361852
* Invokes platform specific functionality to allocate a new image.
18371853
* <p>

0 commit comments

Comments
 (0)