|
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 |
@@ -361,7 +362,7 @@ public Image(Device device, ImageData data) { |
361 | 362 | if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
362 | 363 | initialNativeZoom = DPIUtil.getNativeDeviceZoom(); |
363 | 364 | int deviceZoom = getZoom(); |
364 | | - data = DPIUtil.scaleImageData(device, new ElementAtZoom<>(data, 100), deviceZoom); |
| 365 | + data = scaleImageData(device, 100, deviceZoom, data); |
365 | 366 | init(data, deviceZoom); |
366 | 367 | init(); |
367 | 368 | this.device.registerResourceWithZoomSupport(this); |
@@ -405,8 +406,8 @@ public Image(Device device, ImageData source, ImageData mask) { |
405 | 406 | SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
406 | 407 | } |
407 | 408 | initialNativeZoom = DPIUtil.getNativeDeviceZoom(); |
408 | | - source = DPIUtil.autoScaleUp(device, source); |
409 | | - mask = DPIUtil.autoScaleUp(device, mask); |
| 409 | + source = scaleImageData(device, 100, getZoom(), source); |
| 410 | + mask = scaleImageData(device, 100, getZoom(), mask); |
410 | 411 | mask = ImageData.convertMask(mask); |
411 | 412 | initIconHandle(this.device, source, mask, getZoom()); |
412 | 413 | init(); |
@@ -470,7 +471,8 @@ public Image (Device device, InputStream stream) { |
470 | 471 | super(device); |
471 | 472 | initialNativeZoom = DPIUtil.getNativeDeviceZoom(); |
472 | 473 | int deviceZoom = getZoom(); |
473 | | - ImageData data = DPIUtil.scaleImageData(device, ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, deviceZoom), deviceZoom); |
| 474 | + ElementAtZoom<ImageData> imageCandidate = ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, deviceZoom); |
| 475 | + ImageData data = scaleImageData(device, imageCandidate.zoom(), deviceZoom, imageCandidate.element()); |
474 | 476 | init(data, deviceZoom); |
475 | 477 | init(); |
476 | 478 | this.device.registerResourceWithZoomSupport(this); |
@@ -513,7 +515,8 @@ public Image (Device device, String filename) { |
513 | 515 | if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
514 | 516 | initialNativeZoom = DPIUtil.getNativeDeviceZoom(); |
515 | 517 | int deviceZoom = getZoom(); |
516 | | - ImageData data = DPIUtil.scaleImageData(device, ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, deviceZoom), deviceZoom); |
| 518 | + ElementAtZoom<ImageData> imageCandidate = ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, deviceZoom); |
| 519 | + ImageData data = scaleImageData(device, imageCandidate.zoom(), deviceZoom, imageCandidate.element()); |
517 | 520 | init(data, deviceZoom); |
518 | 521 | init(); |
519 | 522 | this.device.registerResourceWithZoomSupport(this); |
@@ -1237,7 +1240,7 @@ private ImageData getScaledImageData (int zoom) { |
1237 | 1240 | } |
1238 | 1241 | TreeSet<Integer> availableZooms = new TreeSet<>(zoomLevelToImageHandle.keySet()); |
1239 | 1242 | int closestZoom = Optional.ofNullable(availableZooms.higher(zoom)).orElse(availableZooms.lower(zoom)); |
1240 | | - return DPIUtil.scaleImageData (device, getImageMetadata(closestZoom).getImageData(), zoom, closestZoom); |
| 1243 | + return scaleImageData(device, closestZoom, zoom, getImageMetadata(closestZoom).getImageData()); |
1241 | 1244 | } |
1242 | 1245 |
|
1243 | 1246 |
|
@@ -1850,6 +1853,41 @@ private void setBackground(Color color, long handle) { |
1850 | 1853 | device.internal_dispose_GC(hDC, null); |
1851 | 1854 | } |
1852 | 1855 |
|
| 1856 | +private ImageData scaleImageData(Device device, int currentZoom, int targetZoom, ImageData imageData) { |
| 1857 | + if (imageData == null || targetZoom == currentZoom || (device != null && !device.isAutoScalable())) return imageData; |
| 1858 | + float scaleFactor = (float) targetZoom / (float) currentZoom; |
| 1859 | + int width = imageData.width; |
| 1860 | + int height = imageData.height; |
| 1861 | + int scaledWidth = Math.round (width * scaleFactor); |
| 1862 | + int scaledHeight = Math.round (height * scaleFactor); |
| 1863 | + boolean useSmoothScaling = DPIUtil.isSmoothScalingEnabled() && imageData.getTransparencyType() != SWT.TRANSPARENCY_MASK; |
| 1864 | + if (useSmoothScaling) { |
| 1865 | + return scaleToUsingSmoothScaling(scaledWidth, scaledHeight, imageData); |
| 1866 | + } else { |
| 1867 | + return imageData.scaledTo (scaledWidth, scaledHeight); |
| 1868 | + } |
| 1869 | +} |
| 1870 | + |
| 1871 | +private ImageData scaleToUsingSmoothScaling(int width, int height, ImageData imageData) { |
| 1872 | + Image original = new Image (Display.getCurrent(), (ImageDataProvider) zoom -> imageData); |
| 1873 | + /* Create a 24 bit image data with alpha channel */ |
| 1874 | + final ImageData resultData = new ImageData (width, height, 24, new PaletteData (0xFF, 0xFF00, 0xFF0000)); |
| 1875 | + resultData.alphaData = new byte [width * height]; |
| 1876 | + Image resultImage = new Image (Display.getCurrent(), (ImageDataProvider) zoom -> resultData); |
| 1877 | + GC gc = new GC (resultImage); |
| 1878 | + gc.setAntialias (SWT.ON); |
| 1879 | + gc.drawImage (original, 0, 0, imageData.width, imageData.height, |
| 1880 | + /* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors. |
| 1881 | + * Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..). |
| 1882 | + */ |
| 1883 | + 0, 0, width, height, false); |
| 1884 | + gc.dispose (); |
| 1885 | + original.dispose (); |
| 1886 | + ImageData result = resultImage.getImageData (resultImage.getZoom()); |
| 1887 | + resultImage.dispose (); |
| 1888 | + return result; |
| 1889 | +} |
| 1890 | + |
1853 | 1891 | private int getZoom() { |
1854 | 1892 | return DPIUtil.getZoomForAutoscaleProperty(initialNativeZoom); |
1855 | 1893 | } |
@@ -2059,7 +2097,7 @@ ImageData getImageData(int zoom) { |
2059 | 2097 |
|
2060 | 2098 | private ImageData scaleIfNecessary(ElementAtZoom<ImageData> imageDataAtZoom, int zoom) { |
2061 | 2099 | if (imageDataAtZoom.zoom() != zoom) { |
2062 | | - return DPIUtil.scaleImageData(device, imageDataAtZoom, zoom); |
| 2100 | + return scaleImageData(device, imageDataAtZoom.zoom(), zoom, imageDataAtZoom.element()); |
2063 | 2101 | } else { |
2064 | 2102 | return imageDataAtZoom.element(); |
2065 | 2103 | } |
@@ -2308,13 +2346,13 @@ protected Rectangle getBounds(int zoom) { |
2308 | 2346 | @Override |
2309 | 2347 | ImageData getImageData(int zoom) { |
2310 | 2348 | ElementAtZoom<ImageData> data = DPIUtil.validateAndGetImageDataAtZoom (provider, zoom); |
2311 | | - return DPIUtil.scaleImageData (device, data.element(), zoom, data.zoom()); |
| 2349 | + return scaleImageData(device, data.zoom(), zoom, data.element()); |
2312 | 2350 | } |
2313 | 2351 |
|
2314 | 2352 | @Override |
2315 | 2353 | ImageHandle getImageMetadata(int zoom) { |
2316 | 2354 | ElementAtZoom<ImageData> imageCandidate = DPIUtil.validateAndGetImageDataAtZoom (provider, zoom); |
2317 | | - ImageData resizedData = DPIUtil.scaleImageData (device, imageCandidate.element(), zoom, imageCandidate.zoom()); |
| 2355 | + ImageData resizedData = scaleImageData(device, imageCandidate.zoom(), zoom, imageCandidate.element()); |
2318 | 2356 | ImageData newData = adaptImageDataIfDisabledOrGray(resizedData); |
2319 | 2357 | init(newData, zoom); |
2320 | 2358 | return zoomLevelToImageHandle.get(zoom); |
|
0 commit comments