diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java index 1e70b7254c..6ee298079e 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java @@ -913,7 +913,7 @@ public void drawImage(Image image, int destX, int destY, int destWidth, int dest if (image.isDisposed()) { SWT.error(SWT.ERROR_INVALID_ARGUMENT); } - drawImage(image, 0, 0, 0, 0, destX, destY, destWidth, destHeight, false); + image.executeOnImageAtSize(imageAtSize -> drawImage(imageAtSize, 0, 0, 0, 0, destX, destY, destWidth, destHeight, false), destWidth, destHeight); } void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java index ef3648eb67..2640031045 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java @@ -18,6 +18,7 @@ import java.io.*; import java.util.*; +import java.util.function.*; import org.eclipse.swt.*; import org.eclipse.swt.internal.*; @@ -278,16 +279,16 @@ public Image(Device device, Image srcImage, int flag) { if (flag != SWT.IMAGE_DISABLE) transparentPixel = srcImage.transparentPixel; long imageSurface = srcImage.surface; - int width = this.width = srcImage.width; - int height = this.height = srcImage.height; + this.width = srcImage.width; + this.height = srcImage.height; int format = Cairo.cairo_surface_get_content(imageSurface) == Cairo.CAIRO_CONTENT_COLOR ? Cairo.CAIRO_FORMAT_RGB24 : Cairo.CAIRO_FORMAT_ARGB32; boolean hasAlpha = format == Cairo.CAIRO_FORMAT_ARGB32; - surface = Cairo.cairo_image_surface_create(format, width, height); + int dataWidth = DPIUtil.pointToPixel(this.width, DPIUtil.getDeviceZoom()); + int dataHeight= DPIUtil.pointToPixel(this.height, DPIUtil.getDeviceZoom()); + surface = Cairo.cairo_image_surface_create(format, dataWidth, dataHeight); if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES); - if (DPIUtil.getDeviceZoom() != currentDeviceZoom) { - double scaleFactor = DPIUtil.getDeviceZoom() / 100f; - Cairo.cairo_surface_set_device_scale(surface, scaleFactor, scaleFactor); - } + double scaleFactor = DPIUtil.getDeviceZoom() / 100f; + Cairo.cairo_surface_set_device_scale(surface, scaleFactor, scaleFactor); long cairo = Cairo.cairo_create(surface); if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES); Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE); @@ -306,9 +307,9 @@ public Image(Device device, Image srcImage, int flag) { switch (flag) { case SWT.IMAGE_DISABLE: { byte[] line = new byte[stride]; - for (int y=0; y refresh(int destWidth, int destHeight) { + int scaledWidth = DPIUtil.pointToPixel(destWidth, DPIUtil.getDeviceZoom()); + int scaledHeight = DPIUtil.pointToPixel(destHeight, DPIUtil.getDeviceZoom()); + if (isReusable(scaledWidth, scaledHeight)) { + return Optional.of(image); + } else { + destroy(); + Optional imageAtSize = loadImageAtSize(scaledWidth, scaledHeight); + image = imageAtSize.orElse(null); + return imageAtSize; + } + } + + private boolean isReusable(int width, int height) { + return image != null && image.height == height && image.width == width; + } + + private Optional loadImageAtSize(int destWidth, int destHeight) { + Optional imageData = loadImageDataAtExactSize(destWidth, destHeight); + if (imageData.isEmpty()) { + return Optional.empty(); + } + Image image = new Image(device, imageData.get(), DPIUtil.getDeviceZoom()); + if (styleFlag != SWT.IMAGE_COPY) { + Image styledImage = new Image(device, image, styleFlag); + image.dispose(); + image = styledImage; + } + return Optional.of(image); + } + + private Optional loadImageDataAtExactSize(int targetWidth, int targetHeight) { + if (imageDataProvider instanceof ImageDataAtSizeProvider imageDataAtSizeProvider) { + ImageData imageData = imageDataAtSizeProvider.getImageData(targetWidth, targetHeight); + if (imageData == null) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, + " ImageDataAtSizeProvider returned null for width=" + targetWidth + ", height=" + targetHeight); + } + return Optional.of(imageData); + } + if (imageFileNameProvider != null) { + String fileName = DPIUtil.validateAndGetImagePathAtZoom(imageFileNameProvider, 100).element(); + if (ImageDataLoader.isDynamicallySizable(fileName)) { + ImageData imageDataAtSize = ImageDataLoader.loadBySize(fileName, targetWidth, targetHeight); + return Optional.of(imageDataAtSize); + } + } + return Optional.empty(); + } +} + +void executeOnImageAtSize(Consumer imageAtBestFittingSizeConsumer, int destWidth, int destHeight) { + Optional imageAtSize = cachedImageAtSize.refresh(destWidth, destHeight); + imageAtBestFittingSizeConsumer.accept(imageAtSize.orElse(this)); +} + /** * Compares the argument to the receiver, and returns true * if they represent the same object using a class diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java index 2e40ee0034..dfb764d5a9 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java @@ -54,8 +54,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -442,7 +440,6 @@ public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII_ImageDataProvider( } @Test -@DisabledOnOs(value = OS.LINUX) public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII_ImageDataAtSizeProvider_invalid() { ImageDataAtSizeProvider provider = new ImageDataAtSizeProvider() { @Override @@ -469,11 +466,10 @@ public ImageData getImageData(int width, int height) { @ParameterizedTest @ValueSource(ints = {SWT.IMAGE_COPY, SWT.IMAGE_DISABLE, SWT.IMAGE_GRAY, -1}) -@DisabledOnOs(value = OS.LINUX) public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII_ImageDataAtSizeProvider(int styleFlag) { int width = 50; int height = 70; - Image drawToImage = new Image(display, width, height); + Image drawToImage = new Image(display, new ImageData(width, height, 32, new PaletteData(0xFF0000, 0xFF00, 0xFF))); GC gc = new GC(drawToImage); gc.setAntialias(SWT.OFF); RGB drawnRgb = new RGB(255, 255, 255);