eclipse-platform / eclipse.platform.swt

Eclipse SWT
https://www.eclipse.org/swt/
Eclipse Public License 2.0
118 stars 137 forks source link

IllegalArgException on Linux with smooth antialiasing enabled #445

Closed mbooth101 closed 2 years ago

mbooth101 commented 2 years ago

Describe the bug

Running on Linux, with a HiDPI screen, with a scaling factor of 2, with smooth anti-aliasing enabled, my application exits with the following error:

java.lang.IllegalArgumentException: Argument not valid
    at org.eclipse.swt.SWT.error(SWT.java:4899)
    at org.eclipse.swt.SWT.error(SWT.java:4833)
    at org.eclipse.swt.SWT.error(SWT.java:4804)
    at org.eclipse.swt.graphics.GC.drawImage(GC.java:873)
    at org.eclipse.swt.graphics.GC.drawImage(GC.java:854)
    at org.eclipse.swt.internal.DPIUtil.autoScaleImageData(DPIUtil.java:243)
    at org.eclipse.swt.internal.DPIUtil.autoScaleUp(DPIUtil.java:279)
    at org.eclipse.swt.graphics.Image.<init>(Image.java:417)
    at org.eclipse.jface.resource.URLImageDescriptor.createImage(URLImageDescriptor.java:260)
    at org.eclipse.jface.resource.ImageDescriptor.createImage(ImageDescriptor.java:290)
    at org.eclipse.jface.resource.ImageDescriptor.createImage(ImageDescriptor.java:268)

To Reproduce

Either use a HiDPI environment with the scaling factor set to 2 (200%) or set GDK_SCALE=2 in the environment.

When running the following snippet, pass the system property -Dswt.autoScale.method=smooth

Run the following snippet, where "gear_icon1.png" is some 16x16 icon, e.g.: gear_icon1

public class ScalingTest2 {

    public static void main(String[] args) throws MalformedURLException {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setSize(100, 100);

        System.out.println("Device Zoom: " + DPIUtil.getDeviceZoom());

        ImageDescriptor desc1x = ImageDescriptor.createFromURL(new URL("file:gear_icon1.png"));
        Image image1x = desc1x.createImage();

        ToolBar bar = new ToolBar(shell, SWT.BORDER | SWT.FLAT);
        Rectangle clientArea = shell.getClientArea();
        bar.setBounds(clientArea.x, clientArea.y, 100, 32);

        ToolItem item1 = new ToolItem(bar, SWT.NONE);
        item1.setImage(image1x);
        item1.setToolTipText("1x");

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        image1x.dispose();
        display.dispose();
    }
}

Screenshots

Default antialiasing With -Dswt.autoScale.method=smooth
Windows 10 windows_default windows_smooth
Linux linux_default java.lang.IllegalArgumentException: Argument not valid
(see stack trace above)

Expected behavior

No crash, the icon should be antialiased when scaled up 2x, similar to the Windows 10 screenshot above.

Environment:

Select the platform(s) on which the behavior is seen:

Fedora 36 GTK version: gtk3-3.24.34-1.fc36.x86_64 Java version: java-17-openjdk-17.0.4.1.1-1.fc36.x86_64 SWT version: git commit 6c09b67 (15th Oct 2022)

Version since

Unknown

Workaround (or) Additional context

Workaround is don't enable smooth antialiasing :-)

mbooth101 commented 2 years ago

Hmm, I have a change that fixes the problem, but I'm not sure why and rather suspect in some other places the incorrectness was being worked around so this caused some visual glitches in other places, still investigating.

Edit: I think I got it, see PR #446