Skip to content

Commit 0a55729

Browse files
committed
Fix stack overflow in DPIUtil.autoScaleImageData due to
ImageDataProvider zoom handling In PR eclipse-platform#2249, a strict check was introduced that ImageData should be linearly scaled for other zoom levels. And imageDataProviders in SWT repo not following this strict checks were modified (eg to return only imageData at 100%). However, this change broke DPIUtil.autoScaleImageData. That function creates an Image using the system zoom level, draws it on a GC at scaled dimensions, and then requests ImageData at 100% zoom from the image. Since the ImageDataProvider was now restricted to 100% zoom only, requesting imageData at other zoom levels while creating an image at system zoom level triggered recursive calls, causing a stack overflow error. The current commit reverts the behavior of the ImageDataProvider used in DPIUtil.autoScaleImageData to return the same ImageData at all zoom levels. We also Disable the strict zoom check in this specific case, because the scaling is done by GC.drawImage() and the ImageData used to create the is expected to be same.
1 parent ebcb6b9 commit 0a55729

File tree

4 files changed

+25
-15
lines changed

4 files changed

+25
-15
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,22 +1811,26 @@ public String toString () {
18111811
* API for Image. It is marked public only so that it
18121812
* can be shared within the packages provided by SWT.
18131813
*
1814-
* Draws a scaled image using the GC by another image.
1814+
* Draws a scaled image using the GC for a given imageData.
18151815
*
18161816
* @param gc the GC to draw on the resulting image
1817-
* @param original the image which is supposed to be scaled and drawn on the resulting image
1817+
* @param imageData the imageData which is used to draw the scaled Image
18181818
* @param width the width of the original image
18191819
* @param height the height of the original image
18201820
* @param scaleFactor the factor with which the image is supposed to be scaled
18211821
*
18221822
* @noreference This method is not intended to be referenced by clients.
18231823
*/
1824-
public static void drawScaled(GC gc, Image original, int width, int height, float scaleFactor) {
1825-
gc.drawImage (original, 0, 0, CocoaDPIUtil.pixelToPoint (width), CocoaDPIUtil.pixelToPoint (height),
1824+
public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) {
1825+
boolean strictCheckValue = Device.strictChecks;
1826+
Device.strictChecks = false;
1827+
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
1828+
gc.drawImage (imageToDraw, 0, 0, CocoaDPIUtil.pixelToPoint (width), CocoaDPIUtil.pixelToPoint (height),
18261829
/* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors.
18271830
* Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..).
18281831
*/
18291832
0, 0, Math.round (CocoaDPIUtil.pixelToPoint (width * scaleFactor)), Math.round (CocoaDPIUtil.pixelToPoint (height * scaleFactor)));
1833+
Device.strictChecks = strictCheckValue;
18301834
}
18311835

18321836
private final class CocoaDPIUtil {

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,11 @@ public static ImageData autoScaleImageData (Device device, final ImageData image
153153
int defaultZoomLevel = 100;
154154
boolean useSmoothScaling = isSmoothScalingEnabled() && imageData.getTransparencyType() != SWT.TRANSPARENCY_MASK;
155155
if (useSmoothScaling) {
156-
Image original = new Image(device, (ImageDataProvider) zoom -> (zoom == defaultZoomLevel) ? imageData : null);
157156
ImageGcDrawer drawer = new ImageGcDrawer() {
158157
@Override
159158
public void drawOn(GC gc, int imageWidth, int imageHeight) {
160159
gc.setAntialias (SWT.ON);
161-
Image.drawScaled(gc, original, width, height, scaleFactor);
160+
Image.drawScaled(gc, imageData, width, height, scaleFactor);
162161
};
163162

164163
@Override
@@ -168,7 +167,6 @@ public int getGcStyle() {
168167
};
169168
Image resultImage = new Image (device, drawer, scaledWidth, scaledHeight);
170169
ImageData result = resultImage.getImageData (defaultZoomLevel);
171-
original.dispose ();
172170
resultImage.dispose ();
173171
return result;
174172
} else {

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,22 +1574,26 @@ public String toString () {
15741574
* API for Image. It is marked public only so that it
15751575
* can be shared within the packages provided by SWT.
15761576
*
1577-
* Draws a scaled image using the GC by another image.
1577+
* Draws a scaled image using the GC for a given imageData.
15781578
*
15791579
* @param gc the GC to draw on the resulting image
1580-
* @param original the image which is supposed to be scaled and drawn on the resulting image
1580+
* @param imageData the imageData which is used to draw the scaled Image
15811581
* @param width the width of the original image
15821582
* @param height the height of the original image
15831583
* @param scaleFactor the factor with which the image is supposed to be scaled
15841584
*
15851585
* @noreference This method is not intended to be referenced by clients.
15861586
*/
1587-
public static void drawScaled(GC gc, Image original, int width, int height, float scaleFactor) {
1588-
gc.drawImage (original, 0, 0, width, height,
1587+
public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) {
1588+
boolean originalStrictChecks = Device.strictChecks;
1589+
Device.strictChecks = false;
1590+
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
1591+
gc.drawImage (imageToDraw, 0, 0, width, height,
15891592
/* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors.
15901593
* Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..).
15911594
*/
15921595
0, 0, Math.round (width * scaleFactor), Math.round (height * scaleFactor));
1596+
Device.strictChecks = originalStrictChecks;
15931597
}
15941598

15951599
private final class GtkDPIUtil {

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -839,19 +839,23 @@ public static long win32_getHandle (Image image, int zoom) {
839839
* API for Image. It is marked public only so that it
840840
* can be shared within the packages provided by SWT.
841841
*
842-
* Draws a scaled image using the GC by another image.
842+
* Draws a scaled image using the GC for a given imageData.
843843
*
844844
* @param gc the GC to draw on the resulting image
845-
* @param original the image which is supposed to be scaled and drawn on the resulting image
845+
* @param imageData the imageData which is used to draw the scaled Image
846846
* @param width the width of the original image
847847
* @param height the height of the original image
848848
* @param scaleFactor the factor with which the image is supposed to be scaled
849849
*
850850
* @noreference This method is not intended to be referenced by clients.
851851
*/
852-
public static void drawScaled(GC gc, Image original, int width, int height, float scaleFactor) {
853-
gc.drawImage (original, 0, 0, width, height,
852+
public static void drawScaled(GC gc, ImageData imageData, int width, int height, float scaleFactor) {
853+
boolean originalStrictChecks = Device.strictChecks;
854+
Device.strictChecks = false;
855+
Image imageToDraw = new Image(gc.device, (ImageDataProvider) zoom -> imageData);
856+
gc.drawImage (imageToDraw, 0, 0, width, height,
854857
0, 0, Math.round (width * scaleFactor), Math.round (height * scaleFactor), false);
858+
Device.strictChecks = originalStrictChecks;
855859
}
856860

857861
long [] createGdipImage(Integer zoom) {

0 commit comments

Comments
 (0)