Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@


import java.util.*;
import java.util.List;
import java.util.function.*;
import java.util.stream.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.Image.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gdip.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.widgets.*;

/**
* Class <code>GC</code> is where all of the drawing capabilities that are
Expand Down Expand Up @@ -1178,18 +1175,52 @@ private class DrawScalingImageToImageOperation extends ImageOperation {

@Override
void apply() {
draw(getImage(), source.x, source.y, source.width, source.height, destination.x, destination.y, destination.width, destination.height);
}

private void draw(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
int gcZoom = getZoom();
int srcImageZoom = calculateZoomForImage(gcZoom, source.width, source.height, destination.width, destination.height);
drawImage(getImage(), source.x, source.y, source.width, source.height, destination.x, destination.y, destination.width, destination.height, gcZoom, srcImageZoom);
int requestedImageZoom = calculateZoomForImage(gcZoom, source.width, source.height, destination.width, destination.height);

Rectangle src = new Rectangle(srcX, srcY, srcWidth, srcHeight);
Rectangle destPixels = Win32DPIUtils.pointToPixel(drawable, new Rectangle(destX, destY, destWidth, destHeight), gcZoom);
Rectangle fullImageBounds = image.getBounds();
Rectangle requestedFullImageBoundsPixels = Win32DPIUtils.pointToPixel(drawable, fullImageBounds, requestedImageZoom);

image.executeOnImageHandleAtBestFittingSize((tempHandle) -> {
Rectangle srcPixels = computeSourceRectangle(tempHandle, fullImageBounds, src);
drawImage(image, srcPixels.x, srcPixels.y, srcPixels.width, srcPixels.height, destPixels.x, destPixels.y, destPixels.width,
destPixels.height, false, tempHandle);
}, requestedFullImageBoundsPixels.width, requestedFullImageBoundsPixels.height);
}

private Collection<Integer> getAllCurrentMonitorZooms() {
if (device instanceof Display display) {
return Arrays.stream(display.getMonitors())
.map(Monitor::getZoom)
.collect(Collectors.toSet());
private Rectangle computeSourceRectangle(ImageHandle imageHandle, Rectangle fullImageBounds, Rectangle src) {
/*
* The point values (x, y, width, height) of the source "part" in points will be
* computed to pixels depending on the factor of the full image bounds to the
* actual OS handle size that will be used.
*/
float scaleFactor = Math.min(1f * imageHandle.width() / fullImageBounds.width, 1f * imageHandle.height() / fullImageBounds.height);
int closestZoomOfHandle = Math.round(scaleFactor * 100);
Rectangle srcPixels = Win32DPIUtils.pointToPixel(drawable, src, closestZoomOfHandle);

if (closestZoomOfHandle != 100) {
/*
* This is a HACK! Due to rounding errors at fractional scale factors,
* the coordinates may be slightly off. The workaround is to restrict
* coordinates to the allowed bounds.
*/
int errX = srcPixels.x + srcPixels.width - imageHandle.width();
int errY = srcPixels.y + srcPixels.height - imageHandle.height();
if (errX != 0 || errY != 0) {
if (errX <= closestZoomOfHandle / 100 && errY <= closestZoomOfHandle / 100) {
srcPixels.intersect(new Rectangle(0, 0, imageHandle.width(), imageHandle.height()));
} else {
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
}
}
}
return Collections.emptySet();
return srcPixels;
}

private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int destWidth, int destHeight) {
Expand All @@ -1205,15 +1236,9 @@ private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int d
return gcZoom;
}

float imageScaleFactor = 1f * destWidth / srcWidth;
float imageScaleFactor = Math.max(1f * destWidth / srcWidth, 1f * destHeight / srcHeight);
int imageZoom = Math.round(gcZoom * imageScaleFactor);
if (getAllCurrentMonitorZooms().contains(imageZoom)) {
return imageZoom;
}
if (imageZoom > 150) {
return 200;
}
return 100;
return imageZoom;
}
}

Expand Down Expand Up @@ -1241,30 +1266,6 @@ private void drawImage(Image image, int destX, int destY, int destWidth, int des
}, destPixels.width, destPixels.height);
}

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) {
/*
* This is a HACK! Due to rounding errors at fractional scale factors,
* the coordinates may be slightly off. The workaround is to restrict
* coordinates to the allowed bounds.
*/
Rectangle b = image.getBounds(scaledImageZoom);
int errX = src.x + src.width - b.width;
int errY = src.y + src.height - b.height;
if (errX != 0 || errY != 0) {
if (errX <= scaledImageZoom / 100 && errY <= scaledImageZoom / 100) {
src.intersect(b);
} else {
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
}
}
}
drawImage(image, src.x, src.y, src.width, src.height, dest.x, dest.y, dest.width, dest.height, false, image.getHandle(scaledImageZoom, data.nativeZoom));
}

private class DrawImageToImageOperation extends ImageOperation {
private final Rectangle source;
private final Rectangle destination;
Expand Down
Loading