Skip to content

Commit 3065112

Browse files
committed
[MacOS] Support loading and drawing images at desired size
With the support of SVGs and the addition of the ImageDataAtSizeProvider, it is possible for many Image instances to provide a handle that represents the image at sharply rendered specific size in addition to the existing support of providing an image at different zooms of a base size. This change adds according support to the MacOS implementations of GC and Image. The GC#drawImage() method accepting only destination position and size now makes use of enhanced Image capabilities to load the image at the desired size if possible instead of just using the best fitting zoomed handle.
1 parent 3122344 commit 3065112

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,9 @@ public void drawImage(Image image, int destX, int destY, int destWidth, int dest
12381238
if (image.isDisposed()) {
12391239
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
12401240
}
1241-
drawImage(image, 0, 0, 0, 0, destX, destY, destWidth, destHeight, false);
1241+
image.executeOnImageAtSizeBestFittingSize(imageAtSize -> {
1242+
drawImage(imageAtSize, 0, 0, imageAtSize.width, imageAtSize.height, destX, destY, destWidth, destHeight, false);
1243+
}, destWidth, destHeight);
12421244
}
12431245

12441246
void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {

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

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package org.eclipse.swt.graphics;
1515

1616

17+
import static org.eclipse.swt.internal.DPIUtil.pointToPixel;
1718
import static org.eclipse.swt.internal.image.ImageColorTransformer.DEFAULT_DISABLED_IMAGE_TRANSFORMER;
1819

1920
import java.io.*;
@@ -1177,6 +1178,7 @@ private NSBitmapImageRep createRepresentation(ImageData imageData, AlphaInfo alp
11771178

11781179
@Override
11791180
void destroy() {
1181+
cachedImageAtSize.destroy();
11801182
if (memGC != null) memGC.dispose();
11811183
handle.release();
11821184
handle = null;
@@ -1837,5 +1839,73 @@ public static void drawAtSize(GC gc, ImageData imageData, int width, int height)
18371839
});
18381840
}
18391841

1842+
void executeOnImageAtSizeBestFittingSize(Consumer<Image> imageAtBestFittingSizeConsumer, int destWidth, int destHeight) {
1843+
Optional<Image> imageAtSize = cachedImageAtSize.refresh(destWidth, destHeight);
1844+
imageAtBestFittingSizeConsumer.accept(imageAtSize.orElse(this));
1845+
}
1846+
1847+
private CachedImageAtSize cachedImageAtSize = new CachedImageAtSize();
1848+
1849+
private class CachedImageAtSize {
1850+
private Image image;
1851+
1852+
public void destroy() {
1853+
if (image != null) {
1854+
image.dispose();
1855+
image = null;
1856+
}
1857+
}
1858+
1859+
private Optional<Image> refresh(int destWidth, int destHeight) {
1860+
int scaledWidth = pointToPixel(destWidth, DPIUtil.getDeviceZoom());
1861+
int scaledHeight = pointToPixel(destHeight, DPIUtil.getDeviceZoom());
1862+
if (isReusable(scaledWidth, scaledHeight)) {
1863+
return Optional.of(image);
1864+
} else {
1865+
destroy();
1866+
Optional<Image> imageAtSize = loadImageAtSize(scaledWidth, scaledHeight);
1867+
image = imageAtSize.orElse(null);
1868+
return imageAtSize;
1869+
}
1870+
}
1871+
1872+
private boolean isReusable(int width, int height) {
1873+
return image != null && image.height == height && image.width == width;
1874+
}
1875+
1876+
private Optional<Image> loadImageAtSize(int destWidth, int destHeight) {
1877+
Optional<ImageData> imageData = loadImageDataAtExactSize(destWidth, destHeight);
1878+
if (imageData.isEmpty()) {
1879+
return Optional.empty();
1880+
}
1881+
Image image = new Image(device, imageData.get());
1882+
if (styleFlag != SWT.IMAGE_COPY) {
1883+
NSBitmapImageRep representation = image.getRepresentation(100);
1884+
image.createRepFromSourceAndApplyFlag(representation, destWidth, destHeight, styleFlag);
1885+
image.handle.removeRepresentation(representation);
1886+
}
1887+
return Optional.of(image);
1888+
}
1889+
1890+
private Optional<ImageData> loadImageDataAtExactSize(int targetWidth, int targetHeight) {
1891+
if (imageDataProvider instanceof ImageDataAtSizeProvider imageDataAtSizeProvider) {
1892+
ImageData imageData = imageDataAtSizeProvider.getImageData(targetWidth, targetHeight);
1893+
if (imageData == null) {
1894+
SWT.error(SWT.ERROR_INVALID_ARGUMENT, null,
1895+
" ImageDataAtSizeProvider returned null for width=" + targetWidth + ", height=" + targetHeight);
1896+
}
1897+
return Optional.of(imageData);
1898+
}
1899+
if (imageFileNameProvider != null) {
1900+
String fileName = DPIUtil.validateAndGetImagePathAtZoom(imageFileNameProvider, 100).element();
1901+
if (ImageDataLoader.isDynamicallySizable(fileName)) {
1902+
ImageData imageDataAtSize = ImageDataLoader.loadBySize(fileName, targetWidth, targetHeight);
1903+
return Optional.of(imageDataAtSize);
1904+
}
1905+
}
1906+
return Optional.empty();
1907+
}
1908+
}
1909+
18401910
}
18411911

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
import org.junit.jupiter.api.AfterEach;
5555
import org.junit.jupiter.api.BeforeEach;
5656
import org.junit.jupiter.api.Test;
57-
import org.junit.jupiter.api.condition.EnabledOnOs;
57+
import org.junit.jupiter.api.condition.DisabledOnOs;
5858
import org.junit.jupiter.api.condition.OS;
5959
import org.junit.jupiter.params.ParameterizedTest;
6060
import org.junit.jupiter.params.provider.ValueSource;
@@ -442,7 +442,7 @@ public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII_ImageDataProvider(
442442
}
443443

444444
@Test
445-
@EnabledOnOs(value = OS.WINDOWS)
445+
@DisabledOnOs(value = OS.LINUX)
446446
public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII_ImageDataAtSizeProvider_invalid() {
447447
ImageDataAtSizeProvider provider = new ImageDataAtSizeProvider() {
448448
@Override
@@ -469,7 +469,7 @@ public ImageData getImageData(int width, int height) {
469469

470470
@ParameterizedTest
471471
@ValueSource(ints = {SWT.IMAGE_COPY, SWT.IMAGE_DISABLE, SWT.IMAGE_GRAY, -1})
472-
@EnabledOnOs(value = OS.WINDOWS)
472+
@DisabledOnOs(value = OS.LINUX)
473473
public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII_ImageDataAtSizeProvider(int styleFlag) {
474474
int width = 50;
475475
int height = 70;

0 commit comments

Comments
 (0)