Skip to content

Ensure DrawImage deals with scenario ImageData not linearly scaled #2250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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 @@ -25,6 +25,90 @@
@ExtendWith(WithMonitorSpecificScalingExtension.class)
class ImagesWin32Tests {

@Test
public void test_imageScaledFrom150_when125PercentImageUnavailable() {
Display display = Display.getDefault();
GC gc = new GC(display);
GCData gcData = gc.getGCData();
gcData.nativeZoom = 125;
ImageDataProvider imageDataProviderReturnsNullAt125 = zoom -> {
if (zoom == 125) {
return null;
}
float scaleFactor = zoom / 100f;
int scaledWidth = Math.round(16 * scaleFactor);
int scaledHeight = Math.round(16 * scaleFactor);
return new ImageData(scaledWidth, scaledHeight, 1, new PaletteData(new RGB(255, 0, 0)));
};
Image image = new Image(display, imageDataProviderReturnsNullAt125);
gc.drawImage(image, 0, 0, 16, 16, 0, 0, 16, 16);
gc.dispose();
image.dispose();
}

@Test
public void test_imageScaledFrom100_when125And150PercentImagesUnavailable() {
Display display = Display.getDefault();
GC gc = new GC(display);
GCData gcData = gc.getGCData();
gcData.nativeZoom = 125;
ImageDataProvider imageDataProviderReturnsNullAt125and150 = zoom -> {
if (zoom == 125) {
return null;
}
if (zoom == 150) {
return null;
}
float scaleFactor = zoom / 100f;
int scaledWidth = Math.round(16 * scaleFactor);
int scaledHeight = Math.round(16 * scaleFactor);
return new ImageData(scaledWidth, scaledHeight, 1, new PaletteData(new RGB(255, 0, 0)));
};
Image image = new Image(display, imageDataProviderReturnsNullAt125and150);
gc.drawImage(image, 0, 0, 16, 16, 0, 0, 16, 16);
gc.dispose();
image.dispose();
}

@Test
public void test_drawImage_when130PercentImageUnavailable() {
Display display = Display.getDefault();
GC gc = new GC(display);
GCData gcData = gc.getGCData();
gcData.nativeZoom = 130;
ImageDataProvider imageDataProviderReturnsNullAt125 = zoom -> {
if (zoom == 130){
return null;
}
float scaleFactor = zoom / 100f;
int scaledWidth = Math.round(16 * scaleFactor);
int scaledHeight = Math.round(16 * scaleFactor);
return new ImageData(scaledWidth, scaledHeight, 1, new PaletteData(new RGB(255, 0, 0)));
};
Image image = new Image(display, imageDataProviderReturnsNullAt125);
gc.drawImage(image, 0, 0, 16, 16, 0, 0, 16, 16);
gc.dispose();
image.dispose();
}

@Test
public void test_drawImageUsesWronglyScaledImageDataProvider() {
Display display = Display.getDefault();
GC gc = new GC(display);
GCData gcData = gc.getGCData();
gcData.nativeZoom = 125;
ImageDataProvider incorrectlyScaledimageDataProvider = zoom -> {
int scaleFactor = zoom / 100;
int scaledWidth = Math.round(16 * scaleFactor);
int scaledHeight = Math.round(16 * scaleFactor);
return new ImageData(scaledWidth, scaledHeight, 1, new PaletteData(new RGB(255, 0, 0)));
};
Image image = new Image(display, incorrectlyScaledimageDataProvider);
gc.drawImage(image, 0, 0, 16, 16, 0, 0, 16, 16);
gc.dispose();
image.dispose();
}

@Test
public void testImageIconTypeShouldNotChangeAfterCallingGetHandleForDifferentZoom() {
Image icon = Display.getDefault().getSystemImage(SWT.ICON_ERROR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,7 @@ public void drawImage (Image image, int srcX, int srcY, int srcWidth, int srcHei
if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);

int gcZoom = getZoom();
int srcImageZoom = calculateZoomForImage(gcZoom, srcWidth, srcHeight, destWidth, destHeight);
int srcImageZoom = calculateZoomForImage(image, gcZoom, srcWidth, srcHeight, destWidth, destHeight);
drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, gcZoom, srcImageZoom);
}

Expand All @@ -1003,25 +1003,29 @@ private Collection<Integer> getAllCurrentMonitorZooms() {
return Collections.emptySet();
}

private int calculateZoomForImage(int gcZoom, int srcWidth, int srcHeight, int destWidth, int destHeight) {
private int calculateZoomForImage(Image image, int gcZoom, int srcWidth, int srcHeight, int destWidth, int destHeight) {
int scaledImageZoom;
float imageScaleFactor = 1f * destWidth / srcWidth;
int imageZoom = Math.round(gcZoom * imageScaleFactor);
if (srcWidth == 1 && srcHeight == 1) {
// One pixel images can use the GC zoom
return gcZoom;
}
if (destWidth == srcWidth && destHeight == srcHeight) {
scaledImageZoom = gcZoom;
} else if (destWidth == srcWidth && destHeight == srcHeight) {
// unscaled images can use the GC zoom
return gcZoom;
}

float imageScaleFactor = 1f * destWidth / srcWidth;
int imageZoom = Math.round(gcZoom * imageScaleFactor);
if (getAllCurrentMonitorZooms().contains(imageZoom)) {
return imageZoom;
}
if (imageZoom > 150) {
return 200;
}
return 100;
scaledImageZoom = gcZoom;
} else if (getAllCurrentMonitorZooms().contains(imageZoom)) {
scaledImageZoom = imageZoom;
} else if (imageZoom > 150) {
scaledImageZoom = 200;
} else {
scaledImageZoom = 100;
}
Rectangle scaledBounds = image.getBounds(scaledImageZoom);
Rectangle unScaledBound = image.getBounds();
// validates if the image bounds are scaled up correctly as per required zoom, if it is not zoom is returned as per actual scaling factor.
float scalingFactor = (float) scaledBounds.height / unScaledBound.height;
scaledImageZoom = (int) (scalingFactor * 100);
return scaledImageZoom;
}

private void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY,
Expand Down
Loading