|
23 | 23 | import org.eclipse.swt.internal.gdip.*; |
24 | 24 | import org.eclipse.swt.internal.image.*; |
25 | 25 | import org.eclipse.swt.internal.win32.*; |
| 26 | +import org.eclipse.swt.widgets.*; |
26 | 27 |
|
27 | 28 | /** |
28 | 29 | * Instances of this class are graphics which have been prepared |
@@ -372,7 +373,7 @@ public Image(Device device, ImageData data) { |
372 | 373 | if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
373 | 374 | initialNativeZoom = DPIUtil.getNativeDeviceZoom(); |
374 | 375 | int deviceZoom = getZoom(); |
375 | | - data = DPIUtil.scaleImageData(device, new ElementAtZoom<>(data, 100), deviceZoom); |
| 376 | + data = scaleImageData(device, 100, deviceZoom, data); |
376 | 377 | init(data, deviceZoom); |
377 | 378 | init(); |
378 | 379 | this.device.registerResourceWithZoomSupport(this); |
@@ -416,8 +417,8 @@ public Image(Device device, ImageData source, ImageData mask) { |
416 | 417 | SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
417 | 418 | } |
418 | 419 | initialNativeZoom = DPIUtil.getNativeDeviceZoom(); |
419 | | - source = DPIUtil.autoScaleUp(device, source); |
420 | | - mask = DPIUtil.autoScaleUp(device, mask); |
| 420 | + source = scaleImageData(device, 100, getZoom(), source); |
| 421 | + mask = scaleImageData(device, 100, getZoom(), mask); |
421 | 422 | mask = ImageData.convertMask(mask); |
422 | 423 | initIconHandle(this.device, source, mask, getZoom()); |
423 | 424 | init(); |
@@ -481,7 +482,8 @@ public Image (Device device, InputStream stream) { |
481 | 482 | super(device); |
482 | 483 | initialNativeZoom = DPIUtil.getNativeDeviceZoom(); |
483 | 484 | int deviceZoom = getZoom(); |
484 | | - ImageData data = DPIUtil.scaleImageData(device, ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, deviceZoom), deviceZoom); |
| 485 | + ElementAtZoom<ImageData> imageCandidate = ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, deviceZoom); |
| 486 | + ImageData data = scaleImageData(device, imageCandidate.zoom(), deviceZoom, imageCandidate.element()); |
485 | 487 | init(data, deviceZoom); |
486 | 488 | init(); |
487 | 489 | this.device.registerResourceWithZoomSupport(this); |
@@ -524,7 +526,8 @@ public Image (Device device, String filename) { |
524 | 526 | if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
525 | 527 | initialNativeZoom = DPIUtil.getNativeDeviceZoom(); |
526 | 528 | int deviceZoom = getZoom(); |
527 | | - ImageData data = DPIUtil.scaleImageData(device, ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, deviceZoom), deviceZoom); |
| 529 | + ElementAtZoom<ImageData> imageCandidate = ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, deviceZoom); |
| 530 | + ImageData data = scaleImageData(device, imageCandidate.zoom(), deviceZoom, imageCandidate.element()); |
528 | 531 | init(data, deviceZoom); |
529 | 532 | init(); |
530 | 533 | this.device.registerResourceWithZoomSupport(this); |
@@ -1264,7 +1267,7 @@ private ImageData getScaledImageData (int zoom) { |
1264 | 1267 | } |
1265 | 1268 | TreeSet<Integer> availableZooms = new TreeSet<>(zoomLevelToImageHandle.keySet()); |
1266 | 1269 | int closestZoom = Optional.ofNullable(availableZooms.higher(zoom)).orElse(availableZooms.lower(zoom)); |
1267 | | - return DPIUtil.scaleImageData (device, getImageMetadata(closestZoom).getImageData(), zoom, closestZoom); |
| 1270 | + return scaleImageData(device, closestZoom, zoom, getImageMetadata(closestZoom).getImageData()); |
1268 | 1271 | } |
1269 | 1272 |
|
1270 | 1273 |
|
@@ -1854,6 +1857,41 @@ public void setBackground(Color color) { |
1854 | 1857 | zoomLevelToImageHandle.values().forEach(imageHandle -> imageHandle.setBackground(backgroundColor)); |
1855 | 1858 | } |
1856 | 1859 |
|
| 1860 | +private ImageData scaleImageData(Device device, int currentZoom, int targetZoom, ImageData imageData) { |
| 1861 | + if (imageData == null || targetZoom == currentZoom || (device != null && !device.isAutoScalable())) return imageData; |
| 1862 | + float scaleFactor = (float) targetZoom / (float) currentZoom; |
| 1863 | + int width = imageData.width; |
| 1864 | + int height = imageData.height; |
| 1865 | + int scaledWidth = Math.round (width * scaleFactor); |
| 1866 | + int scaledHeight = Math.round (height * scaleFactor); |
| 1867 | + boolean useSmoothScaling = DPIUtil.isSmoothScalingEnabled() && imageData.getTransparencyType() != SWT.TRANSPARENCY_MASK; |
| 1868 | + if (useSmoothScaling) { |
| 1869 | + return scaleToUsingSmoothScaling(scaledWidth, scaledHeight, imageData); |
| 1870 | + } else { |
| 1871 | + return imageData.scaledTo (scaledWidth, scaledHeight); |
| 1872 | + } |
| 1873 | +} |
| 1874 | + |
| 1875 | +private ImageData scaleToUsingSmoothScaling(int width, int height, ImageData imageData) { |
| 1876 | + Image original = new Image (Display.getCurrent(), (ImageDataProvider) zoom -> imageData); |
| 1877 | + /* Create a 24 bit image data with alpha channel */ |
| 1878 | + final ImageData resultData = new ImageData (width, height, 24, new PaletteData (0xFF, 0xFF00, 0xFF0000)); |
| 1879 | + resultData.alphaData = new byte [width * height]; |
| 1880 | + Image resultImage = new Image (Display.getCurrent(), (ImageDataProvider) zoom -> resultData); |
| 1881 | + GC gc = new GC (resultImage); |
| 1882 | + gc.setAntialias (SWT.ON); |
| 1883 | + gc.drawImage (original, 0, 0, imageData.width, imageData.height, |
| 1884 | + /* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors. |
| 1885 | + * Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..). |
| 1886 | + */ |
| 1887 | + 0, 0, width, height, false); |
| 1888 | + gc.dispose (); |
| 1889 | + original.dispose (); |
| 1890 | + ImageData result = resultImage.getImageData (resultImage.getZoom()); |
| 1891 | + resultImage.dispose (); |
| 1892 | + return result; |
| 1893 | +} |
| 1894 | + |
1857 | 1895 | private int getZoom() { |
1858 | 1896 | return DPIUtil.getZoomForAutoscaleProperty(initialNativeZoom); |
1859 | 1897 | } |
@@ -2073,7 +2111,7 @@ ImageData getImageData(int zoom) { |
2073 | 2111 |
|
2074 | 2112 | private ImageData scaleIfNecessary(ElementAtZoom<ImageData> imageDataAtZoom, int zoom) { |
2075 | 2113 | if (imageDataAtZoom.zoom() != zoom) { |
2076 | | - return DPIUtil.scaleImageData(device, imageDataAtZoom, zoom); |
| 2114 | + return scaleImageData(device, imageDataAtZoom.zoom(), zoom, imageDataAtZoom.element()); |
2077 | 2115 | } else { |
2078 | 2116 | return imageDataAtZoom.element(); |
2079 | 2117 | } |
@@ -2298,13 +2336,13 @@ private class ImageDataProviderWrapper extends BaseImageProviderWrapper<ImageDat |
2298 | 2336 | @Override |
2299 | 2337 | ImageData getImageData(int zoom) { |
2300 | 2338 | ElementAtZoom<ImageData> data = DPIUtil.validateAndGetImageDataAtZoom (provider, zoom); |
2301 | | - return DPIUtil.scaleImageData (device, data.element(), zoom, data.zoom()); |
| 2339 | + return scaleImageData(device, data.zoom(), zoom, data.element()); |
2302 | 2340 | } |
2303 | 2341 |
|
2304 | 2342 | @Override |
2305 | 2343 | ImageHandle getImageMetadata(int zoom) { |
2306 | 2344 | ElementAtZoom<ImageData> imageCandidate = DPIUtil.validateAndGetImageDataAtZoom (provider, zoom); |
2307 | | - ImageData resizedData = DPIUtil.scaleImageData (device, imageCandidate.element(), zoom, imageCandidate.zoom()); |
| 2345 | + ImageData resizedData = scaleImageData(device, imageCandidate.zoom(), zoom, imageCandidate.element()); |
2308 | 2346 | ImageData newData = adaptImageDataIfDisabledOrGray(resizedData); |
2309 | 2347 | init(newData, zoom); |
2310 | 2348 | return zoomLevelToImageHandle.get(zoom); |
|
0 commit comments