Describe the bug
Trying to paint an image while all available handles have been consumed fails with an IllegalArgumentException instead of an SWTError.
To Reproduce
package gef;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class DrawGC2 {
public static void main(String[] args) {
Shell shell = new Shell();
Display display = shell.getDisplay();
int width = 310;
int height = 310;
List<Image> images = new ArrayList<>();
for (int i = 0; i < 8000; ++i) {
Image image = new Image(display, width, height);
GC gc = new GC(image);
gc.dispose();
images.add(image);
}
shell.addPaintListener(event -> {
for (Image image : images) {
event.gc.drawImage(image, 0, 0, width, height, 0, 0, 100, 100);
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
images.forEach(Image::dispose);
}
}
Stacktrace:
Exception in thread "main" java.lang.IllegalArgumentException: Argument not valid
at org.eclipse.swt.SWT.error(SWT.java:4915)
at org.eclipse.swt.SWT.error(SWT.java:4849)
at org.eclipse.swt.SWT.error(SWT.java:4820)
at org.eclipse.swt.graphics.ImageData.<init>(ImageData.java:439)
at org.eclipse.swt.graphics.ImageData.<init>(ImageData.java:287)
at org.eclipse.swt.graphics.Image$DestroyableImageHandle.getImageData(Image.java:3305)
at org.eclipse.swt.graphics.Image$AbstractImageProviderWrapper.getClosestAvailableImageData(Image.java:2106)
at org.eclipse.swt.graphics.Image$PlainImageProviderWrapper.loadImageData(Image.java:2388)
at org.eclipse.swt.graphics.Image$HandleAtSize.getOrCreateImageHandleAtClosestSize(Image.java:254)
at org.eclipse.swt.graphics.Image$HandleAtSize.lambda$0(Image.java:225)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.eclipse.swt.graphics.Image$HandleAtSize.refresh(Image.java:225)
at org.eclipse.swt.graphics.Image.executeOnImageHandleAtBestFittingSize(Image.java:968)
at org.eclipse.swt.graphics.GC$DrawScalingImageToImageOperation.draw(GC.java:1240)
at org.eclipse.swt.graphics.GC$DrawScalingImageToImageOperation.apply(GC.java:1222)
at org.eclipse.swt.graphics.GC.storeAndApplyOperationForExistingHandle(GC.java:6136)
at org.eclipse.swt.graphics.GC.drawImage(GC.java:1152)
at gef.DrawGC2.lambda$0(DrawGC2.java:30)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:272)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4363)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1217)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1241)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1226)
at org.eclipse.swt.widgets.Composite.WM_PAINT(Composite.java:1627)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:5021)
at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:336)
at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1490)
at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2446)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:5131)
at org.eclipse.swt.internal.win32.OS.UpdateWindow(Native Method)
at org.eclipse.swt.widgets.Decorations.setVisible(Decorations.java:1322)
at org.eclipse.swt.widgets.Shell.setVisible(Shell.java:2192)
at org.eclipse.swt.widgets.Shell.open(Shell.java:1334)
at gef.DrawGC2.main(DrawGC2.java:34)
Expected behavior
SWT should return a proper error message. Ideally an "No more handles" error.
Environment:
- Select the platform(s) on which the behavior is seen:
Version since
Only tested on master.
Additional information
I think the problem is that the return value is not validated when calling GetDIBits, for example here:
|
/* Call with null lpBits to get the image size */ |
|
OS.GetDIBits(hBitmapDC, handle(), 0, height, null, bmi, OS.DIB_RGB_COLORS); |
|
OS.MoveMemory(bmiHeader, bmi, BITMAPINFOHEADER.sizeof); |
|
imageSize = bmiHeader.biSizeImage; |
From the documentation:
If the function fails, the return value is zero.
Which is the case here, resulting in an "empty" image data, causing the validation error.
Describe the bug
Trying to paint an image while all available handles have been consumed fails with an
IllegalArgumentExceptioninstead of anSWTError.To Reproduce
Stacktrace:
Expected behavior
SWT should return a proper error message. Ideally an "No more handles" error.
Environment:
Version since
Only tested on master.
Additional information
I think the problem is that the return value is not validated when calling
GetDIBits, for example here:eclipse.platform.swt/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
Lines 3254 to 3257 in 725c948
From the documentation:
Which is the case here, resulting in an "empty" image data, causing the validation error.