When a `Scene` or `SubScene` has its width or height set to 0, coordinate
transformations stop working because the transformation matrix contains NaNs.
This is a consequence of divisions by zero in both parallel and perspective
projections.
Even though a 0x0 scene is mathematically degenerate, it is still desirable for
coordinate transformation APIs to remain numerically well-behaved and return
finite results whenever possible, rather than being poisoned by NaN/Infinity.
Here is an application that demonstrates the failing coordinate
transformations. Click on the buttons to resize the SubScene and observe the
console output. After applying the patch in this PR, you should observe that
`localToScreen()` no longer returns NaN.
public class ZeroSizeSubScene extends Application {
@Override
public void start(Stage stage) {
var rect = new Rectangle(50, 50, Color.RED);
var subScene = new SubScene(new Group(rect), 100, 100);
subScene.setFill(Color.GRAY);
// Also try a perspective camera:
//
// var camera = new PerspectiveCamera();
// camera.setRotate(45);
// camera.setTranslateX(-20);
// camera.setRotationAxis(new Point3D(0, 1, 0));
// subScene.setCamera(camera);
class MyButton extends Button {
public MyButton(String text, double width, double height) {
super(text);
setOnAction(_ -> {
var timeline = new Timeline(
new KeyFrame(Duration.seconds(1), new
KeyValue(subScene.widthProperty(), width)),
new KeyFrame(Duration.seconds(1), new
KeyValue(subScene.heightProperty(), height)));
timeline.setOnFinished(_ -> {
Point2D p0 = rect.localToScreen(0, 0);
System.out.println("rect.localToScreen(0, 0) = " + p0);
});
timeline.play();
});
}
}
VBox.setMargin(subScene, new Insets(0, 0, 20, 0));
var root = new VBox(5,
subScene,
new CheckBox("Rotate SubScene") {{ setOnAction(_ ->
subScene.setRotate(isSelected() ? 45 : 0)); }},
new MyButton("Size: 100x100", 100, 100),
new MyButton("Size: 10x10", 10, 10),
new MyButton("Size: 100x0", 100, 0),
new MyButton("Size: 0x100", 0, 100),
new MyButton("Size: 0x0", 0, 0)
);
Scene scene = new Scene(root, 300, 300);
stage.setScene(scene);
stage.show();
}
}
-------------
Commit messages:
- TestScene
- Prevent degenerate viewport for zero-size Scene/SubScene
Changes: https://git.openjdk.org/jfx/pull/1992/files
Webrev: https://webrevs.openjdk.org/?repo=jfx&pr=1992&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8372761
Stats: 163 lines in 3 files changed: 103 ins; 16 del; 44 mod
Patch: https://git.openjdk.org/jfx/pull/1992.diff
Fetch: git fetch https://git.openjdk.org/jfx.git pull/1992/head:pull/1992
PR: https://git.openjdk.org/jfx/pull/1992